# System Status Module
# Provides comprehensive system status checks for provisioning platform

use std log
# Selective imports (ADR-025 Phase 3 Layer 2).
# plugins/mod.nu star-import was dead — dropped.
use lib_provisioning/config/accessor/core.nu [config-get]
use lib_provisioning/user/config.nu [load-user-config]

# Check Nushell version meets requirements
def check-nushell-version [] {
    let current = (version).version
    let required = "0.107.1"

    let meets_requirement = (($current | str contains $required) or ($current >= $required))

    {
        component: "Nushell"
        status: (if $meets_requirement { "✅" } else { "❌" })
        version: $current
        required: $required
        message: (if $meets_requirement {
            "Version OK"
        } else {
            $"Update required: ($required)+"
        })
        docs: "https://nushell.sh"
    }
}

# Check if Nickel is installed
def check-nickel-installed [] {
    let nickel_bin = (which nickel | get path.0? | default "")
    let installed = ($nickel_bin | is-not-empty)

    let version_info = if $installed {
        let result = (do { ^nickel --version } | complete)
        if $result.exit_code == 0 {
            let version_full = ($result.stdout | str trim)
            # Extract version number and revision: "X.Y.Z (rev ...)"
            let version_short = ($version_full | str replace 'nickel-lang-cli nickel ' '')
            $version_short
        } else {
            "unknown"
        }
    } else {
        "not installed"
    }

    {
        component: "Nickel CLI"
        status: (if $installed { "✅" } else { "❌" })
        version: $version_info
        required: "0.11.2+"
        message: (if $installed {
            "Installed and available"
        } else {
            "Not found in PATH"
        })
        docs: "https://nickel-lang.io/docs/user_docs/getting-started/install"
    }
}

# Check required Nushell plugins
def check-plugins [] {
    let required_plugins = [
        {
            name: "nickel"
            description: "Nickel integration"
            optional: true
            docs: "docs/user/PLUGIN_INTEGRATION_GUIDE.md"
        }
        {
            name: "tera"
            description: "Template rendering"
            optional: false
            docs: "docs/user/PLUGIN_INTEGRATION_GUIDE.md"
        }
        {
            name: "auth"
            description: "Authentication"
            optional: true
            docs: "docs/user/AUTHENTICATION_LAYER_GUIDE.md"
        }
        {
            name: "kms"
            description: "Key management"
            optional: true
            docs: "docs/user/RUSTYVAULT_KMS_GUIDE.md"
        }
        {
            name: "orchestrator"
            description: "Orchestrator integration"
            optional: true
            docs: ".claude/features/orchestrator-architecture.md"
        }
    ]

    # Get list of registered plugins - use plugin list which returns structured data
    let installed = (plugin list)

    $required_plugins | each {|plugin|
        let is_installed = ($installed | any {|p| $p.name == $plugin.name})

        {
            component: $plugin.name
            status: (if $is_installed {
                "✅"
            } else if $plugin.optional {
                "⚠️"
            } else {
                "❌"
            })
            version: (if $is_installed { "registered" } else { "not registered" })
            required: (if $plugin.optional { "optional" } else { "required" })
            message: (if $is_installed {
                $plugin.description
            } else if $plugin.optional {
                $"($plugin.description) - optional, HTTP fallback available"
            } else {
                $"($plugin.description) - required for functionality"
            })
            docs: $plugin.docs
        }
    }
}

# Check active workspace configuration
def check-workspace [] {
    let user_config = (load-user-config)
    let active = ($user_config.active_workspace? | default null)

    if $active == null {
        return {
            component: "Active Workspace"
            status: "❌"
            version: "none"
            required: "configured"
            message: "No active workspace set"
            docs: "docs/user/WORKSPACE_SWITCHING_GUIDE.md"
        }
    }

    let workspace = ($user_config.workspaces | where name == $active | first)
    let ws_path = ($workspace.path? | default "")
    let ws_exists = ($ws_path | path exists)

    {
        component: "Active Workspace"
        status: (if $ws_exists { "✅" } else { "❌" })
        version: $active
        required: "configured"
        message: (if $ws_exists {
            $"Using ($active) at ($ws_path)"
        } else {
            $"Workspace ($active) path not found"
        })
        docs: "docs/user/WORKSPACE_SWITCHING_GUIDE.md"
    }
}

# Check available providers
def check-providers [] {
    let providers_path = config-get "paths.providers" "provisioning/extensions/providers"

    let available_providers = if ($providers_path | path exists) {
        ls $providers_path
            | where type == dir
            | where { |item|
                let provider_name = ($item.name | path basename)
                let bin_install_sh = ($providers_path | path join $provider_name | path join "bin" | path join "install.sh" | path exists)
                let bin_install_nu = ($providers_path | path join $provider_name | path join "bin" | path join "install.nu" | path exists)
                $bin_install_sh or $bin_install_nu
            }
            | get name
            | path basename
            | str join ", "
    } else {
        "none"
    }

    let has_providers = ($available_providers != "none")

    {
        component: "Cloud Providers"
        status: (if $has_providers { "✅" } else { "⚠️" })
        version: $available_providers
        required: "at least one"
        message: (if $has_providers {
            $"Available: ($available_providers)"
        } else {
            "No providers found"
        })
        docs: "docs/architecture/multi-repo-strategy.md"
    }
}

# Check orchestrator service
def check-orchestrator [] {
    let orchestrator_url = (config-get "platform.orchestrator.url" "http://localhost:9011")

    # Try to ping orchestrator health endpoint (handle connection errors gracefully)
    let result = (do { ^curl -s -f $"($orchestrator_url)/health" --max-time 2 } | complete)
    let is_running = ($result.exit_code == 0)

    {
        component: "Orchestrator Service"
        status: (if $is_running { "✅" } else { "⚠️" })
        version: (if $is_running { $"running on ($orchestrator_url)" } else { "not running" })
        required: "recommended"
        message: (if $is_running {
            "Service healthy and responding"
        } else {
            "Optional service not running. Review startup options"
        })
        docs: ".claude/features/orchestrator-architecture.md"
    }
}

# Check platform services
def check-platform-services [] {
    let services = [
        {
            name: "Control Center"
            port: (config-get "control_center.port" 8080)
            optional: true
            docs: "provisioning/platform/control-center/README.md"
        }
        {
            name: "MCP Server"
            port: (config-get "mcp_server.port" 3000)
            optional: true
            docs: "provisioning/platform/mcp-server/README.md"
        }
        {
            name: "API Gateway"
            port: (config-get "api_gateway.port" 8090)
            optional: true
            docs: "provisioning/platform/api-gateway/README.md"
        }
    ]

    $services | each {|svc|
        let result = (do { ^curl -s -f $"http://localhost:($svc.port)/health" --max-time 1 } | complete)
        let is_running = ($result.exit_code == 0)

        {
            component: $svc.name
            status: (if $is_running { "✅" } else { "⚠️" })
            version: (if $is_running { $"running on :($svc.port)" } else { "not running" })
            required: "optional"
            message: (if $is_running {
                "Service available"
            } else {
                "Service not running - optional"
            })
            docs: $svc.docs
        }
    }
}

# Collect all status checks
# Refactored to use immutable pattern per Rule 3 (Nushell 0.110.0 compatibility)
def get-all-checks [] {
    # Concatenate all check results immutably
    [
        (check-nushell-version)
        (check-nickel-installed)
        (check-plugins)
        (check-workspace)
        (check-providers)
        (check-orchestrator)
        (check-platform-services)
    ] | flatten
}

# Main system status command
# Comprehensive system status check showing all component states
export def "provisioning status" [] {
    print $"(ansi cyan_bold)Provisioning Platform Status(ansi reset)\n"

    let all_checks = (get-all-checks)
    let results = ($all_checks | select component status version message)
    print ($results | table)
}

# Get status summary (machine-readable)
export def "provisioning status-json" [] {
    let all_checks = (get-all-checks)

    let total = ($all_checks | length)
    let passing = ($all_checks | where status == "✅" | length)
    let warnings = ($all_checks | where status == "⚠️" | length)
    let failing = ($all_checks | where status == "❌" | length)

    {
        timestamp: (date now | format date "%Y-%m-%dT%H:%M:%SZ")
        summary: {
            total: $total
            passing: $passing
            warnings: $warnings
            failing: $failing
            health_percentage: (($passing / $total) * 100 | math round)
        }
        checks: $all_checks
        ready_for_deployment: ($failing == 0)
    }
}
