#!/bin/bash
# Monaco USA Portal - Production Deployment Script
# For Debian/Ubuntu Linux servers
#
# Usage: ./deploy.sh [command]
# Commands:
#   setup     - First-time setup (install Docker, configure firewall)
#   deploy    - Build and start all services
#   update    - Pull latest changes and rebuild portal
#   logs      - View logs
#   status    - Check service status
#   backup    - Backup database
#   restore   - Restore database from backup

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Configuration
COMPOSE_FILE="docker-compose.nginx.yml"
PROJECT_NAME="monacousa"

log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Check if running as root
check_root() {
    if [ "$EUID" -ne 0 ]; then
        log_error "Please run as root (sudo ./deploy.sh)"
        exit 1
    fi
}

# Install Docker and Docker Compose on Debian
install_docker() {
    log_info "Installing Docker..."

    # Remove old versions
    apt-get remove -y docker docker-engine docker.io containerd runc 2>/dev/null || true

    # Install dependencies
    apt-get update
    apt-get install -y \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg \
        lsb-release

    # Add Docker's official GPG key
    install -m 0755 -d /etc/apt/keyrings
    curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    chmod a+r /etc/apt/keyrings/docker.gpg

    # Add repository
    echo \
        "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
        $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
        tee /etc/apt/sources.list.d/docker.list > /dev/null

    # Install Docker
    apt-get update
    apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

    # Start and enable Docker
    systemctl start docker
    systemctl enable docker

    log_info "Docker installed successfully"
}

# Configure firewall
configure_firewall() {
    log_info "Configuring firewall..."

    # Install ufw if not present
    apt-get install -y ufw

    # Allow SSH, HTTP, HTTPS
    ufw allow ssh
    ufw allow http
    ufw allow https

    # Enable firewall
    ufw --force enable

    log_info "Firewall configured (SSH, HTTP, HTTPS allowed)"
}

# First-time setup
setup() {
    check_root
    log_info "Starting first-time setup..."

    # Update system
    apt-get update && apt-get upgrade -y

    # Install Docker
    install_docker

    # Configure firewall
    configure_firewall

    # Install useful tools
    apt-get install -y htop nano git apache2-utils

    # Check for .env file
    if [ ! -f .env ]; then
        log_warn ".env file not found!"
        log_info "Copy .env.production.example to .env and configure it:"
        echo "  cp .env.production.example .env"
        echo "  nano .env"
    fi

    log_info "Setup complete! Next steps:"
    echo "  1. Configure .env file: nano .env"
    echo "  2. Deploy: ./deploy.sh deploy"
}

# Generate secrets helper
generate_secrets() {
    log_info "Generating secrets..."
    echo ""
    echo "JWT_SECRET=$(openssl rand -base64 32)"
    echo "POSTGRES_PASSWORD=$(openssl rand -base64 32)"
    echo "SECRET_KEY_BASE=$(openssl rand -base64 64)"
    echo ""
    log_info "Copy these values to your .env file"
}

# Generate Kong configuration with API keys from .env
generate_kong_config() {
    log_info "Generating Kong configuration..."

    # Load environment variables
    if [ -f .env ]; then
        export $(grep -v '^#' .env | grep -E '^(ANON_KEY|SERVICE_ROLE_KEY)=' | xargs)
    fi

    if [ -z "$ANON_KEY" ] || [ -z "$SERVICE_ROLE_KEY" ]; then
        log_error "ANON_KEY and SERVICE_ROLE_KEY must be set in .env"
        exit 1
    fi

    cat > supabase/docker/kong.yml << KONG_EOF
_format_version: "2.1"
_transform: true

consumers:
  - username: ANON
    keyauth_credentials:
      - key: ${ANON_KEY}
  - username: SERVICE_ROLE
    keyauth_credentials:
      - key: ${SERVICE_ROLE_KEY}

acls:
  - consumer: ANON
    group: anon
  - consumer: SERVICE_ROLE
    group: admin

services:
  - name: auth-verify-redirect
    url: http://portal:3000/auth/verify
    routes:
      - name: auth-verify-redirect
        strip_path: false
        paths:
          - /auth/verify
        preserve_host: false
    plugins:
      - name: cors

  - name: auth-v1-open
    url: http://auth:9999/verify
    routes:
      - name: auth-v1-open
        strip_path: true
        paths:
          - /auth/v1/verify
    plugins:
      - name: cors

  - name: auth-v1-open-callback
    url: http://auth:9999/callback
    routes:
      - name: auth-v1-open-callback
        strip_path: true
        paths:
          - /auth/v1/callback
    plugins:
      - name: cors

  - name: auth-v1-open-authorize
    url: http://auth:9999/authorize
    routes:
      - name: auth-v1-open-authorize
        strip_path: true
        paths:
          - /auth/v1/authorize
    plugins:
      - name: cors

  - name: auth-v1
    url: http://auth:9999/
    routes:
      - name: auth-v1
        strip_path: true
        paths:
          - /auth/v1/
    plugins:
      - name: cors
      - name: key-auth
        config:
          hide_credentials: false
      - name: acl
        config:
          hide_groups_header: true
          allow:
            - admin
            - anon

  - name: rest-v1
    url: http://rest:3000/
    routes:
      - name: rest-v1
        strip_path: true
        paths:
          - /rest/v1/
    plugins:
      - name: cors
      - name: key-auth
        config:
          hide_credentials: false
      - name: acl
        config:
          hide_groups_header: true
          allow:
            - admin
            - anon

  - name: realtime-v1-ws
    url: http://realtime:4000/socket
    routes:
      - name: realtime-v1-ws
        strip_path: true
        paths:
          - /realtime/v1/websocket
    plugins:
      - name: cors
      - name: key-auth
        config:
          hide_credentials: false
      - name: acl
        config:
          hide_groups_header: true
          allow:
            - admin
            - anon

  - name: realtime-v1
    url: http://realtime:4000/
    routes:
      - name: realtime-v1
        strip_path: true
        paths:
          - /realtime/v1/
    plugins:
      - name: cors
      - name: key-auth
        config:
          hide_credentials: false
      - name: acl
        config:
          hide_groups_header: true
          allow:
            - admin
            - anon

  - name: storage-v1-public
    url: http://storage:5000/object/public
    routes:
      - name: storage-v1-public
        strip_path: true
        paths:
          - /storage/v1/object/public
    plugins:
      - name: cors

  - name: storage-v1
    url: http://storage:5000/
    routes:
      - name: storage-v1
        strip_path: true
        paths:
          - /storage/v1/
    plugins:
      - name: cors
      - name: key-auth
        config:
          hide_credentials: false
      - name: acl
        config:
          hide_groups_header: true
          allow:
            - admin
            - anon

  - name: meta
    url: http://meta:8080/
    routes:
      - name: meta
        strip_path: true
        paths:
          - /pg/
    plugins:
      - name: key-auth
        config:
          hide_credentials: false
      - name: acl
        config:
          hide_groups_header: true
          allow:
            - admin
KONG_EOF

    log_info "Kong configuration generated with production API keys"
}

# Deploy/start services
deploy() {
    log_info "Deploying Monaco USA Portal..."

    # Check for .env file
    if [ ! -f .env ]; then
        log_error ".env file not found! Copy .env.production.example to .env first."
        exit 1
    fi

    # Generate Kong config with production API keys
    generate_kong_config

    # Pull latest portal image and start all services
    docker compose -f $COMPOSE_FILE -p $PROJECT_NAME pull portal
    docker compose -f $COMPOSE_FILE -p $PROJECT_NAME up -d

    log_info "Deployment complete!"
    log_info "Waiting for services to be healthy..."
    sleep 10

    # Show status
    docker compose -f $COMPOSE_FILE -p $PROJECT_NAME ps

    log_info "Portal should be available at https://\$(grep DOMAIN .env | cut -d '=' -f2)"
}

# Update and rebuild
update() {
    log_info "Updating Monaco USA Portal..."

    # Pull latest code (if git repo)
    if [ -d .git ]; then
        git pull origin main
    fi

    # Rebuild only the portal service
    docker compose -f $COMPOSE_FILE -p $PROJECT_NAME build --no-cache portal

    # Restart portal with zero downtime
    docker compose -f $COMPOSE_FILE -p $PROJECT_NAME up -d --no-deps portal

    log_info "Update complete!"
}

# View logs
logs() {
    local service=${1:-""}
    if [ -z "$service" ]; then
        docker compose -f $COMPOSE_FILE -p $PROJECT_NAME logs -f --tail=100
    else
        docker compose -f $COMPOSE_FILE -p $PROJECT_NAME logs -f --tail=100 $service
    fi
}

# Check status
status() {
    log_info "Service Status:"
    docker compose -f $COMPOSE_FILE -p $PROJECT_NAME ps
    echo ""
    log_info "Resource Usage:"
    docker stats --no-stream $(docker compose -f $COMPOSE_FILE -p $PROJECT_NAME ps -q)
}

# Backup database
backup() {
    local backup_file="backup_$(date +%Y%m%d_%H%M%S).sql"
    log_info "Backing up database to $backup_file..."

    docker compose -f $COMPOSE_FILE -p $PROJECT_NAME exec -T db \
        pg_dump -U postgres postgres > "$backup_file"

    # Compress
    gzip "$backup_file"

    log_info "Backup complete: ${backup_file}.gz"
}

# Restore database
restore() {
    local backup_file=$1
    if [ -z "$backup_file" ]; then
        log_error "Usage: ./deploy.sh restore <backup_file.sql.gz>"
        exit 1
    fi

    log_warn "This will overwrite the current database!"
    read -p "Are you sure? (y/N) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        exit 1
    fi

    log_info "Restoring database from $backup_file..."

    # Decompress if needed
    if [[ "$backup_file" == *.gz ]]; then
        gunzip -c "$backup_file" | docker compose -f $COMPOSE_FILE -p $PROJECT_NAME exec -T db \
            psql -U postgres postgres
    else
        cat "$backup_file" | docker compose -f $COMPOSE_FILE -p $PROJECT_NAME exec -T db \
            psql -U postgres postgres
    fi

    log_info "Restore complete!"
}

# Stop all services
stop() {
    log_info "Stopping all services..."
    docker compose -f $COMPOSE_FILE -p $PROJECT_NAME down
    log_info "All services stopped"
}

# Restart all services
restart() {
    log_info "Restarting all services..."
    docker compose -f $COMPOSE_FILE -p $PROJECT_NAME restart
    log_info "All services restarted"
}

# Clean up unused Docker resources
cleanup() {
    log_info "Cleaning up unused Docker resources..."
    docker system prune -af --volumes
    log_info "Cleanup complete"
}

# Show help
help() {
    echo "Monaco USA Portal - Deployment Script"
    echo ""
    echo "Usage: ./deploy.sh [command]"
    echo ""
    echo "Commands:"
    echo "  setup           First-time server setup (install Docker, firewall)"
    echo "  generate-secrets Generate random secrets for .env"
    echo "  deploy          Build and start all services"
    echo "  update          Pull latest code and rebuild portal"
    echo "  stop            Stop all services"
    echo "  restart         Restart all services"
    echo "  status          Show service status and resource usage"
    echo "  logs [service]  View logs (optionally for specific service)"
    echo "  backup          Backup database to file"
    echo "  restore <file>  Restore database from backup"
    echo "  cleanup         Remove unused Docker resources"
    echo "  help            Show this help message"
    echo ""
    echo "Examples:"
    echo "  sudo ./deploy.sh setup        # First-time setup"
    echo "  ./deploy.sh deploy            # Deploy the portal"
    echo "  ./deploy.sh logs portal       # View portal logs"
    echo "  ./deploy.sh backup            # Backup database"
}

# Main command handler
case "${1:-help}" in
    setup)
        setup
        ;;
    generate-secrets)
        generate_secrets
        ;;
    deploy)
        deploy
        ;;
    update)
        update
        ;;
    stop)
        stop
        ;;
    restart)
        restart
        ;;
    status)
        status
        ;;
    logs)
        logs $2
        ;;
    backup)
        backup
        ;;
    restore)
        restore $2
        ;;
    cleanup)
        cleanup
        ;;
    help|--help|-h)
        help
        ;;
    *)
        log_error "Unknown command: $1"
        help
        exit 1
        ;;
esac
