#!/usr/bin/env bash
# Platform Services Configuration Setup Script
# Generates and manages platform service configurations in provisioning/config/runtime/
#
# Usage: ./setup-platform-config.sh [options]
#        ./setup-platform-config.sh --service orchestrator --mode solo
#        ./setup-platform-config.sh --mode multiuser --backend web
#        ./setup-platform-config.sh --list-modes
#
# Features:
# - Interactive TypeDialog configuration via provisioning/.typedialog/platform/scripts/configure.nu
# - Quick mode setup (solo, multiuser, cicd, enterprise) from defaults
# - Automatic TOML export for Rust service consumption
# - Runtime config detection and management (clean, update, preserve)

set -euo pipefail

# Ensure TypeDialog is installed
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/ensure-typedialog.sh" || true

# Check TypeDialog availability
if ! command -v typedialog &> /dev/null; then
    echo -e "\033[1;33m⚠️  TypeDialog not found. Attempting installation...\033[0m"
    ensure_typedialog_installed true || {
        echo -e "\033[0;31m❌ Failed to install TypeDialog\033[0m"
        exit 1
    }
fi

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

# Script paths
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
TYPEDIALOG_SCRIPTS="${PROJECT_ROOT}/.typedialog/platform/scripts"
SCHEMAS_PLATFORM="${PROJECT_ROOT}/schemas/platform"
CONFIG_RUNTIME="${PROJECT_ROOT}/config/runtime"
CONFIG_GENERATED="${CONFIG_RUNTIME}/generated"

# Available services and modes
SERVICES=("orchestrator" "control-center" "mcp-server" "vault-service" "extension-registry" "rag" "ai-service" "provisioning-daemon")
MODES=("solo" "multiuser" "cicd" "enterprise")

# Default values
BACKEND="${BACKEND:-web}"
SERVICE=""
MODE=""
ACTION=""
FORCE=false

# ============================================================================
# Helper Functions
# ============================================================================

print_header() {
    echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
    echo -e "${BLUE}$1${NC}"
    echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
}

print_info() {
    echo -e "${BLUE}ℹ️  $1${NC}"
}

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

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

print_error() {
    echo -e "${RED}❌ $1${NC}" >&2
}

# Check if directory/file exists
check_exists() {
    if [[ ! -e "$1" ]]; then
        print_error "Not found: $1"
        return 1
    fi
}

# ============================================================================
# Service/Mode Validation
# ============================================================================

validate_service() {
    local service="$1"

    # "all" is handled by bash script itself, not passed to Nushell
    if [[ "$service" == "all" ]]; then
        return 0
    fi

    if [[ ! " ${SERVICES[*]} " =~ " ${service} " ]]; then
        print_error "Invalid service: $service"
        echo "Valid services: ${SERVICES[*]}, all"
        return 1
    fi
}

validate_mode() {
    local mode="$1"
    if [[ ! " ${MODES[*]} " =~ " ${mode} " ]]; then
        print_error "Invalid mode: $mode"
        echo "Valid modes: ${MODES[*]}"
        return 1
    fi
}

# ============================================================================
# Directory Setup
# ============================================================================

ensure_runtime_dir() {
    if [[ ! -d "$CONFIG_RUNTIME" ]]; then
        print_info "Creating runtime config directory: $CONFIG_RUNTIME"
        mkdir -p "$CONFIG_RUNTIME" "$CONFIG_GENERATED"
    fi

    # Create .gitignore if not present
    if [[ ! -f "$CONFIG_RUNTIME/.gitignore" ]]; then
        cat > "$CONFIG_RUNTIME/.gitignore" <<EOF
# Runtime configurations (private/deployment-specific)
*.ncl
*.toml

# Generated artifacts
generated/

# Backup files
*.bak
*.backup
EOF
        print_info "Created .gitignore in $CONFIG_RUNTIME"
    fi
}

# ============================================================================
# Config Detection & Management
# ============================================================================

detect_runtime_config() {
    # Check if any runtime config exists
    if ls "$CONFIG_RUNTIME"/*.ncl 1>/dev/null 2>&1; then
        echo "existing"
        return 0
    fi
    echo "empty"
    return 0
}

list_runtime_services() {
    local services=()
    for file in "$CONFIG_RUNTIME"/*.ncl; do
        if [[ -f "$file" ]]; then
            local basename=$(basename "$file" .ncl)
            services+=("$basename")
        fi
    done

    if [[ ${#services[@]} -gt 0 ]]; then
        printf '%s\n' "${services[@]}"
    fi
}

# ============================================================================
# Interactive Prompts
# ============================================================================

prompt_action_existing_config() {
    while true; do
        echo ""
        print_warning "Runtime configuration already exists in: $CONFIG_RUNTIME"
        echo ""
        echo "Choose action:"
        echo "  1) Clean up and start fresh (removes all .ncl and .toml files)"
        echo "  2) Use TypeDialog to update configuration [default]"
        echo "  3) Setup quick mode (solo/multiuser/cicd/enterprise)"
        echo "  4) List existing configurations"
        echo "  5) Cancel"
        echo ""
        echo "Press CTRL-C to cancel at any time"
        echo ""
        read -rp "Enter choice [1-5] (default: 2): " choice

        # Default to 2 (TypeDialog update)
        choice="${choice:-2}"

        case "$choice" in
            1) ACTION="clean-start"; return 0 ;;
            2) ACTION="typedialog"; return 0 ;;
            3) ACTION="quick-mode"; return 0 ;;
            4) ACTION="list"; return 0 ;;
            5) print_info "Cancelled."; exit 0 ;;
            *) print_error "Invalid choice. Please enter 1-5 (or press CTRL-C to abort)." ;;
        esac
    done
}

prompt_action_empty_config() {
    while true; do
        echo ""
        echo "Choose how to setup platform configuration:"
        echo "  1) Interactive TypeDialog (recommended, with UI form) [default]"
        echo "  2) Quick mode setup (choose solo/multiuser/cicd/enterprise)"
        echo "  3) Cancel"
        echo ""
        echo "Press CTRL-C to cancel at any time"
        echo ""
        read -rp "Enter choice [1-3] (default: 1): " choice

        # Default to 1 if empty
        choice="${choice:-1}"

        case "$choice" in
            1) ACTION="typedialog"; return 0 ;;
            2) ACTION="quick-mode"; return 0 ;;
            3) print_info "Cancelled."; exit 0 ;;
            *) print_error "Invalid choice. Please enter 1, 2, or 3 (or press CTRL-C to abort)." ;;
        esac
    done
}

prompt_for_service() {
    local max_choice=$((${#SERVICES[@]}+1))

    while true; do
        echo ""
        echo "Select service to configure:"
        for i in "${!SERVICES[@]}"; do
            echo "  $((i+1))) ${SERVICES[$i]}"
        done
        echo "  $max_choice) Configure all services [default]"
        echo ""
        echo "Press CTRL-C to cancel"
        echo ""
        read -rp "Enter choice [1-$max_choice] (default: $max_choice): " choice

        # Default to "all services"
        choice="${choice:-$max_choice}"

        # Validate numeric input
        if ! [[ "$choice" =~ ^[0-9]+$ ]]; then
            print_error "Invalid input. Please enter a number (or press CTRL-C to abort)."
            continue
        fi

        if [[ "$choice" -ge 1 && "$choice" -le "$max_choice" ]]; then
            if [[ "$choice" == "$max_choice" ]]; then
                SERVICE="all"
            else
                SERVICE="${SERVICES[$((choice-1))]}"
            fi
            return 0
        else
            print_error "Invalid choice. Please enter a number between 1 and $max_choice (or press CTRL-C to abort)."
        fi
    done
}

prompt_for_mode() {
    local max_choice=${#MODES[@]}

    while true; do
        echo ""
        echo "Select deployment mode:"
        for i in "${!MODES[@]}"; do
            local marker=""
            # Mark solo as default
            if [[ "${MODES[$i]}" == "solo" ]]; then
                marker=" [default]"
            fi
            echo "  $((i+1))) ${MODES[$i]}$marker"
        done
        echo ""
        echo "Press CTRL-C to cancel"
        echo ""
        read -rp "Enter choice [1-$max_choice] (default: 1): " choice

        # Default to 1 (solo)
        choice="${choice:-1}"

        # Validate numeric input
        if ! [[ "$choice" =~ ^[0-9]+$ ]]; then
            print_error "Invalid input. Please enter a number (or press CTRL-C to abort)."
            continue
        fi

        if [[ "$choice" -ge 1 && "$choice" -le "$max_choice" ]]; then
            MODE="${MODES[$((choice-1))]}"
            return 0
        else
            print_error "Invalid choice. Please enter a number between 1 and $max_choice (or press CTRL-C to abort)."
        fi
    done
}

prompt_for_backend() {
    while true; do
        echo ""
        echo "Select TypeDialog backend:"
        echo "  1) web (browser-based, recommended) [default]"
        echo "  2) tui (terminal UI)"
        echo "  3) cli (command-line)"
        echo ""
        echo "Press CTRL-C to cancel"
        echo ""
        read -rp "Enter choice [1-3] (default: 1): " choice

        # Default to 1 (web)
        choice="${choice:-1}"

        case "$choice" in
            1) BACKEND="web"; return 0 ;;
            2) BACKEND="tui"; return 0 ;;
            3) BACKEND="cli"; return 0 ;;
            *) print_error "Invalid choice. Please enter 1, 2, or 3 (or press CTRL-C to abort)." ;;
        esac
    done
}

# ============================================================================
# Configuration Generation
# ============================================================================

generate_toml_for_service() {
    local service="$1"
    local mode="$2"
    local ncl_file="${CONFIG_RUNTIME}/${service}.${mode}.ncl"

    if [[ ! -f "$ncl_file" ]]; then
        print_warning "Nickel config not found: $ncl_file"
        return 1
    fi

    print_info "Exporting TOML for $service ($mode)..."

    local toml_file="${CONFIG_GENERATED}/${service}.${mode}.toml"

    # Generate TOML from Nickel
    if nickel export --format toml "$ncl_file" > "$toml_file" 2>/dev/null; then
        print_success "Generated: $toml_file"
        return 0
    else
        print_error "Failed to generate TOML for $service ($mode)"
        return 1
    fi
}

generate_all_tomls() {
    echo ""
    print_header "Generating TOML Exports"

    local generated_count=0
    local failed_count=0

    # Scan for all .ncl files in runtime
    for ncl_file in "$CONFIG_RUNTIME"/*.ncl; do
        if [[ -f "$ncl_file" ]]; then
            local basename=$(basename "$ncl_file" .ncl)
            local service="${basename%.*}"  # Remove mode suffix
            local mode="${basename##*.}"     # Extract mode

            if generate_toml_for_service "$service" "$mode"; then
                ((generated_count++))
            else
                ((failed_count++))
            fi
        fi
    done

    echo ""
    print_success "Generated $generated_count TOML files"
    if [[ $failed_count -gt 0 ]]; then
        print_warning "$failed_count files failed"
    fi
}

# ============================================================================
# TypeDialog Configuration
# ============================================================================

configure_via_typedialog() {
    check_exists "$TYPEDIALOG_SCRIPTS/configure.nu" || return 1

    echo ""
    print_header "TypeDialog Configuration"

    # Prompt for service if not provided
    if [[ -z "$SERVICE" ]]; then
        prompt_for_service
    else
        validate_service "$SERVICE" || return 1
    fi

    # Prompt for mode if not provided
    if [[ -z "$MODE" ]]; then
        prompt_for_mode
    else
        validate_mode "$MODE" || return 1
    fi

    # Prompt for backend if using web
    if [[ "$BACKEND" == "default" ]]; then
        prompt_for_backend
    fi

    # Handle "all" services by iterating
    if [[ "$SERVICE" == "all" ]]; then
        print_info "Configuring all services for mode: $MODE"
        echo ""

        local success_count=0
        local fail_count=0

        for svc in "${SERVICES[@]}"; do
            print_info "Launching TypeDialog ($BACKEND backend) for $svc ($MODE)..."

            # Execute from scripts dir so relative module imports work
            if (cd "$TYPEDIALOG_SCRIPTS" && nu configure.nu "$svc" "$MODE" --backend "$BACKEND"); then
                print_success "Configuration completed for $svc"
                generate_toml_for_service "$svc" "$MODE" && ((success_count++)) || ((fail_count++))
            else
                print_warning "Configuration skipped or failed for $svc"
                ((fail_count++))
            fi
            echo ""
        done

        print_info "Configured $success_count services, $fail_count failed/skipped"
        return 0
    fi

    print_info "Launching TypeDialog ($BACKEND backend) for $SERVICE ($MODE)..."
    echo ""

    # Run TypeDialog via Nushell script (execute from scripts dir so module imports work)
    if (cd "$TYPEDIALOG_SCRIPTS" && nu configure.nu "$SERVICE" "$MODE" --backend "$BACKEND"); then
        print_success "Configuration completed for $SERVICE"

        # Auto-generate TOML
        generate_toml_for_service "$SERVICE" "$MODE"

        print_info ""
        print_info "Next steps:"
        print_info "  - Review config: cat $CONFIG_RUNTIME/$SERVICE.$MODE.ncl"
        print_info "  - Export TOML: $TYPEDIALOG_SCRIPTS/generate-configs.nu $SERVICE $MODE"
        print_info "  - Run service: ORCHESTRATOR_MODE=$MODE cargo run -p $SERVICE"
        return 0
    else
        print_error "TypeDialog configuration cancelled or failed"
        return 1
    fi
}

# ============================================================================
# Quick Mode Setup (from defaults)
# ============================================================================

setup_quick_mode() {
    echo ""
    print_header "Quick Mode Setup"

    # Prompt for mode if not provided
    if [[ -z "$MODE" ]]; then
        prompt_for_mode
    else
        validate_mode "$MODE" || return 1
    fi

    print_info "Setting up all services for mode: $MODE"
    echo ""

    local created_count=0
    local failed_count=0

    # Create config for each service by composing defaults + mode overlay
    for service in "${SERVICES[@]}"; do
        local ncl_file="$CONFIG_RUNTIME/${service}.${MODE}.ncl"
        local schema_file="$SCHEMAS_PLATFORM/schemas/${service}.ncl"
        local defaults_file="$SCHEMAS_PLATFORM/defaults/${service}-defaults.ncl"
        local mode_defaults="$SCHEMAS_PLATFORM/defaults/deployment/${MODE}-defaults.ncl"

        if [[ ! -f "$schema_file" ]] || [[ ! -f "$defaults_file" ]]; then
            print_warning "Schema or defaults not found for $service (skipping)"
            ((failed_count++))
            continue
        fi

        # Create Nickel config that composes: schema + defaults + mode overlay
        cat > "$ncl_file" <<'EOF'
# Generated configuration for SERVICE (MODE mode)
# Generated: $(date -u +"%Y-%m-%dT%H:%M:%SZ")
# DO NOT EDIT MANUALLY - Re-run setup-platform-config.sh to update
#
# This configuration is composed from:
# - Schema: provisioning/schemas/platform/schemas/SERVICE.ncl
# - Defaults: provisioning/schemas/platform/defaults/SERVICE-defaults.ncl
# - Mode: provisioning/schemas/platform/defaults/deployment/MODE-defaults.ncl

let helpers = import "provisioning/schemas/platform/common/helpers.ncl"
let schema = import "provisioning/schemas/platform/schemas/SERVICE.ncl"
let defaults = import "provisioning/schemas/platform/defaults/SERVICE-defaults.ncl"
let mode_config = import "provisioning/schemas/platform/defaults/deployment/MODE-defaults.ncl"

# Compose: base defaults + mode overlay + validators
helpers.compose_config defaults mode_config {}
EOF

        # Replace placeholders with actual values
        sed -i.bak "s|SERVICE|$service|g" "$ncl_file"
        sed -i.bak "s|MODE|$MODE|g" "$ncl_file"
        rm -f "${ncl_file}.bak"

        if [[ -f "$ncl_file" ]]; then
            print_success "Created config: $service ($MODE)"

            # Generate TOML
            if generate_toml_for_service "$service" "$MODE"; then
                ((created_count++))
            else
                ((failed_count++))
            fi
        fi
    done

    echo ""
    print_success "Setup complete: $created_count services configured"
    if [[ $failed_count -gt 0 ]]; then
        print_warning "$failed_count services failed"
    fi
}

# ============================================================================
# Cleanup Operations
# ============================================================================

cleanup_runtime_config() {
    echo ""
    print_warning "This will delete all runtime configurations"
    read -rp "Are you sure? (yes/no): " confirm

    if [[ "$confirm" != "yes" ]]; then
        print_info "Cancelled"
        return 0
    fi

    print_info "Removing runtime configurations..."
    rm -f "$CONFIG_RUNTIME"/*.ncl "$CONFIG_GENERATED"/*.toml

    print_success "Cleanup complete"
}

# ============================================================================
# Listing Operations
# ============================================================================

list_deployment_modes() {
    echo ""
    print_info "Available deployment modes:"
    for mode in "${MODES[@]}"; do
        echo "  - $mode"
    done
}

list_available_services() {
    echo ""
    print_info "Available services:"
    for service in "${SERVICES[@]}"; do
        echo "  - $service"
    done
}

list_runtime_configs() {
    echo ""
    print_header "Runtime Configurations"

    local status=$(detect_runtime_config)

    if [[ "$status" == "empty" ]]; then
        print_info "No runtime configurations found"
        return 0
    fi

    echo "Configured services:"
    list_runtime_services | while read -r service; do
        echo "  ✓ $service"
    done

    echo ""
    echo "Location: $CONFIG_RUNTIME"
}

# ============================================================================
# Help Text
# ============================================================================

show_help() {
    cat <<EOF
${BLUE}Platform Services Configuration Setup${NC}

Usage: $(basename "$0") [OPTIONS]

Options:
  -s, --service SERVICE     Configure specific service (orchestrator, control-center, etc.)
  -m, --mode MODE           Set deployment mode (solo, multiuser, cicd, enterprise)
  -b, --backend BACKEND     TypeDialog backend: web (default), tui, cli
  --typedialog              Use TypeDialog for configuration
  --quick-mode              Use quick mode setup from defaults
  --list-modes              List available deployment modes
  --list-services           List available services
  --list-configs            List existing runtime configurations
  --clean                   Remove all runtime configurations
  --generate-toml           Generate TOML files from Nickel configs
  -h, --help                Show this help message

Examples:
  # Interactive setup (prompts for choices)
  $(basename "$0")

  # Configure specific service via TypeDialog
  $(basename "$0") --service orchestrator --mode solo --backend web

  # Quick setup for all services in solo mode
  $(basename "$0") --quick-mode --mode solo

  # List available modes
  $(basename "$0") --list-modes

  # Regenerate TOML files
  $(basename "$0") --generate-toml

Environment Variables:
  TYPEDIALOG_BACKEND       Override TypeDialog backend (web, tui, cli)

EOF
}

# ============================================================================
# Main Entry Point
# ============================================================================

main() {
    # Parse command-line arguments
    while [[ $# -gt 0 ]]; do
        case "$1" in
            -s|--service) SERVICE="$2"; shift 2 ;;
            -m|--mode) MODE="$2"; shift 2 ;;
            -b|--backend) BACKEND="$2"; shift 2 ;;
            --typedialog) ACTION="typedialog"; shift ;;
            --quick-mode) ACTION="quick-mode"; shift ;;
            --list-modes) ACTION="list-modes"; shift ;;
            --list-services) ACTION="list-services"; shift ;;
            --list-configs) ACTION="list"; shift ;;
            --clean) ACTION="clean"; shift ;;
            --generate-toml) ACTION="generate-toml"; shift ;;
            --force) FORCE=true; shift ;;
            -h|--help) show_help; exit 0 ;;
            *) print_error "Unknown option: $1"; show_help; exit 1 ;;
        esac
    done

    # Ensure directories exist
    ensure_runtime_dir

    # Check for required tools
    if ! command -v nickel &>/dev/null; then
        print_error "Nickel not found. Please install Nickel (https://nickel-lang.org/)"
        exit 1
    fi

    if ! command -v nu &>/dev/null; then
        print_error "Nushell not found. Please install Nushell"
        exit 1
    fi

    # Execute requested action
    case "${ACTION:-}" in
        typedialog)
            configure_via_typedialog || exit 1
            ;;
        quick-mode)
            setup_quick_mode || exit 1
            ;;
        clean)
            cleanup_runtime_config
            ;;
        list)
            list_runtime_configs
            ;;
        list-modes)
            list_deployment_modes
            ;;
        list-services)
            list_available_services
            ;;
        generate-toml)
            generate_all_tomls
            ;;
        *)
            # No action specified - interactive mode
            print_header "Platform Services Configuration Setup"

            local runtime_status=$(detect_runtime_config)

            if [[ "$runtime_status" == "existing" ]]; then
                prompt_action_existing_config
            else
                prompt_action_empty_config
            fi

            # Execute chosen action
            case "$ACTION" in
                typedialog) configure_via_typedialog || exit 1 ;;
                quick-mode) setup_quick_mode || exit 1 ;;
                clean) cleanup_runtime_config ;;
                list) list_runtime_configs ;;
                *) print_error "No action selected"; exit 1 ;;
            esac
            ;;
    esac

    echo ""
    print_success "Done!"
}

# Run main function
main "$@"
