#!/bin/bash

# AI Tax Agent Infrastructure Deployment Script
# Supports multiple environments: local, development, production

set -e

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

# Logging functions
log_info() {
    echo -e "${BLUE}ℹ️  $1${NC}"
}

log_success() {
    echo -e "${GREEN}✅ $1${NC}"
}

log_warning() {
    echo -e "${YELLOW}⚠️  $1${NC}"
}

log_error() {
    echo -e "${RED}❌ $1${NC}"
}

# Script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INFRA_DIR="$(dirname "$SCRIPT_DIR")"
PROJECT_ROOT="$(dirname "$INFRA_DIR")"

# Usage
usage() {
    cat << EOF
Usage: $0 <environment> <stack> [options]

Environments:
  local         - Local development (localhost)
  development   - Development server (dev.harkon.co.uk)
  production    - Production server (harkon.co.uk)

Stacks:
  all           - Deploy all stacks
  infrastructure - Core infrastructure (Vault, MinIO, DBs, Redis, NATS)
  monitoring    - Monitoring stack (Prometheus, Grafana, Loki)
  services      - Application services
  external      - External services (Traefik, Authentik, Gitea)
  down          - Stop and remove all stacks

Options:
  --build       - Build images before deploying
  --pull        - Pull images before deploying
  --force       - Force recreate containers

Examples:
  $0 local all
  $0 production infrastructure
  $0 development services --build
  $0 production down

EOF
    exit 1
}

# Check arguments
if [ $# -lt 2 ]; then
    usage
fi

ENVIRONMENT=$1
STACK=$2
shift 2

# Validate environment
case $ENVIRONMENT in
    local|development|production)
        ;;
    *)
        log_error "Invalid environment: $ENVIRONMENT"
        usage
        ;;
esac

# Paths
ENV_FILE="$INFRA_DIR/environments/$ENVIRONMENT/.env"
BASE_DIR="$INFRA_DIR/base"

# Check if environment file exists
if [ ! -f "$ENV_FILE" ]; then
    log_error "Environment file not found: $ENV_FILE"
    log_info "Copy from template: cp $INFRA_DIR/environments/$ENVIRONMENT/.env.example $ENV_FILE"
    exit 1
fi

# Load environment variables
set -a
source "$ENV_FILE"
set +a

log_info "Deploying AI Tax Agent Infrastructure"
echo "  Environment: $ENVIRONMENT"
echo "  Stack: $STACK"
echo "  Env File: $ENV_FILE"
echo ""

# Docker Compose command builder
compose_cmd() {
    local file=$1
    shift

    # For local environment, use the new unified compose.yaml
    if [ "$ENVIRONMENT" = "local" ] && [ "$file" = "all" ]; then
        docker compose -f "$INFRA_DIR/compose/compose.yaml" -f "$INFRA_DIR/compose/compose.override.yaml" --env-file "$ENV_FILE" --project-name "ai-tax-agent" "$@"
        return
    fi

    # For other environments or specific stacks, keep existing behavior for now
    # or adapt as needed. The goal is to eventually unify everything.
    # If file is 'infrastructure.yaml', etc., we might still want to use base/
    # directly for production to avoid local overrides.

    docker compose -f "$BASE_DIR/$file" --env-file "$ENV_FILE" --project-name "ai-tax-agent-$ENVIRONMENT" "$@"
}

# Deploy infrastructure stack
deploy_infrastructure() {
    log_info "Deploying infrastructure stack..."
    compose_cmd "infrastructure.yaml" up -d "$@"
    log_success "Infrastructure stack deployed"
}

# Deploy monitoring stack
deploy_monitoring() {
    log_info "Deploying monitoring stack..."
    compose_cmd "monitoring.yaml" up -d "$@"
    log_success "Monitoring stack deployed"
}

# Deploy services stack
deploy_services() {
    log_info "Deploying services stack..."
    compose_cmd "services.yaml" up -d "$@"
    log_success "Services stack deployed"
}

# Deploy external services stack
deploy_external() {
    log_info "Deploying external services stack..."

    if [ "$ENVIRONMENT" = "production" ] || [ "$ENVIRONMENT" = "development" ]; then
        log_warning "External services (Traefik, Authentik, Gitea) may already exist on this server"
        read -p "Do you want to deploy external services? (y/N) " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "Skipping external services"
            return
        fi
    fi

    compose_cmd "external.yaml" up -d "$@"
    log_success "External services stack deployed"
}

# Stop all stacks
stop_all() {
    log_info "Stopping all stacks..."

    if [ -f "$BASE_DIR/services.yaml" ]; then
        compose_cmd "services.yaml" down
    fi

    if [ -f "$BASE_DIR/monitoring.yaml" ]; then
        compose_cmd "monitoring.yaml" down
    fi

    if [ -f "$BASE_DIR/infrastructure.yaml" ]; then
        compose_cmd "infrastructure.yaml" down
    fi

    if [ -f "$BASE_DIR/external.yaml" ]; then
        log_warning "External services not stopped (may be shared)"
    fi

    log_success "All stacks stopped"
}

# Deploy all stacks
deploy_all() {
    log_info "Deploying all stacks..."

    # Check if networks exist
    if ! docker network inspect apa-frontend >/dev/null 2>&1; then
        log_warning "Network 'apa-frontend' does not exist. Creating..."
        docker network create apa-frontend
    fi

    if ! docker network inspect apa-backend >/dev/null 2>&1; then
        log_warning "Network 'apa-backend' does not exist. Creating..."
        docker network create apa-backend
    fi

    # Deploy in order
    if [ "$ENVIRONMENT" = "local" ]; then
        log_info "Deploying unified stack for local environment..."
        compose_cmd "all" up -d "$@"
    else
        deploy_infrastructure "$@"
        sleep 5

        deploy_monitoring "$@"
        sleep 5

        deploy_services "$@"
    fi

    log_success "All stacks deployed successfully!"
    echo ""
    log_info "Access your services:"
    echo "  - Grafana: https://grafana.$DOMAIN"
    echo "  - Prometheus: https://prometheus.$DOMAIN"
    echo "  - Vault: https://vault.$DOMAIN"
    echo "  - MinIO: https://minio.$DOMAIN"
    echo "  - UI Review: https://ui-review.$DOMAIN"
}

# Main deployment logic
case $STACK in
    all)
        deploy_all "$@"
        ;;
    infrastructure)
        deploy_infrastructure "$@"
        ;;
    monitoring)
        deploy_monitoring "$@"
        ;;
    services)
        deploy_services "$@"
        ;;
    external)
        deploy_external "$@"
        ;;
    down)
        stop_all
        ;;
    *)
        log_error "Invalid stack: $STACK"
        usage
        ;;
esac

log_success "Deployment complete!"
