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

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
fail() { echo "[FAIL] $*" >&2; exit 1; }
ask_yes_no() { local answer; read -rp "$1 [y/N]: " answer; [[ "$answer" =~ ^[Yy]([Ee][Ss])?$ ]]; }

UPDATE_APIS=false; UPDATE_APPS=false; UPDATE_AI=false; DRY_RUN=false
ACTION=""
ACTION_TARGET="all"
installed_apis=false; installed_apps=false; installed_ai=false

case "${1:-}" in
  update|current|status|clean|reset)
    ACTION="$1"
    shift
    [[ "$ACTION" == "clean" && "${1:-}" == "containers" ]] && shift
    ;;
  restart|logs|down|link-ai|proxy-ai)
    ACTION="$1"
    ACTION_TARGET="${2:-}"
    shift 2
    ;;
esac

for arg in "$@"; do
  case "$arg" in
    --apis) UPDATE_APIS=true ;;
    --apps) UPDATE_APPS=true ;;
    --ai) UPDATE_AI=true ;;
    --all) UPDATE_APIS=true; UPDATE_APPS=true; UPDATE_AI=true ;;
    --dry-run) DRY_RUN=true ;;
    -h|--help)
      cat <<'USAGE'
Usage:
  ./manage.sh [--apis|--apps|--ai|--all] [--dry-run]
  ./manage.sh update [--dry-run]
  ./manage.sh current [--dry-run]  # backward-compatible alias
  ./manage.sh restart [apis|apps|ai|all]
  ./manage.sh down [apis|apps|ai|all]
  ./manage.sh status
  ./manage.sh logs [apis|apps|ai|all]
  ./manage.sh clean containers
  ./manage.sh link-ai [AI_URL]
  ./manage.sh proxy-ai [AI_DOMAIN]
  ./manage.sh reset
USAGE
      exit 0
      ;;
    *) fail "Unknown option: $arg" ;;
  esac
done

if [[ -f install-manifest.json ]]; then
  grep -Eq '"apis"[[:space:]]*:[[:space:]]*\{"status":[[:space:]]*"(installed|updated)"' install-manifest.json && installed_apis=true || true
  grep -Eq '"apps"[[:space:]]*:[[:space:]]*\{"status":[[:space:]]*"(installed|updated)"' install-manifest.json && installed_apps=true || true
  grep -Eq '"ai"[[:space:]]*:[[:space:]]*\{"status":[[:space:]]*"(installed|updated)"' install-manifest.json && installed_ai=true || true
fi
[[ -f apis/.env ]] && installed_apis=true
[[ -f ai/.env.ai ]] && installed_ai=true

if [[ "$ACTION" == "clean" ]]; then
  command -v docker >/dev/null 2>&1 || fail "Docker is required"
  docker container prune
  exit 0
fi

if [[ "$ACTION" == "reset" ]]; then
  [[ "${KORO_CONFIRM_RESET:-}" == "RESET KORO ERP" ]] || {
    read -rp "This deletes the Koro deployment files, containers, volumes, and data. Type RESET KORO ERP to continue: " reset_confirmation
    [[ "$reset_confirmation" == "RESET KORO ERP" ]] || fail "Reset cancelled."
  }
  command -v docker >/dev/null 2>&1 || fail "Docker is required"
  command -v curl >/dev/null 2>&1 || command -v wget >/dev/null 2>&1 || fail "curl or wget is required"
  [[ -f apis/docker-compose.yml ]] && docker compose --env-file apis/.env -f apis/docker-compose.yml down --volumes --remove-orphans 2>/dev/null || true
  [[ -f apis/docker-compose.yml && -f apps/docker-compose.yml ]] && docker compose --env-file apis/.env -f apis/docker-compose.yml -f apps/docker-compose.yml --profile all down --volumes --remove-orphans 2>/dev/null || true
  [[ -f ai/docker-compose.yml && -f ai/.env.ai ]] && docker compose --env-file ai/.env.ai -f ai/docker-compose.yml down --volumes --remove-orphans 2>/dev/null || true
  downloader="$(mktemp)"
  download_url="${KORO_DOWNLOAD_URL:-https://koroworks.com/deploy}/get-koroerp.sh"
  if command -v curl >/dev/null 2>&1; then curl -fsSL "$download_url" -o "$downloader"; else wget -q "$download_url" -O "$downloader"; fi
  find "$SCRIPT_DIR" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
  KORO_INSTALL_DIR="$SCRIPT_DIR" KORO_DOWNLOAD_URL="${KORO_DOWNLOAD_URL:-https://koroworks.com/deploy}" bash "$downloader"
  rm -f "$downloader"
  exit 0
fi

if [[ "$ACTION" == "link-ai" ]]; then
  [[ -f apis/.env ]] || fail "apis/.env is missing; install APIs first"
  [[ -f ai/link.sh ]] || fail "ai/link.sh is missing; download the complete deployment package"
  if [[ -n "$ACTION_TARGET" ]]; then
    bash ai/link.sh --ai-url "$ACTION_TARGET"
  else
    bash ai/link.sh
  fi
  exit 0
fi

if [[ "$ACTION" == "proxy-ai" ]]; then
  [[ -f ai/.env.ai ]] || fail "ai/.env.ai is missing; install AI first"
  ai_domain="$ACTION_TARGET"
  [[ -n "$ai_domain" ]] || { read -rp "AI domain/subdomain (e.g. ai.example.com): " ai_domain; }
  [[ -n "$ai_domain" ]] || fail "AI domain is required"
  acme_email="${KORO_ACME_EMAIL:-}"
  [[ -n "$acme_email" ]] || read -rp "ACME email (default: admin@$ai_domain): " acme_email
  acme_email="${acme_email:-admin@$ai_domain}"
  grep -q '^AI_DOMAIN=' ai/.env.ai && sed -i "s|^AI_DOMAIN=.*|AI_DOMAIN=$ai_domain|" ai/.env.ai || echo "AI_DOMAIN=$ai_domain" >> ai/.env.ai
  grep -q '^ACME_EMAIL=' ai/.env.ai && sed -i "s|^ACME_EMAIL=.*|ACME_EMAIL=$acme_email|" ai/.env.ai || echo "ACME_EMAIL=$acme_email" >> ai/.env.ai
  docker compose --env-file ai/.env.ai --profile proxy -f ai/docker-compose.yml up -d
  echo "DNS required: $ai_domain -> this AI server"
  echo "Link from the ERP server with: ./manage.sh link-ai https://$ai_domain"
  exit 0
fi

if [[ "$ACTION" == "status" ]]; then
  command -v docker >/dev/null 2>&1 || fail "Docker is required"
  [[ -f apis/.env ]] && docker compose --env-file apis/.env -f apis/docker-compose.yml ps
  [[ -f apis/.env && $installed_apps == true ]] && docker compose --env-file apis/.env -f apis/docker-compose.yml -f apps/docker-compose.yml --profile all ps
  if [[ -f ai/.env.ai ]]; then
    ai_status_args=()
    grep -q '^AI_DOMAIN=' ai/.env.ai && ai_status_args+=(--profile proxy)
    docker compose --env-file ai/.env.ai "${ai_status_args[@]}" -f ai/docker-compose.yml ps
  fi
  exit 0
fi

if [[ "$ACTION" == "current" ]]; then
  UPDATE_APIS="$installed_apis"
  UPDATE_APPS="$installed_apps"
  UPDATE_AI="$installed_ai"
fi

if [[ "$ACTION" == "restart" || "$ACTION" == "logs" || "$ACTION" == "down" ]]; then
  case "$ACTION_TARGET" in
    apis) UPDATE_APIS=true ;;
    apps) UPDATE_APPS=true ;;
    ai) UPDATE_AI=true ;;
    all) UPDATE_APIS=true; UPDATE_APPS=true; UPDATE_AI=true ;;
    *) fail "Unknown target: $ACTION_TARGET (use apis, apps, ai, or all)" ;;
  esac
fi

if [[ -z "$ACTION" ]] && ! $UPDATE_APIS && ! $UPDATE_APPS && ! $UPDATE_AI; then
  echo "Koro ERP update components"
  $installed_apis && ask_yes_no "Update ERP APIs and core services?" && UPDATE_APIS=true
  $installed_apps && ask_yes_no "Update optional web apps?" && UPDATE_APPS=true
  $installed_ai && ask_yes_no "Update AI service?" && UPDATE_AI=true
fi

! $UPDATE_APIS && ! $UPDATE_APPS && ! $UPDATE_AI && fail "No installed components selected for update."

$UPDATE_APPS && [[ -f apis/.env ]] || $UPDATE_APPS && fail "apis/.env is missing; install APIs first"
$UPDATE_AI && [[ -f ai/.env.ai ]] || $UPDATE_AI && fail "ai/.env.ai is missing; install AI first"
command -v docker >/dev/null 2>&1 || fail "Docker is required"
docker compose version >/dev/null 2>&1 || fail "Docker Compose V2 is required"

run_compose() {
  local env_file="$1"; shift
  docker compose --env-file "$env_file" "$@"
}

if [[ "$ACTION" == "restart" || "$ACTION" == "logs" || "$ACTION" == "down" ]]; then
  compose_action="restart"
  [[ "$ACTION" == "logs" ]] && compose_action="logs --tail=100"
  [[ "$ACTION" == "down" ]] && compose_action="down"
  $UPDATE_APIS && run_compose apis/.env -f apis/docker-compose.yml $compose_action
  $UPDATE_APPS && run_compose apis/.env -f apis/docker-compose.yml -f apps/docker-compose.yml --profile all $compose_action
  if $UPDATE_AI; then
    ai_action_args=()
    grep -q '^AI_DOMAIN=' ai/.env.ai && ai_action_args+=(--profile proxy)
    run_compose ai/.env.ai "${ai_action_args[@]}" -f ai/docker-compose.yml $compose_action
  fi
  exit 0
fi

if $UPDATE_APIS; then
  api_args=(-f apis/docker-compose.yml)
  db_host="$(grep -E '^DB_HOST=' apis/.env | tail -n 1 | cut -d= -f2- || true)"
  [[ "$db_host" == "postgres" ]] && api_args+=(--profile db)
  run_compose apis/.env "${api_args[@]}" pull
  $DRY_RUN || run_compose apis/.env "${api_args[@]}" up -d
fi

if $UPDATE_APPS; then
  app_args=(-f apis/docker-compose.yml -f apps/docker-compose.yml --profile all)
  run_compose apis/.env "${app_args[@]}" pull
  $DRY_RUN || run_compose apis/.env "${app_args[@]}" up -d
fi

if $UPDATE_AI; then
  ai_args=(-f ai/docker-compose.yml)
  storage_mode="$(grep -E '^STORAGE_MODE=' ai/.env.ai | tail -n 1 | cut -d= -f2- || true)"
  [[ "$storage_mode" == "minio" ]] && ai_args+=(--profile minio)
  grep -q '^AI_DOMAIN=' ai/.env.ai && ai_args+=(--profile proxy)
  run_compose ai/.env.ai "${ai_args[@]}" pull
  $DRY_RUN || run_compose ai/.env.ai "${ai_args[@]}" up -d
fi

umask 077
cat > install-manifest.json <<EOF
{
  "schema_version": 1,
  "last_updated_at": "$(date -u +%FT%TZ)",
  "host": "$(hostname 2>/dev/null || echo unknown)",
  "operation": "update",
  "components": {
    "apis": {"status": "$($UPDATE_APIS && echo updated || $installed_apis && echo installed || echo not_installed)"},
    "apps": {"status": "$($UPDATE_APPS && echo updated || $installed_apps && echo installed || echo not_installed)"},
    "ai": {"status": "$($UPDATE_AI && echo updated || $installed_ai && echo installed || echo not_installed)", "storage_mode": "${storage_mode:-unknown}"}
  },
  "secrets_recorded": false
}
EOF
echo "[OK] Update complete"
