#!/usr/bin/env bash
# =============================================================================
# tOS Installation Script
# =============================================================================
# Interaktiver Installationsassistent fuer das tOS Production Deployment.
#
# Ausfuehren mit: chmod +x install.sh && ./install.sh
#
# Das Script:
#   1. Prueft Voraussetzungen (Docker, Docker Compose, openssl)
#   2. Sammelt Konfiguration (Domain, SSL-Modus)
#   3. Generiert kryptographische Secrets
#   4. Startet alle Services
#   5. Wartet auf Bereitschaft und zeigt Setup-URL an
# =============================================================================
set -euo pipefail

# ANSI Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m' # No Color

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

banner() {
  echo -e "${BLUE}${BOLD}"
  echo "  ████████╗ ██████╗ ███████╗"
  echo "     ██╔══╝██╔═══██╗██╔════╝"
  echo "     ██║   ██║   ██║███████╗"
  echo "     ██║   ██║   ██║╚════██║"
  echo "     ██║   ╚██████╔╝███████║"
  echo "     ╚═╝    ╚═════╝ ╚══════╝"
  echo -e "${NC}"
  echo -e "${BOLD}  tOS - Enterprise Web Operating System${NC}"
  echo -e "  Installationsassistent"
  echo ""
}

check_prerequisites() {
  echo -e "${BOLD}[1/4] Voraussetzungen pruefen...${NC}"

  if ! command -v docker &> /dev/null; then
    echo -e "${RED}[FEHLER] Docker nicht gefunden. Bitte installiere Docker: https://docs.docker.com/get-docker/${NC}"
    exit 1
  fi
  echo -e "${GREEN}[OK] Docker gefunden: $(docker --version)${NC}"

  if ! docker compose version &> /dev/null; then
    echo -e "${RED}[FEHLER] Docker Compose Plugin nicht gefunden. Bitte aktualisiere Docker.${NC}"
    exit 1
  fi
  echo -e "${GREEN}[OK] Docker Compose gefunden: $(docker compose version --short)${NC}"

  if ! command -v openssl &> /dev/null; then
    echo -e "${RED}[FEHLER] openssl nicht gefunden. Bitte installiere openssl.${NC}"
    exit 1
  fi
  echo -e "${GREEN}[OK] openssl gefunden${NC}"
  echo ""
}

collect_configuration() {
  echo -e "${BOLD}[2/4] Konfiguration${NC}"

  echo -e "Domain fuer tOS (z.B. tos.meinefirma.de):"
  read -r -p "  Domain: " APP_DOMAIN
  APP_DOMAIN="${APP_DOMAIN:-tos.example.com}"

  echo ""
  echo -e "SSL-Konfiguration:"
  echo "  [1] Let's Encrypt (Caddy - empfohlen fuer oeffentliche Domain)"
  echo "  [2] Externer Reverse Proxy (nginx, Apache, Cloudflare etc.)"
  read -r -p "  Auswahl [1/2]: " SSL_CHOICE

  SSL_MODE="external"
  LETSENCRYPT_EMAIL=""
  if [[ "${SSL_CHOICE}" == "1" ]]; then
    SSL_MODE="letsencrypt"
    read -r -p "  E-Mail fuer Let's Encrypt: " LETSENCRYPT_EMAIL
  fi

  echo ""
}

generate_secrets() {
  echo -e "${BOLD}[3/4] Secrets generieren...${NC}"

  POSTGRES_PASSWORD=$(openssl rand -hex 32)
  JWT_SECRET=$(openssl rand -hex 32)
  ENCRYPTION_KEY=$(openssl rand -hex 32)
  NEXTAUTH_SECRET=$(openssl rand -hex 32)
  KEYCLOAK_ADMIN_PASSWORD=$(openssl rand -base64 24 | tr -d '/+=' | head -c 32)

  # Generate SETUP_TOKEN
  if command -v uuidgen &> /dev/null; then
    SETUP_TOKEN=$(uuidgen | tr '[:upper:]' '[:lower:]')
  else
    SETUP_TOKEN=$(cat /proc/sys/kernel/random/uuid 2>/dev/null || openssl rand -hex 16)
  fi

  echo -e "${GREEN}[OK] Secrets generiert${NC}"
  echo ""

  # docker/.env erstellen
  cat > "${SCRIPT_DIR}/docker/.env" << EOF
# =============================================================================
# tOS Production Configuration - Generated by install.sh on $(date)
# =============================================================================

# ---- Domain -----------------------------------------------------------------
APP_DOMAIN=${APP_DOMAIN}
LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}

# ---- PostgreSQL -------------------------------------------------------------
POSTGRES_USER=tos_user
POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
POSTGRES_DB=tos_db
POSTGRES_PORT=5432

# ---- Redis ------------------------------------------------------------------
REDIS_PORT=6379

# ---- Keycloak ---------------------------------------------------------------
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=${KEYCLOAK_ADMIN_PASSWORD}
KEYCLOAK_PORT=8080
KEYCLOAK_REALM=tOS

# ---- Application Secrets ---------------------------------------------------
JWT_SECRET=${JWT_SECRET}
ENCRYPTION_KEY=${ENCRYPTION_KEY}
NEXTAUTH_SECRET=${NEXTAUTH_SECRET}

# ---- Keycloak OAuth Clients ------------------------------------------------
KEYCLOAK_CLIENT_ID=tos-backend
KEYCLOAK_CLIENT_SECRET=
NEXTAUTH_KEYCLOAK_CLIENT_ID=tos-nextauth
NEXTAUTH_KEYCLOAK_CLIENT_SECRET=

# ---- Setup Token (nach Einrichtung entfernen) -------------------------------
SETUP_TOKEN=${SETUP_TOKEN}
EOF

  echo -e "${GREEN}[OK] Konfigurationsdatei erstellt: docker/.env${NC}"
  echo ""
}

start_services() {
  echo -e "${BOLD}[4/4] Dienste starten...${NC}"

  cd "${SCRIPT_DIR}/docker"

  if [[ "${SSL_MODE}" == "letsencrypt" ]]; then
    echo -e "${YELLOW}Starte alle Dienste mit Let's Encrypt (SSL)...${NC}"
    docker compose -f docker-compose.prod.yml --profile ssl up -d --build
  else
    echo -e "${YELLOW}Starte alle Dienste ohne SSL (externer Reverse Proxy)...${NC}"
    docker compose -f docker-compose.prod.yml up -d --build
    echo -e "${YELLOW}Hinweis: Konfiguriere deinen Reverse Proxy fuer Ports 3000 (Web), 3001 (API) und 8080 (Keycloak).${NC}"
  fi

  echo ""
  echo -e "${YELLOW}Warte auf API-Bereitschaft (max. 3 Minuten)...${NC}"
  API_URL="http://localhost:3001/api/v1/health/liveness"
  for i in $(seq 1 36); do
    if curl -sf "${API_URL}" > /dev/null 2>&1; then
      echo ""
      echo -e "${GREEN}[OK] API ist bereit!${NC}"
      break
    fi
    if [[ $i -eq 36 ]]; then
      echo ""
      echo -e "${RED}[WARNUNG] API hat nicht innerhalb von 3 Minuten geantwortet.${NC}"
      echo -e "  Pruefe die Logs mit: docker compose -f docker/docker-compose.prod.yml logs api"
      echo -e "  Die Dienste laufen moeglicherweise noch hoch. Pruefe den Status mit:"
      echo -e "  docker compose -f docker/docker-compose.prod.yml ps"
      break
    fi
    echo -n "."
    sleep 5
  done
  echo ""
  cd "${SCRIPT_DIR}"
}

print_completion() {
  local SETUP_URL
  if [[ "${SSL_MODE}" == "letsencrypt" ]]; then
    SETUP_URL="https://${APP_DOMAIN}/setup?token=${SETUP_TOKEN}"
  else
    SETUP_URL="http://localhost:3000/setup?token=${SETUP_TOKEN}"
  fi

  echo ""
  echo -e "${GREEN}${BOLD}================================================================${NC}"
  echo -e "${GREEN}${BOLD}  Infrastruktur erfolgreich gestartet!${NC}"
  echo -e "${GREEN}${BOLD}================================================================${NC}"
  echo ""
  echo -e "  Fahre jetzt mit der Einrichtung im Browser fort:"
  echo ""
  echo -e "  ${BOLD}${BLUE}${SETUP_URL}${NC}"
  echo ""
  echo -e "${YELLOW}  WICHTIG: Notiere dir diesen Setup-Token:${NC}"
  echo -e "  ${BOLD}${SETUP_TOKEN}${NC}"
  echo ""
  echo -e "  Der Token wird nur einmal angezeigt und ist in"
  echo -e "  docker/.env gespeichert (SETUP_TOKEN=...)."
  echo ""
  echo -e "  Nach der Einrichtung kannst du SETUP_TOKEN aus"
  echo -e "  docker/.env entfernen."
  echo ""
  echo -e "  Nuetzliche Befehle:"
  echo -e "  ${BOLD}docker compose -f docker/docker-compose.prod.yml logs -f${NC}     # Alle Logs"
  echo -e "  ${BOLD}docker compose -f docker/docker-compose.prod.yml ps${NC}          # Service Status"
  echo -e "  ${BOLD}docker compose -f docker/docker-compose.prod.yml down${NC}        # Stoppen"
  echo -e "  ${BOLD}docker compose -f docker/docker-compose.prod.yml up -d${NC}       # Starten"
  echo ""
}

main() {
  banner
  check_prerequisites
  collect_configuration
  generate_secrets
  start_services
  print_completion
}

main "$@"
