#!/bin/bash
# EN: Deploy GoodGo Platform production services to Kubernetes production environment
# VI: Trien khai cac service production cua GoodGo Platform len moi truong production Kubernetes
#
# Prerequisites:
#   - kubectl configured with production cluster access (KUBECONFIG env var)
#   - Docker images pushed to Docker Hub (goodgo/*:<commit-sha>)
#   - Secrets created via kubectl or sealed-secrets (see secrets.yaml.example)
#
# Usage:
#   export KUBECONFIG=/path/to/kubeconfig
#   ./scripts/deploy/deploy-prod.sh
#   ./scripts/deploy/deploy-prod.sh --service iam-service    # Deploy single service
#   ./scripts/deploy/deploy-prod.sh --dry-run                # Dry run mode
#   ./scripts/deploy/deploy-prod.sh --rollback iam-service   # Rollback service
#   ./scripts/deploy/deploy-prod.sh --migrate                # Run DB migrations before deploy

set -euo pipefail

# EN: Color output helpers
# VI: Ham ho tro mau output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
NC='\033[0m' # No Color

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
DEPLOY_DIR="${ROOT_DIR}/deployments/production/kubernetes"
NAMESPACE="production"
DRY_RUN=""
SINGLE_SERVICE=""
ROLLBACK_SERVICE=""
RUN_MIGRATIONS=false

# EN: Production services list
# VI: Danh sach service production
PROD_SERVICES=(
    "iam-service"
    "merchant-service"
    "catalog-service"
    "order-service"
    "fnb-engine"
    "inventory-service"
    "wallet-service"
    "booking-service"
)

# EN: Parse arguments
# VI: Phan tich tham so
while [[ $# -gt 0 ]]; do
  case $1 in
    --dry-run)
      DRY_RUN="--dry-run=client"
      echo -e "${YELLOW}[DRY RUN] No changes will be applied${NC}"
      shift
      ;;
    --service)
      SINGLE_SERVICE="$2"
      shift 2
      ;;
    --rollback)
      ROLLBACK_SERVICE="$2"
      shift 2
      ;;
    --migrate)
      RUN_MIGRATIONS=true
      shift
      ;;
    --help|-h)
      echo "Usage: $0 [OPTIONS]"
      echo ""
      echo "Options:"
      echo "  --dry-run                 Preview changes without applying"
      echo "  --service <name>          Deploy a single service"
      echo "  --rollback <name>         Rollback a service to previous revision"
      echo "  --migrate                 Run EF Core database migrations before deploy"
      echo "  -h, --help                Show this help"
      echo ""
      echo "Services: ${PROD_SERVICES[*]}"
      exit 0
      ;;
    *)
      echo -e "${RED}Unknown option: $1${NC}"
      echo "Use --help for usage information"
      exit 1
      ;;
  esac
done

# =============================================================================
# EN: Pre-flight checks
# VI: Kiem tra truoc khi deploy
# =============================================================================

echo -e "${MAGENTA}=== GoodGo Platform - Production Deployment ===${NC}"
echo ""

# EN: Require explicit confirmation for production
# VI: Yeu cau xac nhan ro rang cho production
if [ -z "$DRY_RUN" ] && [ -z "$ROLLBACK_SERVICE" ]; then
    echo -e "${RED}WARNING: You are about to deploy to PRODUCTION!${NC}"
    echo -e "${YELLOW}Namespace: ${NAMESPACE}${NC}"
    if [ -n "$SINGLE_SERVICE" ]; then
        echo -e "${YELLOW}Service: ${SINGLE_SERVICE}${NC}"
    else
        echo -e "${YELLOW}Services: ALL (${#PROD_SERVICES[@]} services)${NC}"
    fi
    echo ""
    read -p "Type 'yes' to confirm: " confirm
    if [ "$confirm" != "yes" ]; then
        echo -e "${YELLOW}Deployment cancelled${NC}"
        exit 0
    fi
fi

# EN: Verify KUBECONFIG
# VI: Xac minh KUBECONFIG
if [ -z "${KUBECONFIG:-}" ]; then
    echo -e "${RED}KUBECONFIG environment variable not set${NC}"
    echo "Usage: export KUBECONFIG=/path/to/kubeconfig && $0"
    exit 1
fi

# EN: Verify kubectl connectivity
# VI: Xac minh ket noi kubectl
echo -e "${BLUE}Verifying kubectl connectivity...${NC}"
if ! kubectl cluster-info &>/dev/null; then
    echo -e "${RED}Cannot connect to Kubernetes cluster. Check KUBECONFIG.${NC}"
    exit 1
fi

# EN: Verify namespace exists
# VI: Xac minh namespace ton tai
if ! kubectl get namespace "${NAMESPACE}" &>/dev/null; then
    echo -e "${YELLOW}Namespace '${NAMESPACE}' does not exist. Creating...${NC}"
    kubectl apply -f "${DEPLOY_DIR}/namespace.yaml" ${DRY_RUN}
fi

# EN: Verify manifests directory
# VI: Xac minh thu muc manifests
if [ ! -d "${DEPLOY_DIR}" ]; then
    echo -e "${RED}Deployment directory not found: ${DEPLOY_DIR}${NC}"
    exit 1
fi

echo -e "${GREEN}Pre-flight checks passed${NC}"
echo ""

# =============================================================================
# EN: Handle rollback
# VI: Xu ly rollback
# =============================================================================

if [ -n "$ROLLBACK_SERVICE" ]; then
    echo -e "${YELLOW}Rolling back ${ROLLBACK_SERVICE}...${NC}"

    # EN: Show rollout history
    # VI: Hien thi lich su rollout
    echo -e "${BLUE}Rollout history:${NC}"
    kubectl rollout history "deployment/${ROLLBACK_SERVICE}" -n "${NAMESPACE}" 2>/dev/null || {
        echo -e "${RED}Deployment '${ROLLBACK_SERVICE}' not found in namespace '${NAMESPACE}'${NC}"
        exit 1
    }

    echo ""
    read -p "Rollback to previous revision? (yes/no): " confirm_rollback
    if [ "$confirm_rollback" = "yes" ]; then
        kubectl rollout undo "deployment/${ROLLBACK_SERVICE}" -n "${NAMESPACE}"
        echo -e "${BLUE}Waiting for rollback to complete...${NC}"
        kubectl rollout status "deployment/${ROLLBACK_SERVICE}" -n "${NAMESPACE}" --timeout=180s
        echo -e "${GREEN}Rollback of ${ROLLBACK_SERVICE} completed${NC}"
    else
        echo -e "${YELLOW}Rollback cancelled${NC}"
    fi
    exit 0
fi

# =============================================================================
# EN: Run database migrations (optional)
# VI: Chay database migrations (tuy chon)
# =============================================================================

if [ "$RUN_MIGRATIONS" = true ]; then
    echo -e "${BLUE}[0/6] Running database migrations...${NC}"

    # EN: Check dotnet-ef tool
    # VI: Kiem tra dotnet-ef tool
    if ! command -v dotnet &>/dev/null; then
        echo -e "${RED}dotnet SDK not found. Install .NET 10 SDK for migrations.${NC}"
        exit 1
    fi
    dotnet tool install --global dotnet-ef 2>/dev/null || true

    declare -A MIGRATION_MAP=(
        ["iam-service"]="services/iam-service-net/src/IamService.Infrastructure/IamService.Infrastructure.csproj|services/iam-service-net/src/IamService.API/IamService.API.csproj|NEON_IAM_DATABASE_URL_PRODUCTION"
        ["merchant-service"]="services/merchant-service-net/src/MerchantService.Infrastructure/MerchantService.Infrastructure.csproj|services/merchant-service-net/src/MerchantService.API/MerchantService.API.csproj|NEON_MERCHANT_DATABASE_URL_PRODUCTION"
        ["order-service"]="services/order-service-net/src/OrderService.Infrastructure/OrderService.Infrastructure.csproj|services/order-service-net/src/OrderService.API/OrderService.API.csproj|NEON_ORDER_DATABASE_URL_PRODUCTION"
        ["fnb-engine"]="services/fnb-engine-net/src/FnbEngine.Infrastructure/FnbEngine.Infrastructure.csproj|services/fnb-engine-net/src/FnbEngine.API/FnbEngine.API.csproj|NEON_FNB_DATABASE_URL_PRODUCTION"
        ["inventory-service"]="services/inventory-service-net/src/InventoryService.Infrastructure/InventoryService.Infrastructure.csproj|services/inventory-service-net/src/InventoryService.API/InventoryService.API.csproj|NEON_INVENTORY_DATABASE_URL_PRODUCTION"
        ["wallet-service"]="services/wallet-service-net/src/WalletService.Infrastructure/WalletService.Infrastructure.csproj|services/wallet-service-net/src/WalletService.API/WalletService.API.csproj|NEON_WALLET_DATABASE_URL_PRODUCTION"
        ["catalog-service"]="services/catalog-service-net/src/CatalogService.Infrastructure/CatalogService.Infrastructure.csproj|services/catalog-service-net/src/CatalogService.API/CatalogService.API.csproj|NEON_CATALOG_DATABASE_URL_PRODUCTION"
        ["booking-service"]="services/booking-service-net/src/BookingService.Infrastructure/BookingService.Infrastructure.csproj|services/booking-service-net/src/BookingService.API/BookingService.API.csproj|NEON_BOOKING_DATABASE_URL_PRODUCTION"
    )

    for svc in "${PROD_SERVICES[@]}"; do
        if [ -n "$SINGLE_SERVICE" ] && [ "$SINGLE_SERVICE" != "$svc" ]; then
            continue
        fi

        IFS='|' read -r infra_proj startup_proj db_env_var <<< "${MIGRATION_MAP[$svc]}"
        infra_path="${ROOT_DIR}/${infra_proj}"
        startup_path="${ROOT_DIR}/${startup_proj}"

        if [ -f "$infra_path" ] && [ -f "$startup_path" ]; then
            echo -e "${BLUE}  Migrating ${svc}...${NC}"
            if [ -n "${!db_env_var:-}" ]; then
                ConnectionStrings__DefaultConnection="${!db_env_var}" \
                    dotnet ef database update \
                    --project "$infra_path" \
                    --startup-project "$startup_path" 2>&1 || {
                    echo -e "${RED}  Migration failed for ${svc}${NC}"
                    read -p "Continue deployment? (yes/no): " continue_deploy
                    if [ "$continue_deploy" != "yes" ]; then
                        exit 1
                    fi
                }
                echo -e "${GREEN}  ${svc} migrated${NC}"
            else
                echo -e "${YELLOW}  Skipping ${svc} - env var ${db_env_var} not set${NC}"
            fi
        else
            echo -e "${YELLOW}  Skipping ${svc} - project files not found${NC}"
        fi
    done
    echo ""
fi

# =============================================================================
# EN: Step 1 - Apply namespace
# VI: Buoc 1 - Tao namespace
# =============================================================================
echo -e "${BLUE}[1/6] Applying namespace...${NC}"
kubectl apply -f "${DEPLOY_DIR}/namespace.yaml" ${DRY_RUN}

# =============================================================================
# EN: Step 2 - Apply shared configuration
# VI: Buoc 2 - Ap dung cau hinh chung
# =============================================================================
echo -e "${BLUE}[2/6] Applying configuration...${NC}"
kubectl apply -f "${DEPLOY_DIR}/configmap.yaml" ${DRY_RUN}

# =============================================================================
# EN: Step 3 - Deploy infrastructure (Redis)
# VI: Buoc 3 - Trien khai ha tang (Redis)
# =============================================================================
echo -e "${BLUE}[3/6] Deploying infrastructure...${NC}"
if [ -z "$SINGLE_SERVICE" ] || [ "$SINGLE_SERVICE" = "redis" ]; then
    kubectl apply -f "${DEPLOY_DIR}/redis.yaml" ${DRY_RUN}
    echo -e "${GREEN}  redis deployed${NC}"
fi

# =============================================================================
# EN: Step 4 - Deploy backend services
# VI: Buoc 4 - Trien khai cac service backend
# =============================================================================
echo -e "${BLUE}[4/6] Deploying services...${NC}"

for svc in "${PROD_SERVICES[@]}"; do
    if [ -z "$SINGLE_SERVICE" ] || [ "$SINGLE_SERVICE" = "$svc" ]; then
        if [ -f "${DEPLOY_DIR}/${svc}.yaml" ]; then
            kubectl apply -f "${DEPLOY_DIR}/${svc}.yaml" ${DRY_RUN}
            echo -e "${GREEN}  ${svc} deployed${NC}"
        else
            echo -e "${YELLOW}  ${svc}.yaml not found, skipping${NC}"
        fi
    fi
done

# =============================================================================
# EN: Step 5 - Apply ingress routing
# VI: Buoc 5 - Ap dung dinh tuyen ingress
# =============================================================================
echo -e "${BLUE}[5/6] Applying ingress routing...${NC}"
if [ -z "$SINGLE_SERVICE" ]; then
    kubectl apply -f "${DEPLOY_DIR}/ingress.yaml" ${DRY_RUN}
fi

# =============================================================================
# EN: Step 6 - Wait for rollouts and verify
# VI: Buoc 6 - Cho rollout va xac minh
# =============================================================================
echo ""
echo -e "${BLUE}[6/6] Waiting for rollouts to complete...${NC}"

if [ -z "$DRY_RUN" ]; then
    FAILED=0
    for svc in "${PROD_SERVICES[@]}"; do
        if [ -z "$SINGLE_SERVICE" ] || [ "$SINGLE_SERVICE" = "$svc" ]; then
            echo -n "  ${svc}: "
            if kubectl rollout status "deployment/${svc}" -n "${NAMESPACE}" --timeout=180s 2>/dev/null; then
                echo -e "${GREEN}ready${NC}"
            else
                echo -e "${RED}FAILED${NC}"
                FAILED=$((FAILED + 1))
            fi
        fi
    done

    echo ""

    if [ $FAILED -gt 0 ]; then
        echo -e "${RED}WARNING: ${FAILED} service(s) did not complete rollout${NC}"
        echo -e "${YELLOW}Troubleshooting:${NC}"
        echo -e "  kubectl get pods -n ${NAMESPACE}"
        echo -e "  kubectl describe pod <pod-name> -n ${NAMESPACE}"
        echo -e "  kubectl logs -n ${NAMESPACE} -l app=<service-name> --tail=50"
        echo ""
        echo -e "${YELLOW}To rollback a failed service:${NC}"
        echo -e "  $0 --rollback <service-name>"
        exit 1
    fi

    # EN: Print deployment summary
    # VI: In tom tat deployment
    echo -e "${GREEN}=== Production Deployment Summary ===${NC}"
    echo ""
    echo -e "${BLUE}Pods:${NC}"
    kubectl get pods -n "${NAMESPACE}" -o wide --sort-by='.metadata.name' 2>/dev/null
    echo ""
    echo -e "${BLUE}Services:${NC}"
    kubectl get svc -n "${NAMESPACE}" 2>/dev/null
    echo ""
    echo -e "${BLUE}HPAs:${NC}"
    kubectl get hpa -n "${NAMESPACE}" 2>/dev/null
    echo ""
    echo -e "${BLUE}Ingress:${NC}"
    kubectl get ingress -n "${NAMESPACE}" 2>/dev/null
fi

echo ""
echo -e "${GREEN}=== Production deployment completed ===${NC}"
echo -e "${BLUE}API:  https://api.goodgo.vn${NC}"
echo -e "${BLUE}POS:  https://pos.goodgo.vn${NC}"
echo ""
echo -e "Verify: kubectl get pods -n ${NAMESPACE}"
echo -e "Logs:   kubectl logs -n ${NAMESPACE} -l app=<service-name> -f"
echo -e "Rollback: $0 --rollback <service-name>"
