#!/usr/bin/env bash

set -euo pipefail

# QuickCall Trace — end-user installer
# Usage:
#   curl -fsSL https://quickcall.dev/trace/install.sh | bash -s -- <org> <api-key>
#
# Always pushes to trace.quickcall.dev (override with QC_TRACE_INGEST_URL env var)
#
# Idempotent: safe to re-run. If already installed, prints version and exits.
# User-level only: no root, no sudo, no system-wide changes.

QC_TRACE_DIR="$HOME/.quickcall-trace"
LOCAL_INGEST_URL="http://localhost:19777/ingest"
REMOTE_INGEST_URL="https://trace.quickcall.dev/ingest"
ORG=""
API_KEY=""

# Parse arguments (named flags + positional shorthand)
while [ $# -gt 0 ]; do
    case "$1" in
        --org)   ORG="$2"; shift 2 ;;
        --org=*) ORG="${1#--org=}"; shift ;;
        --key)   API_KEY="$2"; shift 2 ;;
        --key=*) API_KEY="${1#--key=}"; shift ;;
        -*)      shift ;;
        *)
            if [ -z "$ORG" ]; then ORG="$1"
            elif [ -z "$API_KEY" ]; then API_KEY="$1"
            fi
            shift ;;
    esac
done

# Default: remote (trace.quickcall.dev). QC_TRACE_INGEST_URL env var wins if set.
if [ -n "${QC_TRACE_INGEST_URL:-}" ]; then
    INGEST_URL="$QC_TRACE_INGEST_URL"
else
    INGEST_URL="$REMOTE_INGEST_URL"
fi

if [ -z "$ORG" ]; then
    ORG="local"
fi

# ─── Colors ───────────────────────────────────────────────────────────────────

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BOLD='\033[1m'
RESET='\033[0m'

info()  { echo -e "${BOLD}==>${RESET} $*"; }
ok()    { echo -e "${GREEN}✓${RESET} $*"; }
warn()  { echo -e "${YELLOW}!${RESET} $*"; }
fail()  { echo -e "${RED}✗${RESET} $*"; exit 1; }

# ─── Step 1: Idempotency check ───────────────────────────────────────────────

echo ""
echo -e " ${BOLD}░█▀█░█░█░▀█▀░█▀▀░█░█░█▀▀░█▀█░█░░░█░░${RESET}"
echo -e " ${BOLD}░█░█░█░█░░█░░█░░░█▀▄░█░░░█▀█░█░░░█░░${RESET}"
echo -e " ${BOLD}░▀▀█░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀░▀░▀▀▀░▀▀▀${RESET}"
echo -e "  ${GREEN}trace${RESET}  ·  ai session collector"
echo ""

PID_FILE="$QC_TRACE_DIR/quickcall.pid"
if [ -f "$PID_FILE" ]; then
    PID=$(cat "$PID_FILE")
    if kill -0 "$PID" 2>/dev/null; then
        VERSION=$("$HOME/.local/bin/uvx" --quiet qc-trace@latest python -c "from qc_trace import __version__; print(__version__)" 2>/dev/null || echo "unknown")
        ok "QuickCall daemon already running (PID $PID, v$VERSION)"
        exit 0
    fi
fi

# Also check if launchd/systemd service is already registered
OS="$(uname -s)"
if [ "$OS" = "Darwin" ]; then
    DOMAIN_TARGET="gui/$(id -u)"
    if launchctl print "$DOMAIN_TARGET/com.quickcall.traced" >/dev/null 2>&1; then
        ok "QuickCall service already registered (launchd)"
        exit 0
    fi
elif [ "$OS" = "Linux" ]; then
    if systemctl --user is-active --quiet quickcall 2>/dev/null; then
        ok "QuickCall service already running (systemd)"
        exit 0
    fi
fi

# ─── Step 2: Pre-flight checks ───────────────────────────────────────────────

# curl
if ! command -v curl >/dev/null 2>&1; then
    fail "curl is required but not found."
fi

# Warn if running as root
if [ "$(id -u)" = "0" ]; then
    warn "Running as root — the service will be installed for the root user."
fi

# ─── Step 3: Install uv (if not present) ─────────────────────────────────────

if command -v uv >/dev/null 2>&1; then
    ok "uv already installed ($(uv --version 2>/dev/null || echo 'unknown'))"
else
    info "Installing uv..."
    curl -LsSf https://astral.sh/uv/install.sh | sh
    export PATH="$HOME/.local/bin:$PATH"
    if command -v uv >/dev/null 2>&1; then
        ok "uv installed"
    else
        fail "uv installation failed"
    fi
fi

# Python 3.11+ (uv manages its own Python, so only check system python as fallback info)
if command -v python3 >/dev/null 2>&1; then
    PY_VERSION=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
    ok "Python $PY_VERSION (uv will manage its own Python for quickcall)"
else
    ok "No system python3 found (uv will manage Python automatically)"
fi

# ─── Step 4: Configure shell ─────────────────────────────────────────────────

SHELL_CONFIG=""
if [ -f "$HOME/.zshrc" ]; then
    SHELL_CONFIG="$HOME/.zshrc"
elif [ -f "$HOME/.bashrc" ]; then
    SHELL_CONFIG="$HOME/.bashrc"
elif [ -f "$HOME/.bash_profile" ]; then
    SHELL_CONFIG="$HOME/.bash_profile"
fi

MARKER_BEGIN="# >>> quickcall-trace >>>"
MARKER_END="# <<< quickcall-trace <<<"
SHELL_BLOCK="$MARKER_BEGIN
export PATH=\"\$HOME/.local/bin:\$PATH\"
alias quickcall='uvx --quiet --no-cache --from qc-trace quickcall'
$MARKER_END"

if [ -n "$SHELL_CONFIG" ]; then
    if grep -q "$MARKER_BEGIN" "$SHELL_CONFIG" 2>/dev/null; then
        # Update existing block in-place
        # Delete from marker begin to marker end, then append new block
        LC_ALL=C sed -i.bak "/$MARKER_BEGIN/,/$MARKER_END/d" "$SHELL_CONFIG"
        rm -f "${SHELL_CONFIG}.bak"
    fi
    echo "$SHELL_BLOCK" >> "$SHELL_CONFIG"
    ok "Shell config updated ($SHELL_CONFIG)"
else
    warn "No shell config found (.zshrc/.bashrc) — add \$HOME/.local/bin to your PATH manually"
fi

# Ensure PATH is set for this session
export PATH="$HOME/.local/bin:$PATH"

# ─── Step 5: Verify quickcall alias works ────────────────────────────────────

# Remove any old uv tool install (replaced by alias)
uv tool uninstall qc-trace 2>/dev/null || true

# Clear stale cache to prevent corrupted venv issues
uv cache clean qc-trace --force >/dev/null 2>&1 || true

ok "quickcall alias configured (via uvx)"

# ─── Step 6: Create data directory + write org to config ─────────────────────

mkdir -p "$QC_TRACE_DIR"

# Generate a persistent device ID (survives re-installs, unique per user+machine)
DEVICE_ID_FILE="$QC_TRACE_DIR/.device_id"
if [ -f "$DEVICE_ID_FILE" ]; then
    DEVICE_ID=$(cat "$DEVICE_ID_FILE")
else
    DEVICE_ID=$(uv run python3 -c "import uuid; print(uuid.uuid4())")
    echo "$DEVICE_ID" > "$DEVICE_ID_FILE"
fi

CONFIG_FILE="$QC_TRACE_DIR/config.json"
if [ -f "$CONFIG_FILE" ]; then
    # Merge org + api_key into existing config (python one-liner, minimal deps)
    python3 -c "
import json, sys
with open('$CONFIG_FILE') as f: c = json.load(f)
c['org'] = '$ORG'
if '$API_KEY': c['api_key'] = '$API_KEY'
if '$INGEST_URL': c['ingest_url'] = '$INGEST_URL'
c['device_id'] = '$DEVICE_ID'
with open('$CONFIG_FILE', 'w') as f: json.dump(c, f, indent=2)
print()
" 2>/dev/null || echo "{\"org\": \"$ORG\", \"api_key\": \"$API_KEY\", \"ingest_url\": \"$INGEST_URL\", \"device_id\": \"$DEVICE_ID\"}" > "$CONFIG_FILE"
else
    echo "{\"org\": \"$ORG\", \"api_key\": \"$API_KEY\", \"ingest_url\": \"$INGEST_URL\", \"device_id\": \"$DEVICE_ID\"}" > "$CONFIG_FILE"
fi
ok "Org set to: $ORG"
if [ -n "$API_KEY" ]; then
    ok "API key configured"
fi

# ─── Step 7: Generate run.sh wrapper with version check + crash loop ─────────

TRACE_SERVER="${INGEST_URL%/ingest}"
RUN_SCRIPT="$QC_TRACE_DIR/quickcall-daemon"

cat > "$RUN_SCRIPT" <<'RUNSH_EOF'
#!/bin/sh
UPDATE_CHECK_INTERVAL=${QC_UPDATE_INTERVAL:-300}  # check for updates (default 5 min)

get_latest_version() {
  # Try server first, fall back to PyPI
  V=$(curl -sf __TRACE_SERVER__/api/latest-version 2>/dev/null | sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
  if [ -z "$V" ]; then
    V=$(curl -sf https://pypi.org/pypi/qc-trace/json 2>/dev/null | sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
  fi
  echo "$V"
}

while true; do
  VERSION=$(get_latest_version)
  [ -z "$VERSION" ] && VERSION="latest"
  export PATH="$HOME/.local/bin:$PATH"

  # Kill any existing quickcall run processes to prevent duplicates
  pkill -f "quickcall run" 2>/dev/null || true
  sleep 1

  # Clear stale cache to prevent corrupted venv crashes
  uv cache clean qc-trace --force >/dev/null 2>&1 || true

  # Start daemon in background
  uvx --no-cache --from "qc-trace@${VERSION}" quickcall run &
  DAEMON_PID=$!
  echo "[quickcall] daemon started v${VERSION} (PID ${DAEMON_PID})"

  # Subloop: poll for updates while daemon is running
  while kill -0 "$DAEMON_PID" 2>/dev/null; do
    sleep "$UPDATE_CHECK_INTERVAL"
    NEW_VERSION=$(get_latest_version)
    [ -z "$NEW_VERSION" ] && continue
    if [ "$NEW_VERSION" != "$VERSION" ]; then
      echo "[quickcall] update available: v${VERSION} -> v${NEW_VERSION}, restarting..."
      kill "$DAEMON_PID" 2>/dev/null
      wait "$DAEMON_PID" 2>/dev/null
      break
    fi
  done

  # Wait for daemon to fully exit
  wait "$DAEMON_PID" 2>/dev/null

  # If the daemon exited (crash/update), wait briefly then restart
  sleep 5
done
RUNSH_EOF

sed -i.bak "s|__TRACE_SERVER__|${TRACE_SERVER}|g" "$RUN_SCRIPT"
rm -f "${RUN_SCRIPT}.bak"
chmod +x "$RUN_SCRIPT"
# Remove old run.sh if present
rm -f "$QC_TRACE_DIR/run.sh"
ok "Daemon wrapper written ($RUN_SCRIPT)"

# ─── Step 8: Install service (user-level, no root) ───────────────────────────

case "$OS" in
    Linux)
        info "Installing user-level systemd service..."
        SERVICE_DIR="$HOME/.config/systemd/user"
        SERVICE_FILE="$SERVICE_DIR/quickcall.service"
        mkdir -p "$SERVICE_DIR"

        cat > "$SERVICE_FILE" <<SYSTEMD_EOF
[Unit]
Description=QuickCall trace collection daemon
After=network-online.target

[Service]
Type=simple
Environment=QC_TRACE_INGEST_URL=$INGEST_URL
Environment=QC_TRACE_ORG=$ORG
Environment=QC_TRACE_API_KEY=$API_KEY
ExecStart=/bin/sh ${RUN_SCRIPT}
Restart=always
RestartSec=10

[Install]
WantedBy=default.target
SYSTEMD_EOF

        systemctl --user daemon-reload
        systemctl --user enable --now quickcall

        ok "systemd user service installed and started"
        echo "  Status:  systemctl --user status quickcall"
        echo "  Logs:    journalctl --user-unit quickcall -f"
        ;;

    Darwin)
        info "Installing launchd agent..."

        # ── Build minimal .app bundle so macOS shows "QuickCall" with a proper icon
        #    instead of "sh" with a Terminal icon in the background items notification
        APP_DIR="$QC_TRACE_DIR/QuickCall.app"
        APP_CONTENTS="$APP_DIR/Contents"
        APP_MACOS="$APP_CONTENTS/MacOS"
        APP_RESOURCES="$APP_CONTENTS/Resources"
        mkdir -p "$APP_MACOS" "$APP_RESOURCES"

        # App Info.plist — identifies the app to macOS
        cat > "$APP_CONTENTS/Info.plist" <<APPLIST_EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleIdentifier</key>
    <string>com.quickcall.traced</string>
    <key>CFBundleName</key>
    <string>QuickCall</string>
    <key>CFBundleDisplayName</key>
    <string>QuickCall</string>
    <key>CFBundleExecutable</key>
    <string>quickcall-daemon</string>
    <key>CFBundleIconFile</key>
    <string>AppIcon</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>LSBackgroundOnly</key>
    <true/>
    <key>LSUIElement</key>
    <true/>
</dict>
</plist>
APPLIST_EOF

        # Symlink the daemon wrapper into the .app bundle
        ln -sf "$RUN_SCRIPT" "$APP_MACOS/quickcall-daemon"

        # Generate a simple app icon (blue circle with Q) using Python + macOS sips
        # Creates a 256x256 PNG, then converts to .icns
        python3 -c "
import struct, zlib, os

# Generate a 256x256 RGBA PNG with a blue circle and white Q
W = 256
pixels = bytearray()
for y in range(W):
    pixels.append(0)  # filter byte
    for x in range(W):
        # Distance from center
        cx, cy = W//2, W//2
        dx, dy = x - cx, y - cy
        dist = (dx*dx + dy*dy) ** 0.5
        r_outer = W//2 - 8
        if dist <= r_outer:
            # Blue circle (#2563EB)
            r, g, b, a = 37, 99, 235, 255
            # White Q letter (rough approximation)
            r_q_outer = W//2 - 60
            r_q_inner = W//2 - 90
            in_ring = r_q_inner <= dist <= r_q_outer
            # Q tail: diagonal line from center-right going down-right
            in_tail = (50 < dx < 85 and 20 < dy < 75 and abs(dx - dy - 30) < 18)
            if in_ring or in_tail:
                r, g, b = 255, 255, 255
        else:
            r, g, b, a = 0, 0, 0, 0
        pixels.extend([r, g, b, a])

def make_png(width, height, raw_data):
    def chunk(ctype, data):
        c = ctype + data
        return struct.pack('>I', len(data)) + c + struct.pack('>I', zlib.crc32(c) & 0xffffffff)
    header = b'\\x89PNG\\r\\n\\x1a\\n'
    ihdr = chunk(b'IHDR', struct.pack('>IIBBBBB', width, height, 8, 6, 0, 0, 0))
    idat = chunk(b'IDAT', zlib.compress(bytes(raw_data), 9))
    iend = chunk(b'IEND', b'')
    return header + ihdr + idat + iend

png = make_png(W, W, pixels)
icon_path = os.path.expanduser('~/.quickcall-trace/QuickCall.app/Contents/Resources/AppIcon.png')
with open(icon_path, 'wb') as f:
    f.write(png)
" 2>/dev/null

        # Convert PNG to icns using macOS built-in tools
        ICONSET_DIR="$APP_RESOURCES/AppIcon.iconset"
        mkdir -p "$ICONSET_DIR"
        if [ -f "$APP_RESOURCES/AppIcon.png" ]; then
            # Create required icon sizes
            for size in 16 32 128 256; do
                sips -z $size $size "$APP_RESOURCES/AppIcon.png" --out "$ICONSET_DIR/icon_${size}x${size}.png" >/dev/null 2>&1
            done
            for size in 16 32 128; do
                double=$((size * 2))
                sips -z $double $double "$APP_RESOURCES/AppIcon.png" --out "$ICONSET_DIR/icon_${size}x${size}@2x.png" >/dev/null 2>&1
            done
            iconutil -c icns "$ICONSET_DIR" -o "$APP_RESOURCES/AppIcon.icns" 2>/dev/null
            rm -rf "$ICONSET_DIR" "$APP_RESOURCES/AppIcon.png"
        fi

        # Ad-hoc sign the app bundle so Gatekeeper doesn't complain
        codesign --force --deep -s - "$APP_DIR" 2>/dev/null || true

        ok "App bundle created ($APP_DIR)"

        # ── LaunchAgent plist — points to the .app bundle executable
        PLIST_DIR="$HOME/Library/LaunchAgents"
        PLIST_FILE="$PLIST_DIR/com.quickcall.traced.plist"
        mkdir -p "$PLIST_DIR"

        cat > "$PLIST_FILE" <<PLIST_EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.quickcall.traced</string>

    <key>Program</key>
    <string>${APP_MACOS}/quickcall-daemon</string>

    <key>EnvironmentVariables</key>
    <dict>
        <key>QC_TRACE_INGEST_URL</key>
        <string>${INGEST_URL}</string>
        <key>QC_TRACE_ORG</key>
        <string>${ORG}</string>
        <key>QC_TRACE_API_KEY</key>
        <string>${API_KEY}</string>
    </dict>

    <key>RunAtLoad</key>
    <true/>

    <key>KeepAlive</key>
    <true/>

    <key>StandardOutPath</key>
    <string>${QC_TRACE_DIR}/quickcall.log</string>

    <key>StandardErrorPath</key>
    <string>${QC_TRACE_DIR}/quickcall.err</string>
</dict>
</plist>
PLIST_EOF

        DOMAIN_TARGET="gui/$(id -u)"
        launchctl bootout "$DOMAIN_TARGET/com.quickcall.traced" 2>/dev/null || true
        launchctl bootstrap "$DOMAIN_TARGET" "$PLIST_FILE"

        ok "launchd agent installed and started"
        echo "  Plist:   $PLIST_FILE"
        echo "  Logs:    $QC_TRACE_DIR/quickcall.log"
        echo "  Errors:  $QC_TRACE_DIR/quickcall.err"
        ;;

    *)
        fail "Unsupported OS: $OS (supported: Linux, macOS)"
        ;;
esac

echo "  Data:    $QC_TRACE_DIR/"

# ─── Step 9: Verify ──────────────────────────────────────────────────────────

info "Verifying installation..."
sleep 2  # give daemon a moment to start

CURL_ARGS=(-s -o /dev/null -w "%{http_code}" -X POST "$INGEST_URL"
    -H "Content-Type: application/json")
if [ -n "$API_KEY" ]; then
    CURL_ARGS+=(-H "X-API-Key: $API_KEY")
fi

HEARTBEAT=$(curl "${CURL_ARGS[@]}" \
    -d "[{
        \"id\": \"install-$(hostname)-$(date +%s)\",
        \"session_id\": \"install-verify\",
        \"source\": \"qc_trace_install\",
        \"msg_type\": \"system\",
        \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",
        \"content\": \"install ok — $(whoami)@$(hostname) — $(uname -s) — python $PY_VERSION\",
        \"source_schema_version\": 1
    }]" 2>/dev/null || echo "000")

if [ "$HEARTBEAT" = "200" ] || [ "$HEARTBEAT" = "201" ]; then
    ok "Heartbeat sent to $INGEST_URL"
else
    warn "Could not reach ingest server ($INGEST_URL, HTTP $HEARTBEAT) — daemon will retry"
fi

echo ""
echo -e "${GREEN}${BOLD}QuickCall Trace installed successfully!${RESET}"
echo ""
echo "The daemon is now watching your AI CLI sessions and pushing to:"
echo "  $INGEST_URL"
echo ""
echo "Commands:"
echo "  quickcall status    # Check daemon + stats"
echo "  quickcall logs -f   # Follow daemon logs"
echo ""
echo "To use 'quickcall' in this shell, run: source $SHELL_CONFIG"
echo ""
