#!/usr/bin/env bash
set -euo pipefail

# ═══════════════════════════════════════════════════════════════════════
# ByteLyst NoteLett - Production Deployment Script
# ═══════════════════════════════════════════════════════════════════════
# Usage: ./deploy-notes.sh [option]
#
# Options (interactive menu when no arguments):
#   1 - Normal deployment (with cache, with health checks)
#   2 - Force deployment (skip dirty checks, with cache)
#   3 - Skip health checks (with cache)
#   4 - No-cache build (force rebuild, with health checks)
#   5 - Force + No-cache (skip checks, force rebuild)
#   6 - Force + Skip health checks (skip both)
#   7 - All options: Force + Skip health + No-cache
#
# Command-line options:
#   --force              Skip dirty checks and force deployment
#   --skip-health-check  Skip endpoint health verification
#   --no-cache           Force rebuild without cache
# ═══════════════════════════════════════════════════════════════════════

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'

log()  { echo -e "${CYAN}[$(date +%H:%M:%S)]${NC} $*"; }
ok()   { echo -e "${GREEN}[$(date +%H:%M:%S)] ✓${NC} $*"; }
warn() { echo -e "${YELLOW}[$(date +%H:%M:%S)] ⚠${NC} $*"; }
fail() { echo -e "${RED}[$(date +%H:%M:%S)] ✗${NC} $*"; exit 1; }

# ── Configuration ────────────────────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_DIR="${SCRIPT_DIR}/../learning_ai_notes"
cd "$SCRIPT_DIR"

FORCE=false
SKIP_HEALTH_CHECK=false
NO_CACHE=false

# Parse command-line arguments
while [[ $# -gt 0 ]]; do
  case "$1" in
    --force) FORCE=true; shift ;;
    --skip-health-check) SKIP_HEALTH_CHECK=true; shift ;;
    --no-cache) NO_CACHE=true; shift ;;
    *) fail "Unknown option: $1";;
  esac
done

# ── Interactive Menu ─────────────────────────────────────────────────
if [ "$FORCE" = false ] && [ "$SKIP_HEALTH_CHECK" = false ] && [ "$NO_CACHE" = false ]; then
    echo ""
    echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${CYAN}║${NC}  ByteLyst NoteLett - Deployment Options         ${CYAN}║${NC}"
    echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
    echo ""
    echo -e " ${GREEN}1${NC} - Normal deployment (with cache, with health checks)"
    echo -e " ${GREEN}2${NC} - Force deployment (skip dirty checks, with cache)"
    echo -e " ${GREEN}3${NC} - Skip health checks (with cache)"
    echo -e " ${GREEN}4${NC} - No-cache build (force rebuild, with health checks)"
    echo -e " ${GREEN}5${NC} - Force + No-cache (skip checks, force rebuild)"
    echo -e " ${GREEN}6${NC} - Force + Skip health checks (skip both)"
    echo -e " ${GREEN}7${NC} - All options: Force + Skip health + No-cache"
    echo ""
    read -r -p "Select option (1-7): " choice

    case $choice in
        1) ;;
        2) FORCE=true ;;
        3) SKIP_HEALTH_CHECK=true ;;
        4) NO_CACHE=true ;;
        5) FORCE=true; NO_CACHE=true ;;
        6) FORCE=true; SKIP_HEALTH_CHECK=true ;;
        7) FORCE=true; SKIP_HEALTH_CHECK=true; NO_CACHE=true ;;
        *) fail "Invalid option. Please select 1-7." ;;
    esac
fi

# ── Prerequisites ────────────────────────────────────────────────────
if [ ! -d "$REPO_DIR" ]; then
  fail "Repo directory not found: $REPO_DIR"
fi

cd "$REPO_DIR"

# ── Dirty Check ───────────────────────────────────────────────────────
if [ "$FORCE" = false ]; then
  log "Running dirty checks..."

  # Check for uncommitted changes
  if ! git diff-index --quiet HEAD --; then
    fail "Uncommitted changes detected. Commit or stash first, or use --force"
  fi

  # Check for untracked files
  if [ -n "$(git ls-files --others --exclude-standard)" ]; then
    fail "Untracked files detected. Commit or remove them, or use --force"
  fi

  # Check for unpushed commits
  LOCAL_COMMIT=$(git rev-parse @)
  REMOTE_COMMIT=$(git rev-parse '@{u}' 2>/dev/null || echo "")

  if [ -n "$REMOTE_COMMIT" ] && [ "$LOCAL_COMMIT" != "$REMOTE_COMMIT" ]; then
    fail "Unpushed commits detected. Push first or use --force"
  fi

  ok "Dirty checks passed"
else
  warn "Skipping dirty checks (--force enabled)"
fi

# ── Pull and Rebase ───────────────────────────────────────────────────
log "Pulling latest changes from origin/main..."
git fetch origin

LOCAL_MAIN=$(git rev-parse main)
REMOTE_MAIN=$(git rev-parse origin/main)

if [ "$LOCAL_MAIN" != "$REMOTE_MAIN" ]; then
  log "Local main is behind origin/main, rebasing..."
  git rebase origin/main || {
    fail "Rebase failed. Resolve conflicts and run: git rebase --continue"
  }
  ok "Rebase completed successfully"
else
  ok "Already up to date with origin/main"
fi

# ── Run Smoke Tests ─────────────────────────────────────────────────────
if [ "$SKIP_HEALTH_CHECK" = false ]; then
  log "Running smoke tests before deployment..."
  if [ -f "scripts/smoke-release.sh" ]; then
    chmod +x scripts/smoke-release.sh
    ./scripts/smoke-release.sh || {
      fail "Smoke tests failed. Fix issues before deploying or use --skip-health-check"
    }
    ok "Smoke tests passed"
  else
    warn "Smoke test script not found, skipping pre-deployment tests"
  fi
fi

# ── Package Publication Check ───────────────────────────────────────────
log "Checking @bytelyst package publication status..."

# Read Gitea token from file
unset GITEA_NPM_TOKEN
if [ -f "/opt/bytelyst/.gitea_token" ]; then
    GITEA_NPM_TOKEN="$(< /opt/bytelyst/.gitea_token)"
elif [ -f "$HOME/.gitea_npm_token" ]; then
    GITEA_NPM_TOKEN="$(< "$HOME/.gitea_npm_token")"
fi

if [ -z "$GITEA_NPM_TOKEN" ]; then
    warn "Gitea token not found, skipping package publication check"
else
    GITEA_REGISTRY="http://localhost:3300/api/packages/ByteLyst/npm/"
    CRITICAL_PACKAGES=(
      "@bytelyst/config|@bytelyst%2fconfig"
      "@bytelyst/cosmos|@bytelyst%2fcosmos"
      "@bytelyst/errors|@bytelyst%2ferrors"
      "@bytelyst/fastify-core|@bytelyst%2ffastify-core"
    )
    MISSING_PACKAGES=()

    for entry in "${CRITICAL_PACKAGES[@]}"; do
        package="${entry%%|*}"
        encoded="${entry##*|}"
        if ! curl -sf -H "Authorization: token ${GITEA_NPM_TOKEN}" "${GITEA_REGISTRY}${encoded}" > /dev/null 2>&1; then
            MISSING_PACKAGES+=("$package")
        fi
    done

    if [ "${#MISSING_PACKAGES[@]}" -eq 0 ]; then
        ok "All critical @bytelyst packages are published"
    else
        warn "Some @bytelyst packages may not be published: ${MISSING_PACKAGES[*]}"
        read -r -p "Continue anyway? (y/N): " continue_anyway
        if [[ ! "$continue_anyway" =~ ^[Yy]$ ]]; then
            fail "Deployment cancelled"
        fi
    fi
fi

# ── Build and Deploy ──────────────────────────────────────────────────
log "Building and deploying Docker containers..."

# Check if docker-compose files exist
if [ ! -f "docker-compose.yml" ]; then
  fail "docker-compose.yml not found in $REPO_DIR"
fi

# Build and start services
BUILD_ARGS=()
if [ "$NO_CACHE" = true ]; then
    BUILD_ARGS+=(--no-cache)
    log "Building Docker images without cache..."
else
    log "Building Docker images..."
fi

docker compose build "${BUILD_ARGS[@]}" || fail "Docker build failed"

log "Starting services..."
docker compose up -d || fail "Docker compose up failed"

ok "Deployment completed"

# ── Health Check ──────────────────────────────────────────────────────
if [ "$SKIP_HEALTH_CHECK" = true ]; then
  warn "Skipping health checks (--skip-health-check enabled)"
  exit 0
fi

log "Waiting for services to be healthy..."
sleep 10

# Check backend health
BACKEND_HEALTH=false
for _ in {1..30}; do
  if curl -sf http://localhost:4016/health > /dev/null 2>&1; then
    BACKEND_HEALTH=true
    break
  fi
  echo -n "."
  sleep 2
done
echo ""

if [ "$BACKEND_HEALTH" = true ]; then
  ok "Backend health check passed (http://localhost:4016)"
else
  fail "Backend health check failed"
fi

# Check web health
WEB_HEALTH=false
for _ in {1..30}; do
  if curl -sf http://localhost:3045 > /dev/null 2>&1; then
    WEB_HEALTH=true
    break
  fi
  echo -n "."
  sleep 2
done
echo ""

if [ "$WEB_HEALTH" = true ]; then
  ok "Web health check passed (http://localhost:3045)"
else
  warn "Web health check failed (may be starting up)"
fi

# ── Endpoint Verification ─────────────────────────────────────────────
log "Verifying production endpoints..."

API_ENDPOINT="https://api.bytelyst.com/notelett"
WEB_ENDPOINT="https://notes.bytelyst.com"

# Check API endpoint
if curl -sf "$API_ENDPOINT/health" > /dev/null 2>&1; then
  ok "API endpoint accessible: $API_ENDPOINT"
else
  warn "API endpoint not accessible: $API_ENDPOINT (may need DNS propagation or routing)"
fi

# Check web endpoint
if curl -sf "$WEB_ENDPOINT" > /dev/null 2>&1; then
  ok "Web endpoint accessible: $WEB_ENDPOINT"
else
  warn "Web endpoint not accessible: $WEB_ENDPOINT (may be starting up)"
fi

# ── API Smoke Tests (Post-Deployment) ───────────────────────────────────
log "Running post-deployment API smoke tests..."

# Test backend health endpoint
BACKEND_URL="http://localhost:4016"
if curl -sf "$BACKEND_URL/health" > /dev/null 2>&1; then
  ok "Backend health endpoint responding"
  # Try to get health details
  HEALTH_RESPONSE=$(curl -s "$BACKEND_URL/health" 2>/dev/null || echo "{}")
  log "Health response: $HEALTH_RESPONSE"
else
  fail "Backend health endpoint not responding"
fi

# Test web is serving content
WEB_URL="http://localhost:3045"
if curl -sf "$WEB_URL" > /dev/null 2>&1; then
  ok "Web frontend is serving content"
  # Check if it's actually HTML
  CONTENT_TYPE=$(curl -sI "$WEB_URL" | grep -i content-type || echo "")
  if echo "$CONTENT_TYPE" | grep -qi "text/html"; then
    ok "Web frontend is serving HTML content"
  else
    warn "Web frontend content type unexpected: $CONTENT_TYPE"
  fi
else
  fail "Web frontend not responding"
fi

log "══════════════════════════════════════════════════════════════════════"
ok "Deployment completed successfully!"
log "Backend: http://localhost:4016 → $API_ENDPOINT"
log "Web: http://localhost:3045 → $WEB_ENDPOINT"
log "══════════════════════════════════════════════════════════════════════"
