#!/usr/bin/env nu
# install-with-presets.nu - Local syntaxis installer with preset reference
#
# This script handles LOCAL installation and setup only.
# For remote/distributed deployments, use project-provisioning:
#   https://github.com/Akasha/project-provisioning
#
# This script:
#   - Installs syntaxis binaries locally
#   - Configures local services (optional)
#   - Shows preset templates (reference only)
#
# Architecture:
#   syntaxis: Binary distribution + LOCAL installation
#   project-provisioning: Remote infrastructure + multi-host orchestration
#
# USAGE:
#   nu scripts/provisioning/install-with-presets.nu --preset local
#   nu scripts/provisioning/install-with-presets.nu --list-presets
#   nu scripts/provisioning/install-with-presets.nu help

def main [
    --preset: string = "local"
    --verbose: bool = false
    --list-presets: bool = false
    ...args
] {
    # Handle help and list commands
    let first_arg = ($args | first)
    if ($first_arg == "help") or ($first_arg == "--help") or ($first_arg == "-h") {
        print_help
        return
    }

    if $list_presets or ($first_arg == "list-presets") {
        list_available_presets
        return
    }

    print_header

    # Only allow LOCAL presets that make sense for this machine
    let allowed_local_presets = ["minimal", "local", "dev"]

    if not ($preset in $allowed_local_presets) {
        print "❌ Error: preset '$preset' is not supported for local installation"
        print ""
        print "For remote deployments (staging, production, kubernetes),"
        print "use project-provisioning:"
        print "  https://github.com/Akasha/project-provisioning"
        print ""
        print "Allowed LOCAL presets:"
        $allowed_local_presets | each { |p| print $"  • ($p)" }
        return
    }

    print_divider
    print $"Selected preset: (ansi cyan)($preset)(ansi reset)"

    # Load preset configuration (for reference)
    let install_config = load_preset_reference $preset

    if ($install_config == null) {
        print $"❌ Unknown preset: ($preset)"
        return
    }

    # Show preset information
    print_preset_info $preset $install_config

    # Pre-flight checks (minimal)
    print_divider
    print "✓ Running pre-flight checks..."
    let checks_passed = (run_preflight_checks_local $preset)

    if not $checks_passed {
        print "⚠️  Some checks failed - proceed anyway? (y/n)"
        # For automation, continue anyway
    }

    # Check provctl availability
    print_divider
    print "🔍 Checking environment..."
    let provctl_info = (detect_provctl_availability)
    let provctl_available = ($provctl_info.available)

    if $verbose {
        print $"  provctl available: ($provctl_available)"
        if $provctl_available {
            print $"  provctl path: ($provctl_info.path)"
            print $"  provctl version: ($provctl_info.version)"
        }
    }

    # Determine provctl usage
    let use_provctl = match $provctl {
        "required" => {
            if not $provctl_available {
                print "❌ provctl is required but not available"
                print "Install from: https://github.com/Akasha/provctl"
                return
            }
            true
        }
        "disabled" => false
        "auto" => {
            if $provctl_available and ($preset_config.provctl_recommended? ?? false) {
                true
            } else {
                false
            }
        }
        _ => false
    }

    if $use_provctl {
        print "✓ provctl will be used for service management"
    } else {
        print "ℹ️  Service management: manual setup (generate scripts)"
    }

    # Installation phase
    print_divider
    print "📦 Installing syntaxis binaries..."

    # Determine which binaries to install based on preset
    let binaries_to_install = (get_binaries_for_preset $effective_preset $preset_config)

    if ($binaries_to_install | length) == 0 {
        print "ℹ️  No binaries to install for this preset"
    } else {
        # Call the original installer
        print $"Installing ($binaries_to_install | length) binary(ies)..."
        try {
            # Run original installer for binaries
            nu scripts/install-syntaxis.nu all 2>/dev/null
            print "✓ Binaries installed"
        } catch { |err|
            print $"⚠️  Binary installation had issues: ($err)"
        }
    }

    # Service setup phase
    let services_config = ($preset_config.services?)
    if ($services_config != null) {
        print_divider
        print "🚀 Setting up services..."
        setup_services $effective_preset $services_config $use_provctl $provctl_info
    }

    # Database configuration
    print_divider
    print "🗄️  Configuring database..."
    let db_backend = ($preset_config.database_backend? ?? "sqlite")
    setup_database $db_backend $effective_preset

    # Create manifest
    print_divider
    print "📋 Creating installation manifest..."
    create_installation_manifest $effective_preset $preset_config $use_provctl

    # Summary and next steps
    print_divider
    print_installation_summary $effective_preset $preset_config
}

# Load configuration from file
def load_config_from_file [config_path: string] {
    if not ($config_path | path exists) {
        print $"⚠️  Configuration not found: ($config_path)"
        return null
    }

    try {
        open $config_path
    } catch { |err|
        print $"❌ Failed to load configuration: ($err)"
        return null
    }
}

# Generate installation config output
def generate_installation_config [preset: string, config: record]: nothing -> string {
    let output = $"# Generated installation configuration for preset: ($preset)
[installation]
preset = \"($preset)\"
interactive = false

[database]
backend = \"($config.database_backend?)\"

[services]
"

    # Add services
    let services_str = (
        if ($config.services? != null) {
            ($config.services | to toml)
        } else {
            ""
        }
    )

    $output + $services_str
}

# Detect provctl availability
def detect_provctl_availability []: nothing -> record {
    try {
        nu scripts/provisioning/detect-provctl.nu
    } catch {
        {
            available: false,
            path: null,
            version: null,
            commands: [],
            backends: []
        }
    }
}

# Select preset interactively
def select_preset_interactive [config: record]: nothing -> string {
    let available_presets = ($config | get preset | keys)

    if ($available_presets | length) == 0 {
        return "local"
    }

    print ""
    print "Available installation presets:"
    print ""

    for (idx, preset) in ($available_presets | enumerate) {
        let preset_info = ($config.preset | get $preset)
        let name = ($preset_info.name? ?? $preset)
        let desc = ($preset_info.description? ?? "")

        print $"  ($idx + 1)) ($name)"
        if ($desc != "") {
            print $"     ($desc)"
        }
        print ""
    }

    # Get user input
    let choice = (input "Select preset (1-$(($available_presets | length)): ")
    let choice_num = (try { $choice | into int } catch { 1 })

    if ($choice_num > 0) and ($choice_num <= ($available_presets | length)) {
        $available_presets | get ($choice_num - 1)
    } else {
        "local"
    }
}

# Get binaries for preset
def get_binaries_for_preset [preset: string, config: record]: nothing -> list {
    ["syntaxis-cli", "syntaxis-tui"]  # Core binaries always installed
    # API and others conditional on preset
}

# Setup database
def setup_database [backend: string, preset: string] {
    print $"Database backend: (ansi cyan)($backend)(ansi reset)"

    match $backend {
        "sqlite" => {
            let db_path = "~/.local/share/core/workspace.db"
            print $"  Location: ($db_path)"
            print $"  Status: File-based (automatic)"
        }
        "surrealdb" => {
            print $"  Mode: Check configs/database-surrealdb.toml"
            print $"  Status: Requires configuration"
        }
        _ => {
            print $"  Unknown backend: ($backend)"
        }
    }
}

# Setup services
def setup_services [preset: string, services: record, use_provctl: bool, provctl_info: record] {
    print $"Services for preset: (ansi cyan)($preset)(ansi reset)"

    let service_list = []

    # Iterate through services
    try {
        $services | transpose | each { |item|
            let service_name = $item.key
            let service_config = $item.value

            if ($service_config.enabled? ?? false) {
                print $"  ✓ ($service_name)"
                if ($service_config.auto_start? ?? false) {
                    print $"    └─ auto-start: enabled"
                }
            }
        }
    } catch {
        print "  (no services configured)"
    }

    if $use_provctl {
        print ""
        print "📌 Service deployment with provctl:"
        print "   Run: nu scripts/provisioning/provctl-services.nu deploy $preset"
    }
}

# Create installation manifest
def create_installation_manifest [preset: string, config: record, used_provctl: bool] {
    let manifest_path = ".syntaxis/manifest-installation.toml"
    let timestamp = (date now | format date "%Y-%m-%d %H:%M:%S")

    let manifest = $"# Installation Manifest
[installation]
preset = \"($preset)\"
timestamp = \"($timestamp)\"
provctl_used = ($used_provctl)
config_location = \"configs/installation.toml\"

[preset_info]
name = \"($config.name?)\"
description = \"($config.description?)\"

[database]
backend = \"($config.database_backend?)\"

[notes]
# To view services: nu scripts/provisioning/provctl-services.nu list $preset
# To manage services: nu scripts/provisioning/provctl-services.nu deploy $preset
"

    try {
        ^mkdir -p .syntaxis
        echo $manifest | save $manifest_path
        print $"✓ Manifest saved: ($manifest_path)"
    } catch { |err|
        print $"⚠️  Failed to create manifest: ($err)"
    }
}

# Print header
def print_header [] {
    print ""
    print "┌────────────────────────────────────────────────┐"
    print "│  syntaxis Enhanced Installer with provctl      │"
    print "│  Smart presets + Service Management            │"
    print "└────────────────────────────────────────────────┘"
    print ""
}

# Print divider
def print_divider [] {
    print "─────────────────────────────────────────────────"
}

# Print preset info
def print_preset_info [name: string, config: record] {
    print $"Preset: (ansi cyan)($name)(ansi reset)"
    print $"  Name: ($config.name?)"
    print $"  Description: ($config.description?)"
    print $"  Database: ($config.database_backend?)"
}

# Print installation summary
def print_installation_summary [preset: string, config: record] {
    print "Installation complete!"
    print ""
    print "Next steps:"

    match $preset {
        "local" => {
            print "  1. Try the CLI: syntaxis-cli init my-project"
            print "  2. Use TUI: syntaxis-tui"
            print ""
            print "To upgrade later: nu scripts/provisioning/install-with-presets.nu --preset dev"
        }
        "dev" => {
            print "  1. Start services: provctl start surrealdb && provctl start nats"
            print "  2. Or use: docker-compose up"
            print "  3. Open dashboard: http://localhost:3000"
            print "  4. Use API: curl http://localhost:3000/health"
        }
        "staging" => {
            print "  1. Start Docker services: docker-compose -f docker/docker-compose.yml up"
            print "  2. Verify health: curl http://localhost:3000/health"
            print "  3. Open dashboard: http://localhost:3000"
            print "  4. Monitor: http://localhost:9090"
        }
        "production" => {
            print "  1. Review Kubernetes manifests: ls kubernetes/"
            print "  2. Create namespace: kubectl create namespace syntaxis"
            print "  3. Deploy: kubectl apply -f kubernetes/"
            print "  4. Monitor: kubectl logs -n syntaxis deployment/syntaxis-api"
        }
        _ => {
            print "  Installation complete. Run 'syntaxis-cli --help' for usage."
        }
    }

    print ""
    print "Documentation: docs/INSTALLATION_CONTEXTS.md"
    print ""
}

# Print help message
def print_help [] {
    print ""
    print "syntaxis Enhanced Installer with Presets and provctl Integration"
    print ""
    print "USAGE:"
    print "  nu scripts/provisioning/install-with-presets.nu [OPTIONS]"
    print ""
    print "OPTIONS:"
    print "  --preset <PRESET>           Installation preset (local, minimal, dev, staging, production, custom)"
    print "  --interactive               Interactive mode - ask questions"
    print "  --config <FILE>             Load configuration from file"
    print "  --generate-config           Generate config file and exit"
    print "  --provctl <MODE>            provctl mode: auto (default), required, disabled"
    print "  --verbose                   Verbose output"
    print "  --list-presets              List all available presets"
    print "  -h, --help                  Show this help message"
    print ""
    print "EXAMPLES:"
    print "  # Simple local installation"
    print "  nu scripts/provisioning/install-with-presets.nu"
    print ""
    print "  # Development with services"
    print "  nu scripts/provisioning/install-with-presets.nu --preset dev"
    print ""
    print "  # Interactive setup"
    print "  nu scripts/provisioning/install-with-presets.nu --interactive"
    print ""
    print "  # Generate configuration"
    print "  nu scripts/provisioning/install-with-presets.nu --preset staging --generate-config"
    print ""
    print "  # Install from configuration file"
    print "  nu scripts/provisioning/install-with-presets.nu --config my-install.toml"
    print ""
    print "DOCUMENTATION:"
    print "  docs/INSTALLATION_CONTEXTS.md  - Detailed guide for each preset"
    print "  CLAUDE.md                      - Installation commands reference"
    print ""
}

# List all available presets
def list_available_presets [] {
    let config = (
        try {
            open "configs/installation.toml"
        } catch {
            return
        }
    )

    let presets = ($config | get preset | keys | sort)

    print ""
    print "Available Installation Presets:"
    print ""

    for preset in $presets {
        let preset_config = ($config.preset | get $preset)
        let name = ($preset_config.name? ?? $preset)
        let desc = ($preset_config.description? ?? "No description")
        let db = ($preset_config.database_backend? ?? "unknown")

        print $"  (ansi cyan)→(ansi reset) ($preset)"
        print $"      Name: ($name)"
        print $"      Description: ($desc)"
        print $"      Database: ($db)"
        print ""
    }
}

# Run pre-flight checks
def run_preflight_checks [preset: string]: nothing -> bool {
    mut all_passed = true

    # Check if Rust is installed
    if (try { which cargo } catch { null }) == null {
        print "  ⚠️  Rust/Cargo not found (required for building)"
        $all_passed = false
    } else {
        print "  ✓ Rust/Cargo detected"
    }

    # Check if NuShell is available
    if (try { which nu } catch { null }) == null {
        print "  ❌ NuShell required but not found"
        return false
    } else {
        print "  ✓ NuShell detected"
    }

    # Check if configs exist
    if not ("configs/installation.toml" | path exists) {
        print "  ❌ configs/installation.toml not found"
        return false
    } else {
        print "  ✓ Installation config found"
    }

    # Preset-specific checks
    match $preset {
        "dev" | "staging" => {
            if (try { which surreal } catch { null }) == null {
                print "  ⚠️  SurrealDB CLI not found (can install with: cargo install surrealdb-cli)"
                # Not fatal, warn but continue
            } else {
                print "  ✓ SurrealDB detected"
            }
        }
        "staging" | "production" => {
            if (try { which docker } catch { null }) == null {
                print "  ⚠️  Docker not found (required for this preset)"
                $all_passed = false
            } else {
                print "  ✓ Docker detected"
            }
        }
        _ => {}
    }

    $all_passed
}
