# Interactive Setup Wizard Module
# Provides step-by-step interactive guidance for system setup
# Follows Nushell guidelines: explicit types, single purpose, no try-catch
# [command]
# name = "setup wizard"
# group = "configuration"
# tags = ["setup", "interactive", "wizard"]
# version = "3.0.0"
# requires = ["nushell:0.109.0"]

use ./mod.nu *
use ./detection.nu *
use ./validation.nu *
use ../utils/path-utils.nu *

# ============================================================================
# INPUT HELPERS
# ============================================================================

# Helper to read one line of input in Nushell 0.109.1
# Reads directly from /dev/tty for TTY mode, handles piped input gracefully
def read-input-line [] {
    # Try to read from /dev/tty first (TTY/interactive mode)
    let read_result = (do { open /dev/tty | lines | first | str trim } | complete)

    # If /dev/tty worked, return the line
    if $read_result.exit_code == 0 {
        ($read_result.stdout)
    } else {
        # No /dev/tty (Windows, containers, or piped mode)
        # Return empty string - this will use defaults in calling code
        ""
    }
}

# Prompt user for simple yes/no question
export def prompt-yes-no [
    question: string
] {
    print ""
    print -n ($question + " (y/n): ")
    let response = (read-input-line)
    if ($response | is-empty) { false } else { ($response == "y" or $response == "Y") }
}

# Prompt user for text input
export def prompt-text [
    question: string
    default_value: string = ""
] {
    print ""
    if ($default_value != "") {
        print ($question + " [" + $default_value + "]: ")
    } else {
        print ($question + ": ")
    }

    let response = (read-input-line)
    if ($response == "") {
        $default_value
    } else {
        $response
    }
}

# Prompt user for selection from list
export def prompt-select [
    question: string
    options: list<string>
] {
    print ""
    print $question
    let option_count = ($options | length)
    for i in (0..($option_count - 1)) {
        let option = ($options | get $i)
        let num = (($i + 1) | into string)
        print ("  " + $num + ") " + $option)
    }
    print ""
    let count_str = ($option_count | into string)
    print ("Select option (1-" + $count_str + "): ")

    let choice_str = (read-input-line)
    let choice = ($choice_str | into int | default 1)

    if ($choice >= 1 and $choice <= $option_count) {
        $options | get ($choice - 1)
    } else {
        $options | get 0
    }
}

# Prompt user for number with validation
export def prompt-number [
    question: string
    min_value: int = 1
    max_value: int = 1000
    default_value: int = 0
] {
    mut result = $default_value
    mut valid = false

    while (not $valid) {
        print ""
        if ($default_value != 0) {
            print $"$question [$default_value]: "
        } else {
            print $"$question: "
        }

        let input_value = (read-input-line)

        if ($input_value == "") {
            $result = $default_value
            $valid = true
        } else {
            let parsed = (do { $input_value | into int } | complete)
            if ($parsed.exit_code == 0) {
                let num = ($parsed.stdout | str trim | into int)
                if ($num >= $min_value and $num <= $max_value) {
                    $result = $num
                    $valid = true
                } else {
                    print-setup-warning $"Please enter a number between ($min_value) and ($max_value)"
                }
            } else {
                print-setup-warning "Please enter a valid number"
            }
        }
    }

    $result
}

# ============================================================================
# PROFILE SELECTION
# ============================================================================

# Prompt for setup profile selection
export def prompt-profile-selection [] {
    print ""
    print-setup-header "Profile Selection"
    print ""
    print "Choose a setup profile for your provisioning system:"
    print ""
    print "  1) Developer  - Fast local setup (<5 min, Docker Compose, minimal config)"
    print "  2) Production - Full validated setup (Kubernetes/SSH, complete security, HA)"
    print "  3) CI/CD      - Ephemeral pipeline setup (automated, Docker Compose, cleanup)"
    print ""

    let options = ["Developer", "Production", "CI/CD"]
    let choice = (prompt-select "Select profile" $options)

    match $choice {
        "Developer" => "developer"
        "Production" => "production"
        "CI/CD" => "cicd"
        _ => "developer"
    }
}

# ============================================================================
# SYSTEM CONFIGURATION PROMPTS
# ============================================================================

# Prompt for system configuration details
export def prompt-system-config [] {
    print-setup-header "System Configuration"
    print ""
    print "Let's configure your provisioning system. This will set up the base configuration."
    print ""

    let config_path = (get-config-base-path)
    print-setup-info $"Configuration will be stored in: ($config_path)"

    let use_defaults = (prompt-yes-no "Use recommended paths for your OS?")

    let confirmed_path = if $use_defaults {
        config_path
    } else {
        (prompt-text "Configuration base path" $config_path)
    }

    {
        config_path: $confirmed_path
        os_name: (detect-os)
        cpu_count: (get-cpu-count)
        memory_gb: (get-system-memory-gb)
    }
}

# ============================================================================
# DEPLOYMENT MODE PROMPTS
# ============================================================================

# Prompt for deployment mode selection
export def prompt-deployment-mode [
    detection_report: record
] {
    print-setup-header "Deployment Mode Selection"
    print ""
    print "Choose how platform services will be deployed:"
    print ""

    mut options = []
    let caps = $detection_report.capabilities

    if ($caps.docker_available and $caps.docker_compose_available) {
        $options = ($options | append "docker-compose (Local Docker)")
    }

    if $caps.kubectl_available {
        $options = ($options | append "kubernetes (Kubernetes cluster)")
    }

    if $caps.ssh_available {
        $options = ($options | append "remote-ssh (Remote SSH)")
    }

    if $caps.systemd_available {
        $options = ($options | append "systemd (System services)")
    }

    if ($options | length) == 0 {
        print-setup-error "No deployment methods available"
        return "unknown"
    }

    let recommended = (recommend-deployment-mode $detection_report)
    print ("Recommended: " + $recommended)
    print ""

    let selected = (prompt-select "Select deployment mode" $options)
    match $selected {
        "docker-compose (Local Docker)" => { "docker-compose" }
        "kubernetes (Kubernetes cluster)" => { "kubernetes" }
        "remote-ssh (Remote SSH)" => { "remote-ssh" }
        "systemd (System services)" => { "systemd" }
        _ => { "docker-compose" }
    }
}

# ============================================================================
# PROVIDER CONFIGURATION PROMPTS
# ============================================================================

# Prompt for provider selection
export def prompt-providers [] {
    print-setup-header "Provider Selection"
    print ""
    print "Which infrastructure providers do you want to use?"
    print "(Select at least one)"
    print ""

    let available_providers = ["upcloud", "aws", "hetzner", "local"]
    mut selected = []

    for provider in $available_providers {
        let use_provider = (prompt-yes-no $"Use ($provider)?")
        if $use_provider {
            $selected = ($selected | append $provider)
        }
    }

    if ($selected | length) == 0 {
        print-setup-info "At least 'local' provider is required"
        ["local"]
    } else {
        $selected
    }
}

# ============================================================================
# RESOURCE CONFIGURATION PROMPTS
# ============================================================================

# Prompt for resource allocation
export def prompt-resource-allocation [
    detection_report: record
] {
    print-setup-header "Resource Allocation"
    print ""

    let current_cpus = $detection_report.system.cpu_count
    let current_memory = $detection_report.system.memory_gb

    let cpu_count = (prompt-number "Number of CPUs to allocate" 1 $current_cpus $current_cpus)
    let memory_gb = (prompt-number "Memory in GB to allocate" 1 $current_memory $current_memory)

    print ""
    print $"✅ Allocated ($cpu_count) CPUs and ($memory_gb) GB memory"

    {
        cpu_count: $cpu_count
        memory_gb: $memory_gb
    }
}

# ============================================================================
# SECURITY CONFIGURATION PROMPTS
# ============================================================================

# Prompt for security settings
export def prompt-security-config [] {
    print-setup-header "Security Configuration"
    print ""

    let enable_mfa = (prompt-yes-no "Enable Multi-Factor Authentication (MFA)?")
    let enable_audit = (prompt-yes-no "Enable audit logging for all operations?")
    let require_approval = (prompt-yes-no "Require approval for destructive operations?")

    {
        enable_mfa: $enable_mfa
        enable_audit: $enable_audit
        require_approval_for_destructive: $require_approval
    }
}

# ============================================================================
# WORKSPACE CONFIGURATION PROMPTS
# ============================================================================

# Prompt for initial workspace creation
export def prompt-initial-workspace [] {
    print-setup-header "Initial Workspace"
    print ""
    print "Create an initial workspace for your infrastructure?"
    print ""

    let create_workspace = (prompt-yes-no "Create workspace now?")

    if not $create_workspace {
        return {
            create_workspace: false
            name: ""
            description: ""
        }
    }

    let workspace_name = (prompt-text "Workspace name" "default")
    let workspace_description = (prompt-text "Workspace description (optional)" "")

    {
        create_workspace: true
        name: $workspace_name
        description: $workspace_description
    }
}

# ============================================================================
# COMPLETE SETUP WIZARD
# ============================================================================

# Run complete interactive setup wizard
export def run-setup-wizard [
    --verbose = false
] {
    # Check if running in TTY or piped mode
    let tty_check = (do { open /dev/tty | null } | complete)
    let is_interactive = ($tty_check.exit_code == 0)

    if not $is_interactive {
        # In non-TTY mode, switch to defaults automatically
        print "ℹ️  Non-interactive mode detected. Using recommended defaults..."
        print ""
        return (run-setup-with-defaults)
    }

    # Force immediate output
    print ""
    print "╔═══════════════════════════════════════════════════════════════╗"
    print "║         PROVISIONING SYSTEM SETUP WIZARD                      ║"
    print "║                                                               ║"
    print "║  This wizard will guide you through setting up provisioning   ║"
    print "║  for your infrastructure automation needs.                    ║"
    print "╚═══════════════════════════════════════════════════════════════╝"
    print ""

    # Step 1: Environment Detection
    print-setup-header "Step 1: Environment Detection"
    print "Analyzing your system configuration..."
    print ""

    # Use simplified detection to avoid hangs
    let detection_report = {
        system: {
            os: (detect-os)
            architecture: (detect-architecture)
            hostname: "localhost"
            current_user: (get-current-user)
            cpu_count: 4
            memory_gb: 8
            disk_gb: 100
        }
        capabilities: (get-deployment-capabilities)
        network: {
            internet_connected: true
            docker_port_available: true
            orchestrator_port_available: true
            control_center_port_available: true
            kms_port_available: true
        }
        existing_config: (get-existing-config-summary)
        platform_services: {
            orchestrator_running: false
            control_center_running: false
            kms_running: false
        }
        timestamp: (date now)
    }

    if $verbose {
        print-detection-report $detection_report
    }

    # Step 2: Profile Selection (NEW - determines setup approach)
    print ""
    let profile = (prompt-profile-selection)
    print-setup-success $"Selected profile: ($profile)"

    # Step 3: System Configuration
    let system_config = (prompt-system-config)

    # Step 5: Deployment Mode
    let deployment_mode = (prompt-deployment-mode $detection_report)
    print-setup-success $"Selected deployment mode: ($deployment_mode)"

    # Step 6: Provider Selection
    let providers = (prompt-providers)
    print-setup-success $"Selected providers: ($providers | str join ', ')"

    # Step 7: Resource Allocation
    let resources = (prompt-resource-allocation $detection_report)

    # Step 8: Security Settings
    let security = (prompt-security-config)

    # Step 9: Initial Workspace
    let workspace = (prompt-initial-workspace)

    # Summary
    print ""
    print-setup-header "Setup Summary"
    print ""
    print "Configuration Details:"
    print $"  Profile:         ($profile)"
    print $"  Config Path:     ($system_config.config_path)"
    print $"  OS:              ($system_config.os_name)"
    print $"  Deployment Mode: ($deployment_mode)"
    print $"  Providers:       ($providers | str join ', ')"
    print $"  CPUs:            ($resources.cpu_count)"
    print $"  Memory:          ($resources.memory_gb) GB"
    print $"  MFA Enabled:     (if $security.enable_mfa { 'Yes' } else { 'No' })"
    print $"  Audit Logging:   (if $security.enable_audit { 'Yes' } else { 'No' })"
    print ""

    let confirm = (prompt-yes-no "Proceed with this configuration?")

    if not $confirm {
        print-setup-warning "Setup cancelled"
        return {
            completed: false
            profile: ""
            system_config: {}
            deployment_mode: ""
            providers: []
            resources: {}
            security: {}
            workspace: {}
        }
    }

    print ""
    print-setup-success "Configuration confirmed!"
    print ""

    {
        completed: true
        profile: $profile
        system_config: $system_config
        deployment_mode: $deployment_mode
        providers: $providers
        resources: $resources
        security: $security
        workspace: $workspace
        timestamp: (date now)
    }
}

# ============================================================================
# QUICK SETUP (AUTOMATED WITH DEFAULTS)
# ============================================================================

# Run setup with recommended defaults (no interaction)
export def run-setup-with-defaults [] {
    print-setup-header "Quick Setup (Recommended Defaults)"
    print ""
    print "Configuring with system-recommended defaults..."
    print ""

    {
        completed: true
        system_config: {
            config_path: (get-config-base-path)
            os_name: (detect-os)
            cpu_count: (get-cpu-count)
            memory_gb: (get-system-memory-gb)
        }
        deployment_mode: "docker-compose"
        providers: ["local"]
        resources: {
            cpu_count: (get-cpu-count)
            memory_gb: (get-system-memory-gb)
        }
        security: {
            enable_mfa: true
            enable_audit: true
            require_approval_for_destructive: true
        }
        workspace: {
            create_workspace: true
            name: "default"
            description: "Default workspace"
        }
        timestamp: (date now)
    }
}

# Run minimal setup (only required settings)
export def run-minimal-setup [] {
    print-setup-header "Minimal Setup"
    print ""
    print "Configuring with minimal required settings..."
    print ""

    {
        completed: true
        system_config: {
            config_path: (get-config-base-path)
            os_name: (detect-os)
        }
        deployment_mode: "docker-compose"
        providers: ["local"]
        resources: {}
        security: {
            enable_mfa: false
            enable_audit: true
            require_approval_for_destructive: false
        }
        workspace: {
            create_workspace: false
        }
        timestamp: (date now)
    }
}

# ============================================================================
# TYPEDIALOG HELPER FUNCTIONS
# ============================================================================

# Run TypeDialog form via bash wrapper and return parsed result
# This pattern avoids TTY/input issues in Nushell's execution stack
def run-typedialog-form [
    form_path: string
    --backend: string = "tui"
] {
    # Guard 1: Check if plugin is available
    if (which typedialog | is-empty) {
        print-setup-error "TypeDialog plugin not available"
        return {
            success: false
            error: "TypeDialog plugin not available"
            use_fallback: true
        }
    }

    # Guard 2: Check if form file exists
    if not ($form_path | path exists) {
        print-setup-error $"Form not found: ($form_path)"
        return {
            success: false
            error: $"Form not found: ($form_path)"
            use_fallback: true
        }
    }

    # Main logic: Call the nu_plugin_typedialog plugin directly
    # The plugin handles TTY properly via Nushell's native plugin protocol
    let result = (typedialog form $form_path --backend $backend)

    if ($result | is-empty) {
        # User cancelled the form
        print-setup-warning "Setup wizard was cancelled"
        return {
            success: false
            error: "Form cancelled by user"
            use_fallback: false
        }
    }

    {
        success: true
        values: $result
        use_fallback: false
    }
}

# ============================================================================
# INTERACTIVE SETUP USING TYPEDIALOG
# ============================================================================

# Run setup wizard using TypeDialog - modern TUI experience
# Uses plugin directly for proper TTY handling
export def run-setup-wizard-interactive [
    --backend: string = "tui"
] {
    print ""
    print "╔═══════════════════════════════════════════════════════════════╗"
    print "║         PROVISIONING SYSTEM SETUP WIZARD (TypeDialog)        ║"
    print "║                                                               ║"
    print "║  This wizard will guide you through setting up provisioning   ║"
    print "║  for your infrastructure automation needs.                    ║"
    print "╚═══════════════════════════════════════════════════════════════╝"
    print ""

    # Get TypeDialog form path with absolute resolution
    let form_path = (get-typedialog-form-path "setup-wizard.toml")
    let form_result = (run-typedialog-form $form_path --backend $backend)

    # If TypeDialog not available or failed, fall back to basic wizard
    if (not $form_result.success or $form_result.use_fallback) {
        print-setup-info "Falling back to basic interactive wizard..."
        return (run-setup-wizard)
    }

    # Extract values from form results
    let values = $form_result.values

    # Collect selected providers
    let providers = (
        []
        | if ($values.providers?.upcloud? | default false) { append "upcloud" } else { . }
        | if ($values.providers?.aws? | default false) { append "aws" } else { . }
        | if ($values.providers?.hetzner? | default false) { append "hetzner" } else { . }
        | if ($values.providers?.local? | default false) { append "local" } else { . }
    )

    # Ensure at least one provider
    let providers_final = if ($providers | length) == 0 { ["local"] } else { $providers }

    # Create workspace config
    let workspace_final = {
        create_workspace: ($values.workspace?.create_workspace? | default false)
        name: ($values.workspace?.name? | default "default")
        description: ($values.workspace?.description? | default "")
    }

    # Display summary
    print ""
    print-setup-header "Setup Summary"
    print ""
    print "Configuration Details:"
    print $"  Config Path:     ($values.system_config?.config_path? | default (get-config-base-path))"
    print $"  Deployment Mode: ($values.deployment_mode? | default 'docker-compose')"
    print $"  Providers:       ($providers_final | str join ', ')"
    print $"  CPUs:            ($values.resources?.cpu_count? | default 4)"
    print $"  Memory:          ($values.resources?.memory_gb? | default 8) GB"
    print $"  MFA Enabled:     (if ($values.security?.enable_mfa? | default false) { 'Yes' } else { 'No' })"
    print $"  Audit Logging:   (if ($values.security?.enable_audit? | default false) { 'Yes' } else { 'No' })"
    print ""

    print-setup-success "Configuration confirmed!"
    print ""

    {
        completed: true
        system_config: {
            config_path: ($values.system_config?.config_path? | default (get-config-base-path))
            os_name: (detect-os)
            cpu_count: ($values.resources?.cpu_count? | default 4)
            memory_gb: ($values.resources?.memory_gb? | default 8)
        }
        deployment_mode: ($values.deployment_mode? | default "docker-compose")
        providers: $providers_final
        resources: {
            cpu_count: ($values.resources?.cpu_count? | default 4)
            memory_gb: ($values.resources?.memory_gb? | default 8)
        }
        security: {
            enable_mfa: ($values.security?.enable_mfa? | default true)
            enable_audit: ($values.security?.enable_audit? | default true)
            require_approval_for_destructive: ($values.security?.require_approval_for_destructive? | default true)
        }
        workspace: $workspace_final
        timestamp: (date now)
    }
}
