#!/usr/bin/env bash
# =============================================================================
# Deploy script for optical-dev.oliver.solutions
# Run from: /opt/video-accessibility/
#
# Usage:
#   First deploy:   ./scripts/deploy-dev.sh
#   Code-only:      ./scripts/deploy-dev.sh --redeploy
#   Custom:         ./scripts/deploy-dev.sh [--skip-build] [--skip-frontend] [--skip-migrations]
#
# --redeploy   shorthand for --skip-build --skip-frontend --skip-migrations
#              (just git pull + docker up -d, no rebuilds)
# =============================================================================
set -euo pipefail

# ── Config ────────────────────────────────────────────────────────────────────
PROJECT_DIR="/opt/video-accessibility"
WEBROOT="/var/www/html/video-accessibility"
APACHE_CONF_DIR="/etc/apache2/sites-enabled"
APACHE_VHOST="optical-dev.oliver.solutions.conf"
COMPOSE="docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.optical-dev.yml --env-file .env.production"
API_INTERNAL_PORT=8012   # host port the api container exposes
VITE_BASE="/video-accessibility"
GCS_BUCKET="${GCS_BUCKET:-$(grep '^GCS_BUCKET=' .env.production 2>/dev/null | cut -d= -f2)}"

# In fallback mode (USE_CELERY_FALLBACK=true) all pipeline workers run locally.
# whisper-worker uses a separate Dockerfile target; tts/ffmpeg-worker reuse the
# worker target but need their own image tag for docker compose up.
BUILD_SERVICES="api worker tts-worker ffmpeg-worker whisper-worker"

# ── Flags ─────────────────────────────────────────────────────────────────────
SKIP_BUILD=false
SKIP_FRONTEND=false
SKIP_MIGRATIONS=false
for arg in "$@"; do
  case $arg in
    --redeploy)        SKIP_BUILD=true; SKIP_FRONTEND=true; SKIP_MIGRATIONS=true ;;
    --skip-build)      SKIP_BUILD=true ;;
    --skip-frontend)   SKIP_FRONTEND=true ;;
    --skip-migrations) SKIP_MIGRATIONS=true ;;
  esac
done

# ── Helpers ───────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
ok()   { echo -e "${GREEN}✓ $*${NC}"; }
info() { echo -e "${BLUE}» $*${NC}"; }
warn() { echo -e "${YELLOW}⚠ $*${NC}"; }
fail() { echo -e "${RED}✗ $*${NC}"; exit 1; }

# ── Pre-flight ────────────────────────────────────────────────────────────────
preflight() {
  info "Pre-flight checks..."
  [[ -f "docker-compose.yml" ]]          || fail "Run from /opt/video-accessibility/"
  [[ -f ".env.production" ]]             || fail ".env.production not found"
  [[ -f "secrets/gcp-credentials.json" ]] || fail "secrets/gcp-credentials.json not found"
  docker info &>/dev/null                || fail "Docker not running"
  docker compose version &>/dev/null     || fail "docker compose not found"

  # Warn if free RAM < 2 GB
  FREE_MB=$(free -m | awk '/^Mem:/ {print $7}')
  if (( FREE_MB < 2048 )); then
    warn "Low free RAM: ${FREE_MB}MB — build may be slow or OOM"
  fi
  ok "Pre-flight passed (free RAM: ${FREE_MB}MB)"
}

# ── Git pull ──────────────────────────────────────────────────────────────────
pull_code() {
  info "Pulling latest code from main..."
  git pull origin main
  ok "Code updated ($(git rev-parse --short HEAD))"
}

# ── Docker build (sequential, one service at a time) ─────────────────────────
build_images() {
  if $SKIP_BUILD; then warn "Skipping Docker build (--skip-build)"; return; fi

  info "Building Docker images sequentially..."
  for svc in $BUILD_SERVICES; do
    info "  Building: $svc"
    $COMPOSE build "$svc"
    ok "  $svc — done"
  done
  ok "All images built"
}

# ── Start services ────────────────────────────────────────────────────────────
start_services() {
  info "Starting services..."
  $COMPOSE up -d
  ok "Containers started"

  # Wait for API to be healthy (up to 60s)
  info "Waiting for API to be healthy..."
  for i in $(seq 1 30); do
    if curl -sf "http://localhost:${API_INTERNAL_PORT}/health" &>/dev/null; then
      ok "API is healthy"
      return
    fi
    sleep 2
  done
  warn "API health check timed out — check logs: docker compose logs api"
}

# ── Migrations ────────────────────────────────────────────────────────────────
run_migrations() {
  if $SKIP_MIGRATIONS; then warn "Skipping migrations (--skip-migrations)"; return; fi

  info "Running database migrations..."
  $COMPOSE exec -T api python migrate.py up
  ok "Migrations complete"
}

# ── Frontend build & deploy ───────────────────────────────────────────────────
deploy_frontend() {
  if $SKIP_FRONTEND; then warn "Skipping frontend (--skip-frontend)"; return; fi

  info "Building frontend..."
  cd frontend
  npm ci --prefer-offline
  VITE_BASE_PATH="${VITE_BASE}" npm run build
  cd ..
  ok "Frontend built"

  info "Deploying frontend to Apache webroot..."
  sudo mkdir -p "${WEBROOT}"
  sudo rsync -a --delete frontend/dist/ "${WEBROOT}/"
  sudo chown -R www-data:www-data "${WEBROOT}"
  sudo chmod -R 755 "${WEBROOT}"
  ok "Frontend deployed to ${WEBROOT}"
}

# ── Apache modules ────────────────────────────────────────────────────────────
ensure_apache_modules() {
  info "Enabling required Apache modules..."
  sudo a2enmod proxy proxy_http proxy_wstunnel rewrite headers 2>/dev/null
  ok "Apache modules enabled"
}

# ── Apache fragment ───────────────────────────────────────────────────────────
ensure_apache_config() {
  FRAGMENT="${PROJECT_DIR}/deploy/apache-video-accessibility.conf"

  # Always regenerate the fragment so it picks up PORT/WEBROOT changes
  info "Writing Apache config fragment..."
  sudo mkdir -p "${PROJECT_DIR}/deploy"
  sudo tee "$FRAGMENT" > /dev/null <<APACHE
# =============================================================
# video-accessibility — Apache config fragment
# Generated by deploy-dev.sh — do NOT edit manually
# =============================================================

# ── Timeouts for large video uploads (up to 2 GB, ~10 min) ──
<IfModule mod_proxy.c>
    ProxyTimeout 600
</IfModule>

# ── WebSocket proxy (MUST be before /api/ HTTP proxy) ────────
# ProxyPassMatch uses regex — takes precedence over Alias even when the
# physical directory ${WEBROOT} exists on disk.
ProxyPassMatch ^/video-accessibility/api/v1/ws/(.*)$ ws://127.0.0.1:${API_INTERNAL_PORT}/api/v1/ws/\$1 disablereuse=on
ProxyPassReverse /video-accessibility/api/v1/ws/ ws://127.0.0.1:${API_INTERNAL_PORT}/api/v1/ws/

# ── API proxy (strip /video-accessibility prefix) ────────────
ProxyPassMatch ^/video-accessibility/api/(.*)$ http://127.0.0.1:${API_INTERNAL_PORT}/api/\$1
ProxyPassReverse /video-accessibility/api/ http://127.0.0.1:${API_INTERNAL_PORT}/api/

# Swagger docs
ProxyPassMatch ^/video-accessibility/docs(/.*)?$ http://127.0.0.1:${API_INTERNAL_PORT}/docs\$1
ProxyPassReverse /video-accessibility/docs http://127.0.0.1:${API_INTERNAL_PORT}/docs
ProxyPassMatch ^/video-accessibility/openapi\.json$ http://127.0.0.1:${API_INTERNAL_PORT}/openapi.json
ProxyPassReverse /video-accessibility/openapi.json http://127.0.0.1:${API_INTERNAL_PORT}/openapi.json

# ── SPA static files ─────────────────────────────────────────
Alias /video-accessibility ${WEBROOT}
<Directory ${WEBROOT}>
    Options -Indexes +FollowSymLinks
    AllowOverride None
    Require all granted

    # Allow large video file uploads (2 GB)
    LimitRequestBody 2147483648

    RewriteEngine On
    RewriteBase /video-accessibility/

    # Serve real files/dirs directly
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]

    # All other paths → index.html (React Router handles client-side nav)
    RewriteRule ^ index.html [L]
</Directory>
APACHE
  ok "Apache fragment written to $FRAGMENT"

  VHOST_FILE="${APACHE_CONF_DIR}/${APACHE_VHOST}"
  INCLUDE_LINE="    Include ${FRAGMENT}"

  if [[ -f "$VHOST_FILE" ]]; then
    if ! sudo grep -qF "$FRAGMENT" "$VHOST_FILE"; then
      info "Injecting Include into Apache vhost..."
      sudo sed -i "s|</VirtualHost>|${INCLUDE_LINE}\n</VirtualHost>|" "$VHOST_FILE"
      ok "Include injected"
    else
      ok "Apache Include already present"
    fi

    sudo apache2ctl configtest && sudo systemctl reload apache2
    ok "Apache reloaded"
  else
    warn "Vhost file not found: $VHOST_FILE — add manually:"
    warn "  Include ${FRAGMENT}"
  fi
}

# ── Smoke test ────────────────────────────────────────────────────────────────
smoke_test() {
  info "Smoke test..."

  # Internal API
  if curl -sf "http://localhost:${API_INTERNAL_PORT}/health" | python3 -m json.tool; then
    ok "API /health — OK"
  else
    warn "API /health — failed"
  fi

  # Public URL
  PUBLIC_URL="https://optical-dev.oliver.solutions${VITE_BASE}"
  HTTP_CODE=$(curl -o /dev/null -sw "%{http_code}" "${PUBLIC_URL}/" 2>/dev/null || echo "000")
  if [[ "$HTTP_CODE" == "200" ]]; then
    ok "Frontend ${PUBLIC_URL}/ — HTTP 200"
  else
    warn "Frontend ${PUBLIC_URL}/ — HTTP ${HTTP_CODE} (Apache may need config)"
  fi

  echo ""
  info "Container status:"
  $COMPOSE ps
}

# ── GCS CORS (needed for browser→GCS chunked uploads) ────────────────────────
ensure_gcs_cors() {
  if [[ -z "$GCS_BUCKET" ]]; then
    warn "GCS_BUCKET not set — skipping CORS config (set manually: gsutil cors set infra/gcs-cors.json gs://<bucket>)"
    return
  fi
  info "Setting GCS CORS configuration for gs://${GCS_BUCKET}..."
  if gsutil cors set "${PROJECT_DIR}/infra/gcs-cors.json" "gs://${GCS_BUCKET}" 2>/dev/null; then
    ok "GCS CORS set"
  else
    warn "gsutil cors set failed — run manually: gsutil cors set infra/gcs-cors.json gs://${GCS_BUCKET}"
  fi
}

# ── Main ──────────────────────────────────────────────────────────────────────
main() {
  echo ""
  echo -e "${BLUE}══════════════════════════════════════════${NC}"
  echo -e "${BLUE}  video-accessibility — optical-dev deploy ${NC}"
  echo -e "${BLUE}══════════════════════════════════════════${NC}"
  echo ""

  cd "$PROJECT_DIR"

  preflight
  pull_code
  build_images
  start_services
  run_migrations
  deploy_frontend
  ensure_apache_modules
  ensure_apache_config
  ensure_gcs_cors
  smoke_test

  echo ""
  ok "Deploy complete!"
  echo ""
  echo "  App:  https://optical-dev.oliver.solutions/video-accessibility/"
  echo "  API:  https://optical-dev.oliver.solutions/video-accessibility/api/v1/health"
  echo "  Docs: https://optical-dev.oliver.solutions/video-accessibility/docs"
  echo ""
  echo "Logs:       $COMPOSE logs -f api"
  echo "Redeploy:   ./scripts/deploy-dev.sh --redeploy          # just pull + restart"
  echo "Code+front: ./scripts/deploy-dev.sh --skip-build        # rebuild frontend, skip docker build"
  echo "Full:       ./scripts/deploy-dev.sh                     # everything from scratch"
}

main "$@"
