#!/bin/bash

set -e

FORCE=false

# Parse arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        --force)
            FORCE=true
            shift
            ;;
        --dry-run)
            DRY_RUN="--dry-run=client"
            shift
            ;;
        -*)
            echo "Unknown option $1"
            echo "Usage: $0 <app_name> [--force] [--dry-run]"
            exit 1
            ;;
        *)
            if [ -z "${APP_NAME}" ]; then
                APP_NAME="$1"
            else
                echo "Too many arguments"
                echo "Usage: $0 <app_name> [--force] [--dry-run]"
                exit 1
            fi
            shift
            ;;
    esac
done

if [ -z "${APP_NAME}" ]; then
    echo "Usage: $0 <app_name> [--force] [--dry-run]"
    exit 1
fi

if [ ! -d "apps/${APP_NAME}" ]; then
    echo "Error: App directory 'apps/${APP_NAME}' not found"
    exit 1
fi

# Initialize Wild Cloud environment
if [ -z "${WC_ROOT}" ]; then
    print "WC_ROOT is not set."
    exit 1
else
    source "${WC_ROOT}/scripts/common.sh"
    init_wild_env
fi

SECRETS_FILE="${WC_HOME}/secrets.yaml"
if [ ! -f "${SECRETS_FILE}" ]; then
    echo "Error: Secrets file '${SECRETS_FILE}' not found"
    exit 1
fi

# Function to deploy secrets for an app
deploy_secrets() {
    local app_name="$1"
    local target_namespace="${2:-${app_name}}"  # Default to app name if not specified
    
    # Check if app has a manifest with requiredSecrets
    local manifest_file="apps/${app_name}/manifest.yaml"
    if [ ! -f "${manifest_file}" ]; then
        return 0
    fi
    
    # Check if there are required secrets defined
    if ! yq eval '.requiredSecrets' "${manifest_file}" | grep -q -v '^null$'; then
        return 0
    fi
    
    # Use the target namespace parameter
    local namespace="${target_namespace}"
    
    echo "Deploying secrets for app '${app_name}' in namespace '${namespace}'"
    
    # Gather data for app secret
    local secret_data=""
    while IFS= read -r secret_path; do
        secret_value=$(yq eval ".${secret_path} // \"\"" "${SECRETS_FILE}")
        if [ -n "${secret_value}" ] && [ "${secret_value}" != "null" ]; then
            secret_data="${secret_data} --from-literal=${secret_path}=${secret_value}"
        else
            echo "Error: Required secret '${secret_path}' not found in ${SECRETS_FILE} for app '${app_name}'"
            exit 1
        fi
    done < <(yq eval '.requiredSecrets[]' "${manifest_file}")
    
    # Create/update app secret in cluster
    if [ -n "${secret_data}" ]; then
        echo "Creating/updating secret '${app_name}-secrets' in namespace '${namespace}'"
        if [ "${DRY_RUN:-}" = "--dry-run=client" ]; then
            echo "DRY RUN: kubectl create secret generic ${app_name}-secrets ${secret_data} --namespace=${namespace} --dry-run=client -o yaml"
        else
            kubectl delete secret "${app_name}-secrets" --namespace="${namespace}" --ignore-not-found=true
            kubectl create secret generic "${app_name}-secrets" ${secret_data} --namespace="${namespace}"
        fi
    fi
}

# Step 1: Create namespaces first
echo "Creating namespaces..."
MANIFEST_FILE="apps/${APP_NAME}/manifest.yaml"

# Create dependency namespaces.
if [ -f "${MANIFEST_FILE}" ]; then
    if yq eval '.requires' "${MANIFEST_FILE}" | grep -q -v '^null$'; then
        yq eval '.requires[].name' "${MANIFEST_FILE}" | while read -r required_app; do
            if [ -z "${required_app}" ] || [ "${required_app}" = "null" ]; then
                echo "Warning: Empty or null dependency found, skipping"
                continue
            fi
            
            if [ ! -d "apps/${required_app}" ]; then
                echo "Error: Required dependency '${required_app}' not found in apps/ directory"
                exit 1
            fi
            
            if [ -f "apps/${required_app}/namespace.yaml" ]; then
                echo "Creating namespace for dependency: ${required_app}"
                kubectl apply -f "apps/${required_app}/namespace.yaml" ${DRY_RUN:-}
            else
                echo "Warning: No namespace.yaml found for dependency: ${required_app}"
            fi
        done
    fi
fi

# Create namespace for main app
if [ -f "apps/${APP_NAME}/namespace.yaml" ]; then
    echo "Creating namespace for app: ${APP_NAME}"
    kubectl apply -f "apps/${APP_NAME}/namespace.yaml" ${DRY_RUN:-}
fi

# Copy TLS certificates to the namespace
if [ -f "apps/${APP_NAME}/namespace.yaml" ]; then
    NAMESPACE=$(yq eval '.metadata.name' "apps/${APP_NAME}/namespace.yaml")
    echo "Step 3: Copying TLS certificates to namespace $NAMESPACE..."
    wild-cluster-secret-copy cert-manager:wildcard-internal-wild-cloud-tls "$NAMESPACE" || echo "Warning: Failed to copy internal wildcard certificate"
    wild-cluster-secret-copy cert-manager:wildcard-wild-cloud-tls "$NAMESPACE" || echo "Warning: Failed to copy external wildcard certificate"
fi

# Deploy secrets for this app
deploy_secrets "${APP_NAME}"

# Step 2.5: Handle idempotent jobs (delete and recreate)
echo "Managing idempotent jobs..."
if [ -f "apps/${APP_NAME}/db-init-job.yaml" ]; then
    echo "Deleting and recreating db-init job for idempotent execution"
    kubectl delete job immich-db-init --namespace="${APP_NAME}" --ignore-not-found=true ${DRY_RUN:-}
    # Wait for job deletion to complete
    if [ "${DRY_RUN:-}" != "--dry-run=client" ]; then
        kubectl wait --for=delete job/immich-db-init --namespace="${APP_NAME}" --timeout=30s || true
    fi
fi

# Step 3: Deploy the main application
echo "Deploying application..."
if [ "${FORCE}" = true ]; then
    echo "Force deploying app '${APP_NAME}'"
    kubectl replace --force -k "apps/${APP_NAME}" ${DRY_RUN:-}
else
    echo "Deploying app '${APP_NAME}'"
    kubectl apply -k "apps/${APP_NAME}" ${DRY_RUN:-}
fi
