#!/bin/bash
# Cortiva Node Installer
# https://install.cortiva.dev
#
# Usage:
#   curl -fsSL https://install.cortiva.dev | bash
#   curl -fsSL https://install.cortiva.dev | bash -s -- --key ctv_node_xxx
#   curl -fsSL https://install.cortiva.dev | bash -s -- --dry-run
set -e

# --- Args ---

DRY_RUN=false
PAIRING_KEY=""
while [ $# -gt 0 ]; do
    case "$1" in
        --dry-run) DRY_RUN=true; shift ;;
        --key) PAIRING_KEY="$2"; shift 2 ;;
        --key=*) PAIRING_KEY="${1#*=}"; shift ;;
        *) shift ;;
    esac
done

# --- Colours & helpers ---

BOLD="\033[1m"
DIM="\033[2m"
RESET="\033[0m"
GREEN="\033[32m"
RED="\033[31m"
YELLOW="\033[33m"
CYAN="\033[36m"
MAGENTA="\033[35m"

ok()   { printf "  ${GREEN}✓${RESET} %s\n" "$*"; }
fail() { printf "  ${RED}✗${RESET} %s\n" "$*"; }
warn() { printf "  ${YELLOW}○${RESET} %s\n" "$*"; }
info() { printf "  ${DIM}%s${RESET}\n" "$*"; }

step() {
    printf "\n${BOLD}${CYAN}▸ %s${RESET}\n" "$*"
}

run_or_dry() {
    if [ "$DRY_RUN" = true ]; then
        info "[dry run] $*"
    else
        eval "$@"
    fi
}

spin_install() {
    local name="$1"
    local check_cmd="$2"
    local install_cmd="$3"
    local version_cmd="$4"

    if eval "$check_cmd" &>/dev/null; then
        local version
        version=$(eval "$version_cmd" 2>/dev/null || echo "")
        if [ -n "$version" ]; then
            printf "  ${GREEN}✓${RESET} %s ${DIM}(%s)${RESET}\n" "$name" "$version"
        else
            ok "$name"
        fi
    else
        if [ "$DRY_RUN" = true ]; then
            warn "$name — would install"
        else
            printf "  ${YELLOW}◌${RESET} %s — installing..." "$name"
            if eval "$install_cmd" >/dev/null 2>&1; then
                local version
                version=$(eval "$version_cmd" 2>/dev/null || echo "")
                printf "\r  ${GREEN}✓${RESET} %s ${DIM}(%s)${RESET}          \n" "$name" "$version"
            else
                printf "\r  ${RED}✗${RESET} %s — install failed          \n" "$name"
                return 1
            fi
        fi
    fi
}

# --- Banner ---

printf "\n"
printf "  ${MAGENTA}${BOLD}cortiva${RESET}\n"
printf "  ${DIM}Node Installer${RESET}\n"
printf "  ${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n"

if [ "$DRY_RUN" = true ]; then
    printf "\n  ${YELLOW}${BOLD}DRY RUN${RESET} ${DIM}— no changes will be made${RESET}\n"
fi

# --- Platform detection ---

step "Checking platform"

OS="$(uname -s)"
ARCH="$(uname -m)"

case "$OS" in
    Darwin)
        MACOS_VERSION=$(sw_vers -productVersion 2>/dev/null || echo "0")
        MACOS_MAJOR=$(echo "$MACOS_VERSION" | cut -d. -f1)
        if [ "$MACOS_MAJOR" -lt 13 ] 2>/dev/null; then
            fail "macOS $MACOS_VERSION — minimum required: macOS 13 (Ventura)"
            exit 1
        fi
        ok "macOS $MACOS_VERSION ($ARCH)"
        ;;
    Linux)
        if [ -f /etc/os-release ]; then
            DISTRO=$(. /etc/os-release && echo "$PRETTY_NAME")
        else
            DISTRO="Linux"
        fi
        ok "$DISTRO ($ARCH)"
        ;;
    *)
        fail "Unsupported OS: $OS"
        info "See https://docs.cortiva.dev/getting-started/install"
        exit 1
        ;;
esac

# Disk space
if [ "$OS" = "Darwin" ]; then
    FREE_KB=$(df -k / | tail -1 | awk '{print $4}')
else
    FREE_KB=$(df -k / | tail -1 | awk '{print $4}')
fi
FREE_GB=$((FREE_KB / 1024 / 1024))
if [ "$FREE_GB" -lt 10 ]; then
    fail "Only ${FREE_GB}GB free — minimum 10GB required"
    exit 1
fi
ok "${FREE_GB}GB free disk space"

# --- Dependencies ---

step "Installing dependencies"

if [ "$OS" = "Darwin" ]; then
    spin_install \
        "Xcode CLT" \
        "xcode-select -p" \
        "xcode-select --install 2>/dev/null; echo 'Complete the Xcode CLT install dialog, then press Enter'; read" \
        "xcode-select --version"

    spin_install \
        "Homebrew" \
        "command -v brew" \
        'NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"' \
        "brew --version | head -1"

    spin_install \
        "Python 3.11+" \
        "python3 -c 'import sys; assert sys.version_info >= (3, 11)'" \
        "HOMEBREW_NO_AUTO_UPDATE=1 brew install python@3.13" \
        "python3 --version"

    spin_install \
        "Node.js" \
        "command -v node" \
        "HOMEBREW_NO_AUTO_UPDATE=1 brew install node" \
        "node --version"

    spin_install \
        "Ollama" \
        "command -v ollama" \
        "HOMEBREW_NO_AUTO_UPDATE=1 brew install ollama" \
        "ollama --version 2>&1 | head -1"

elif [ "$OS" = "Linux" ]; then
    if command -v apt-get &>/dev/null; then
        PKG_MGR="apt"
        PKG_INSTALL="sudo apt-get install -y -qq"
    elif command -v dnf &>/dev/null; then
        PKG_MGR="dnf"
        PKG_INSTALL="sudo dnf install -y -q"
    elif command -v pacman &>/dev/null; then
        PKG_MGR="pacman"
        PKG_INSTALL="sudo pacman -S --noconfirm --quiet"
    else
        fail "No supported package manager found (apt, dnf, pacman)"
        exit 1
    fi
    ok "Package manager: $PKG_MGR"

    spin_install \
        "Python 3.11+" \
        "python3 -c 'import sys; assert sys.version_info >= (3, 11)'" \
        "$PKG_INSTALL python3 python3-pip python3-venv" \
        "python3 --version"

    spin_install \
        "Node.js" \
        "command -v node" \
        "$PKG_INSTALL nodejs npm" \
        "node --version"

    spin_install \
        "Ollama" \
        "command -v ollama" \
        "curl -fsSL https://ollama.ai/install.sh | sh" \
        "ollama --version 2>&1 | head -1"
fi

if command -v claude &>/dev/null; then
    ok "Claude Code CLI"
else
    warn "Claude Code CLI — not found ${DIM}(optional: npm i -g @anthropic-ai/claude-code)${RESET}"
fi

# --- Install Cortiva ---

step "Installing Cortiva"

if pip3 show cortiva &>/dev/null; then
    current=$(pip3 show cortiva 2>/dev/null | grep Version | cut -d' ' -f2)
    printf "  ${YELLOW}◌${RESET} Cortiva ($current) — checking for updates..."
    run_or_dry "pip3 install --upgrade cortiva cortiva-hq-agent --break-system-packages -q 2>/dev/null"
    if [ "$DRY_RUN" = false ]; then
        new=$(pip3 show cortiva 2>/dev/null | grep Version | cut -d' ' -f2)
        if [ "$current" != "$new" ]; then
            printf "\r  ${GREEN}✓${RESET} Cortiva upgraded: $current → $new          \n"
        else
            printf "\r  ${GREEN}✓${RESET} Cortiva is up to date ($current)          \n"
        fi
    else
        printf "\n"
    fi
else
    printf "  ${YELLOW}◌${RESET} Cortiva — installing..."
    run_or_dry "pip3 install cortiva cortiva-hq-agent --break-system-packages -q 2>/dev/null"
    if [ "$DRY_RUN" = false ]; then
        ver=$(pip3 show cortiva 2>/dev/null | grep Version | cut -d' ' -f2)
        printf "\r  ${GREEN}✓${RESET} Cortiva installed ($ver)          \n"
    else
        printf "\n"
    fi
fi

# --- Service user ---

step "Configuring system"

if [ "$OS" = "Darwin" ]; then
    if id "cortiva" &>/dev/null; then
        ok "cortiva user"
    else
        if [ "$DRY_RUN" = true ]; then
            warn "cortiva user — would create"
        else
            printf "  ${YELLOW}◌${RESET} Creating cortiva user..."
            sudo sysadminctl -addUser cortiva -fullName "Cortiva Agent" \
                -password "$(openssl rand -base64 32)" -home /Users/cortiva 2>/dev/null
            printf "\r  ${GREEN}✓${RESET} cortiva user — created          \n"
        fi
    fi
elif [ "$OS" = "Linux" ]; then
    if id "cortiva" &>/dev/null; then
        ok "cortiva user"
    else
        if [ "$DRY_RUN" = true ]; then
            warn "cortiva user — would create"
        else
            printf "  ${YELLOW}◌${RESET} Creating cortiva user..."
            sudo useradd -r -m -s /bin/bash -d /home/cortiva cortiva
            printf "\r  ${GREEN}✓${RESET} cortiva user — created          \n"
        fi
    fi
fi

# --- Existing configuration ---

CORTIVA_HOME="/Users/cortiva"
[ "$OS" = "Linux" ] && CORTIVA_HOME="/home/cortiva"
CONFIG_FILE="$CORTIVA_HOME/.cortiva/config.yaml"
DO_PAIR=true

if [ -f "$CONFIG_FILE" ]; then
    warn "Existing configuration found"
    if [ "$DRY_RUN" = true ]; then
        info "[dry run] Would prompt: keep/fresh/skip"
        DO_PAIR=true
    else
        echo ""
        info "Would you like to:"
        info "  [k] Keep existing config and re-register"
        info "  [f] Fresh install (backs up existing config)"
        info "  [s] Skip pairing"
        read -rp "    Choice [k/f/s]: " choice

        case "$choice" in
            f)
                backup_dir="$CORTIVA_HOME/.cortiva/backup-$(date +%Y%m%d-%H%M%S)"
                sudo -u cortiva mkdir -p "$backup_dir"
                sudo -u cortiva cp "$CONFIG_FILE" "$backup_dir/"
                [ -d "$CORTIVA_HOME/agents" ] && sudo -u cortiva cp -r "$CORTIVA_HOME/agents" "$backup_dir/"
                ok "Config backed up to $backup_dir"
                DO_PAIR=true
                ;;
            s)
                ok "Keeping existing configuration"
                DO_PAIR=false
                ;;
            *)
                DO_PAIR=true
                ;;
        esac
    fi
fi

# --- Pairing ---

if [ "$DO_PAIR" = true ]; then
    step "Pairing with Cortiva HQ"

    if [ "$DRY_RUN" = true ]; then
        info "[dry run] Would pair with key: ${PAIRING_KEY:-<interactive>}"
    else
        if [ -n "$PAIRING_KEY" ]; then
            printf "  ${YELLOW}◌${RESET} Pairing..."
            cortiva-hq-agent pair "$PAIRING_KEY" >/dev/null 2>&1
            printf "\r  ${GREEN}✓${RESET} Paired with Cortiva HQ          \n"
        else
            echo ""
            read -rp "  Enter your pairing key: " PAIRING_KEY
            printf "  ${YELLOW}◌${RESET} Pairing..."
            cortiva-hq-agent pair "$PAIRING_KEY" >/dev/null 2>&1
            printf "\r  ${GREEN}✓${RESET} Paired with Cortiva HQ          \n"
        fi
    fi
fi

# --- Service installation ---

step "Starting service"

if [ "$OS" = "Darwin" ]; then
    PLIST="$HOME/Library/LaunchAgents/com.cortiva.fabric.plist"
    if [ -f "$PLIST" ]; then
        ok "launchd service — reloading"
        run_or_dry "launchctl unload '$PLIST' 2>/dev/null || true"
        run_or_dry "cortiva-hq-agent install-service >/dev/null 2>&1"
        run_or_dry "launchctl load '$PLIST'"
    else
        printf "  ${YELLOW}◌${RESET} Registering launchd service..."
        run_or_dry "cortiva-hq-agent install-service >/dev/null 2>&1"
        run_or_dry "launchctl load '$PLIST'"
        printf "\r  ${GREEN}✓${RESET} launchd service — running          \n"
    fi
elif [ "$OS" = "Linux" ]; then
    SERVICE="/etc/systemd/system/cortiva.service"
    if [ -f "$SERVICE" ]; then
        ok "systemd service — reloading"
        run_or_dry "cortiva-hq-agent install-service >/dev/null 2>&1"
        run_or_dry "sudo systemctl daemon-reload"
        run_or_dry "sudo systemctl restart cortiva"
    else
        printf "  ${YELLOW}◌${RESET} Registering systemd service..."
        run_or_dry "cortiva-hq-agent install-service >/dev/null 2>&1"
        run_or_dry "sudo systemctl daemon-reload"
        run_or_dry "sudo systemctl enable --now cortiva"
        printf "\r  ${GREEN}✓${RESET} systemd service — running          \n"
    fi
fi

# --- Verify ---

if [ "$DRY_RUN" = false ]; then
    step "Verifying"
    sleep 3
    cortiva-hq-agent diagnose --brief 2>/dev/null || true
fi

# --- Done ---

printf "\n"
printf "  ${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n"
if [ "$DRY_RUN" = true ]; then
    printf "\n  ${YELLOW}Dry run complete.${RESET} No changes were made.\n"
else
    printf "\n  ${GREEN}${BOLD}✓ Cortiva is running${RESET}\n"
    printf "  ${DIM}Your node will appear in the portal shortly.${RESET}\n"
    printf "\n"
    printf "  ${DIM}Diagnose${RESET}  cortiva-hq-agent diagnose\n"
    printf "  ${DIM}Logs${RESET}      cortiva-hq-agent logs\n"
    printf "  ${DIM}Stop${RESET}      cortiva-hq-agent stop\n"
fi
printf "\n"
