#!/bin/bash
# =============================================================================
# 🐳 Plesk Docker Deployment Script
# =============================================================================
# Deploys pre-built Docker images to a Plesk server
# For building images locally, use: pnpm plesk:images
# =============================================================================

set -euo pipefail

# =============================================================================
# Configuration
# =============================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"

# Default paths (override via env vars)
REPO_PATH="${REPO_PATH:-/var/www/vhosts/yourdomain.com/git/customer-portal}"
COMPOSE_FILE="${COMPOSE_FILE:-$PROJECT_ROOT/docker/Prod - Portainer/docker-compose.yml}"
ENV_FILE="${ENV_FILE:-$PROJECT_ROOT/.env}"

# Image settings
IMAGE_FRONTEND="${IMAGE_FRONTEND:-portal-frontend}"
IMAGE_BACKEND="${IMAGE_BACKEND:-portal-backend}"
IMAGE_TAG="${IMAGE_TAG:-latest}"

# =============================================================================
# Colors and Logging
# =============================================================================
if [[ -t 1 ]]; then
  GREEN='\033[0;32m'
  YELLOW='\033[1;33m'
  RED='\033[0;31m'
  BLUE='\033[0;34m'
  NC='\033[0m'
else
  GREEN='' YELLOW='' RED='' BLUE='' NC=''
fi

log()   { echo -e "${GREEN}[PLESK]${NC} $*"; }
warn()  { echo -e "${YELLOW}[PLESK]${NC} WARNING: $*"; }
error() { echo -e "${RED}[PLESK]${NC} ERROR: $*"; exit 1; }
info()  { echo -e "${BLUE}[PLESK]${NC} $*"; }

# =============================================================================
# Usage
# =============================================================================
usage() {
  cat <<EOF
Deploy Docker images to Plesk server.

Usage: $0 [COMMAND] [OPTIONS]

Commands:
  deploy      Full deployment (load images, run migrations, start services)
  start       Start services
  stop        Stop services
  restart     Restart services
  status      Show service status
  logs        Show service logs
  load        Load Docker images from tarballs
  help        Show this help

Options:
  --env-file <path>   Path to environment file (default: .env)
  --compose <path>    Path to docker-compose file
  --tag <tag>         Image tag to use (default: latest)

Examples:
  $0 deploy                    # Full deployment
  $0 load                      # Load images from tarballs
  $0 status                    # Check service status
  $0 logs backend              # Show backend logs
EOF
  exit 0
}

# =============================================================================
# Pre-flight Checks
# =============================================================================
preflight_checks() {
  log "🔍 Running pre-flight checks..."
  
  # Check Docker
  if ! command -v docker &> /dev/null; then
    error "Docker is not installed. Please install Docker first."
  fi
  
  # Check Docker daemon
  if ! docker info >/dev/null 2>&1; then
    error "Docker daemon is not running."
  fi
  
  # Check docker compose
  if ! docker compose version >/dev/null 2>&1; then
    error "Docker Compose V2 is required. Please upgrade Docker."
  fi
  
  # Check environment file
  if [[ ! -f "$ENV_FILE" ]]; then
    if [[ -f "$PROJECT_ROOT/.env.production.example" ]]; then
      log "Creating environment file from template..."
      cp "$PROJECT_ROOT/.env.production.example" "$ENV_FILE"
      warn "Please edit $ENV_FILE with your production values!"
      error "Production environment not configured. Please set up .env"
    else
      error "Environment file not found: $ENV_FILE"
    fi
  fi
  
  # Check compose file
  if [[ ! -f "$COMPOSE_FILE" ]]; then
    error "Docker Compose file not found: $COMPOSE_FILE"
  fi
  
  log "✅ Pre-flight checks passed"
}

# =============================================================================
# Load Images from Tarballs
# =============================================================================
load_images() {
  log "📦 Loading Docker images..."
  
  local search_dir="${1:-$PROJECT_ROOT}"
  local loaded=0
  
  for img in "$IMAGE_FRONTEND" "$IMAGE_BACKEND"; do
    local tarball
    
    # Try compressed first, then uncompressed
    if [[ -f "$search_dir/${img}.latest.tar.gz" ]]; then
      tarball="$search_dir/${img}.latest.tar.gz"
      log "Loading $tarball..."
      gunzip -c "$tarball" | docker load
      loaded=$((loaded + 1))
    elif [[ -f "$search_dir/${img}.${IMAGE_TAG}.tar.gz" ]]; then
      tarball="$search_dir/${img}.${IMAGE_TAG}.tar.gz"
      log "Loading $tarball..."
      gunzip -c "$tarball" | docker load
      loaded=$((loaded + 1))
    elif [[ -f "$search_dir/${img}.latest.tar" ]]; then
      tarball="$search_dir/${img}.latest.tar"
      log "Loading $tarball..."
      docker load -i "$tarball"
      loaded=$((loaded + 1))
    elif [[ -f "$search_dir/${img}.${IMAGE_TAG}.tar" ]]; then
      tarball="$search_dir/${img}.${IMAGE_TAG}.tar"
      log "Loading $tarball..."
      docker load -i "$tarball"
      loaded=$((loaded + 1))
    else
      warn "No tarball found for $img"
    fi
  done
  
  if [[ $loaded -eq 0 ]]; then
    error "No image tarballs found in $search_dir"
  fi
  
  log "✅ Loaded $loaded images"
}

# =============================================================================
# Docker Compose Helpers
# =============================================================================
dc() {
  docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" "$@"
}

# =============================================================================
# Deployment
# =============================================================================
deploy() {
  log "🚀 Starting Plesk Docker deployment..."
  
  preflight_checks
  
  # Check if images exist, if not try to load from tarballs
  if ! docker image inspect "${IMAGE_FRONTEND}:latest" >/dev/null 2>&1 || \
     ! docker image inspect "${IMAGE_BACKEND}:latest" >/dev/null 2>&1; then
    log "Images not found, attempting to load from tarballs..."
    load_images "$PROJECT_ROOT" || true
  fi
  
  # Verify images exist
  for img in "${IMAGE_FRONTEND}:latest" "${IMAGE_BACKEND}:latest"; do
    if ! docker image inspect "$img" >/dev/null 2>&1; then
      error "Required image not found: $img. Build images first with: pnpm plesk:images"
    fi
  done
  
  # Start infrastructure first
  log "🗄️ Starting database and cache..."
  dc up -d database cache
  
  # Wait for database
  log "⏳ Waiting for database..."
  local timeout=60
  while [[ $timeout -gt 0 ]]; do
    if dc exec -T database pg_isready -U portal -d portal_prod 2>/dev/null; then
      log "✅ Database is ready"
      break
    fi
    sleep 2
    timeout=$((timeout - 2))
  done
  
  if [[ $timeout -eq 0 ]]; then
    error "Database failed to start within 60 seconds"
  fi
  
  # Start application services
  log "🚀 Starting application services..."
  dc up -d frontend backend
  
  # Health check
  log "🏥 Waiting for services to be healthy..."
  sleep 15
  
  if dc ps | grep -q "unhealthy"; then
    warn "Some services may not be healthy - check logs with: $0 logs"
  else
    log "✅ All services healthy"
  fi
  
  log "🎉 Plesk Docker deployment completed!"
  echo ""
  info "📝 Next steps:"
  echo "  1. Configure Plesk reverse proxy to point to port 3000 (frontend)"
  echo "  2. Set up SSL certificates in Plesk"
  echo "  3. Test your application at your domain"
  echo ""
  info "📋 Useful commands:"
  echo "  $0 status    - Check service status"
  echo "  $0 logs      - View logs"
  echo "  $0 restart   - Restart services"
}

# =============================================================================
# Service Management
# =============================================================================
start_services() {
  preflight_checks
  log "▶️ Starting services..."
  dc up -d
  log "✅ Services started"
}

stop_services() {
  log "⏹️ Stopping services..."
  dc down
  log "✅ Services stopped"
}

restart_services() {
  log "🔄 Restarting services..."
  dc restart
  log "✅ Services restarted"
}

show_status() {
  log "📊 Service Status:"
  dc ps
  echo ""
  log "🏥 Health Status:"
  dc ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"
}

show_logs() {
  local service="${1:-}"
  if [[ -n "$service" ]]; then
    dc logs -f "$service"
  else
    dc logs -f
  fi
}

# =============================================================================
# Argument Parsing
# =============================================================================
COMMAND="${1:-help}"
shift || true

while [[ $# -gt 0 ]]; do
  case "$1" in
    --env-file) ENV_FILE="$2"; shift 2 ;;
    --compose)  COMPOSE_FILE="$2"; shift 2 ;;
    --tag)      IMAGE_TAG="$2"; shift 2 ;;
    -h|--help)  usage ;;
    *)          break ;;
  esac
done

export IMAGE_TAG

# =============================================================================
# Main
# =============================================================================
case "$COMMAND" in
  deploy)   deploy ;;
  start)    start_services ;;
  stop)     stop_services ;;
  restart)  restart_services ;;
  status)   show_status ;;
  logs)     show_logs "$@" ;;
  load)     preflight_checks; load_images "${1:-$PROJECT_ROOT}" ;;
  help|*)   usage ;;
esac
