#!/usr/bin/env nu
# VAPORA Configuration Validation Utility
# Comprehensive validation of Nickel and rendered configurations
# Version: 1.0.0

def main [
    --config: string
    --mode: string
] {
    if ($config == null) and ($mode == null) {
        print "VAPORA Configuration Validator"
        print ""
        print "Usage:"
        print "  Validate single config: nu validate-config.nu --config <path>"
        print "  Validate mode config:   nu validate-config.nu --mode <solo|multiuser|enterprise>"
        print "  Validate all modes:     nu validate-config.nu --mode all"
        return
    }

    if ($config != null) {
        validate-config-file $config
    } else if ($mode == "all") {
        ["solo", "multiuser", "enterprise"] | each { |m| validate-mode $m }
    } else {
        validate-mode $mode
    }
}

def validate-mode [mode: string] {
    print $"🔍 Validating ($mode) mode configuration"
    print ""

    # Step 1: Export from Nickel
    print "Step 1: Generating from Nickel..."
    let config_file = ([$env.PWD, "..", "schemas", "platform", "configs", $"vapora-($mode).ncl"] | path join)

    if not ($config_file | path exists) {
        error make {msg: $"Config not found: ($config_file)"}
    }

    let result = do {
        nickel export $config_file
    } | complete

    if $result.exit_code != 0 {
        error make {msg: $"Nickel export failed: ($result.stderr)"}
    }

    let json_output = ($result.stdout | from json)
    print "  ✓ Nickel export successful"

    # Step 2: Validate structure
    print "Step 2: Validating structure..."
    validate-structure $json_output
    print "  ✓ Structure valid"

    # Step 3: Validate field ranges
    print "Step 3: Validating field ranges..."
    validate-ranges $json_output $mode
    print "  ✓ Field ranges valid"

    # Step 4: Validate provider configuration
    print "Step 4: Validating provider configuration..."
    validate-providers $json_output $mode
    print "  ✓ Provider configuration valid"

    # Step 5: Validate security settings
    print "Step 5: Validating security settings..."
    validate-security $json_output $mode
    print "  ✓ Security settings valid"

    # Step 6: Consistency checks
    print "Step 6: Checking consistency..."
    validate-consistency $json_output $mode
    print "  ✓ Consistency checks passed"

    print ""
    print $"✅ ($mode) configuration valid"
    print ""
}

def validate-config-file [config_path: string] {
    print $"🔍 Validating: ($config_path)"
    print ""

    if not ($config_path | path exists) {
        error make {msg: $"Config file not found: ($config_path)"}
    }

    # Determine file type
    if ($config_path | str ends-with ".json") {
        validate-json-file $config_path
    } else if ($config_path | str ends-with ".ncl") {
        validate-nickel-file $config_path
    } else if ($config_path | str ends-with ".toml") {
        validate-toml-file $config_path
    } else if ($config_path | str ends-with ".yaml") or ($config_path | str ends-with ".yml") {
        validate-yaml-file $config_path
    } else {
        error make {msg: "Unknown file type"}
    }
}

def validate-structure [config: record] {
    let required_fields = [
        "deployment_mode"
        "workspace_name"
        "backend"
        "agents"
        "llm_router"
        "frontend"
        "database"
        "nats"
        "providers"
        "monitoring"
        "security"
        "storage"
    ]

    let missing = $required_fields | where { |field|
        ($config | get $field -o) == null
    }

    if ($missing | length) > 0 {
        error make {msg: $"Missing required fields: ($missing | str join ', ')"}
    }

    # Validate nested structures
    let backend_required = ["host", "port", "workers", "auth", "database"]
    let backend_missing = $backend_required | where { |field|
        ($config.backend | get $field -i) == null
    }

    if ($backend_missing | length) > 0 {
        error make {msg: $"Backend missing: ($backend_missing | str join ', ')"}
    }
}

def validate-ranges [config: record, mode: string] {
    let port_min = 1024
    let port_max = 65535

    # Validate ports
    if ($config.backend.port < $port_min) or ($config.backend.port > $port_max) {
        error make {msg: $"Invalid backend port: ($config.backend.port)"}
    }

    if ($config.agents.port < $port_min) or ($config.agents.port > $port_max) {
        error make {msg: $"Invalid agents port: ($config.agents.port)"}
    }

    if ($config.llm_router.port < $port_min) or ($config.llm_router.port > $port_max) {
        error make {msg: $"Invalid llm_router port: ($config.llm_router.port)"}
    }

    # Validate workers based on mode
    let max_workers = match $mode {
        "solo" => 4
        "multiuser" => 16
        "enterprise" => 32
        _ => 4
    }

    if ($config.backend.workers < 1) or ($config.backend.workers > $max_workers) {
        error make {msg: $"Invalid worker count: ($config.backend.workers)"}
    }

    # Validate pool sizes
    if ($config.backend.database.pool_size < 1) or ($config.backend.database.pool_size > 500) {
        error make {msg: $"Invalid pool size: ($config.backend.database.pool_size)"}
    }

    # Validate timeouts
    if ($config.backend.request_timeout < 1000) or ($config.backend.request_timeout > 600000) {
        error make {msg: $"Invalid request timeout: ($config.backend.request_timeout)"}
    }
}

def validate-providers [config: record, mode: string] {
    let provider_count = [
        $config.providers.claude_enabled
        $config.providers.openai_enabled
        $config.providers.gemini_enabled
        $config.providers.ollama_enabled
    ] | where { |p| $p } | length

    if $provider_count == 0 {
        error make {msg: "At least one LLM provider must be enabled"}
    }

    # Validate Ollama URL if enabled
    if $config.providers.ollama_enabled {
        if ($config.providers.ollama_url | is-empty) {
            error make {msg: "Ollama enabled but URL not set"}
        }
        if not ($config.providers.ollama_url | str starts-with "http") {
            error make {msg: "Invalid Ollama URL format"}
        }
    }
}

def validate-security [config: record, mode: string] {
    # JWT secret warning (but allow empty for local dev)
    if ($config.backend.auth.jwt_secret | is-empty) and ($mode != "solo") {
        print "  ⚠️  Warning: JWT secret is empty (non-solo mode)"
    }

    # TLS validation
    if $config.security.tls_enabled {
        if ($config.security.tls_cert_path | is-empty) {
            error make {msg: "TLS enabled but cert path not set"}
        }
        if ($config.security.tls_key_path | is-empty) {
            error make {msg: "TLS enabled but key path not set"}
        }
    }

    # MFA validation
    if $config.backend.auth.mfa_enabled and ($config.backend.auth.method == "jwt") {
        print "  ⚠️  Warning: MFA with JWT only (consider OAuth2)"
    }
}

def validate-consistency [config: record, mode: string] {
    # Deployment mode consistency
    if $config.deployment_mode != $mode {
        error make {msg: $"Deployment mode mismatch: expected ($mode), got ($config.deployment_mode)"}
    }

    # Database URL should match mode expectations
    if $mode == "solo" {
        if not ($config.database.url | str contains "localhost") and not ($config.database.url | str contains "127.0.0.1") {
            print "  ⚠️  Warning: Solo mode with remote database"
        }
    } else if $mode == "multiuser" {
        if not ($config.agents.nats.enabled) {
            print "  ⚠️  Warning: Multiuser mode without NATS"
        }
    }

    # Enterprise mode should have high availability enabled
    if $mode == "enterprise" {
        if not ($config.agents.nats.enabled) {
            error make {msg: "Enterprise mode requires NATS enabled"}
        }
        if not ($config.monitoring.prometheus_enabled) {
            print "  ⚠️  Warning: Enterprise mode without Prometheus"
        }
    }

    # API URL should be set for non-localhost deployments
    if ($config.backend.host != "127.0.0.1") {
        if ($config.frontend.api_url == null) or ($config.frontend.api_url | is-empty) {
            print "  ⚠️  Warning: No API URL set for non-localhost backend"
        }
    }
}

def validate-json-file [path: string] {
    print "Validating JSON file..."

    let result = do {
        open $path
    } | complete

    if $result.exit_code != 0 {
        error make {msg: "Failed to parse JSON"}
    }

    let config = ($result.stdout | from json)
    print "  ✓ Valid JSON"

    validate-structure $config
    print "  ✓ Structure valid"

    print ""
    print "✅ JSON file valid"
}

def validate-nickel-file [path: string] {
    print "Validating Nickel file..."

    # Typecheck
    let typecheck_result = do {
        nickel typecheck $path
    } | complete

    if $typecheck_result.exit_code != 0 {
        error make {msg: $"Typecheck failed: ($typecheck_result.stderr)"}
    }
    print "  ✓ Typecheck passed"

    # Export
    let export_result = do {
        nickel export $path
    } | complete

    if $export_result.exit_code != 0 {
        error make {msg: $"Export failed: ($export_result.stderr)"}
    }
    print "  ✓ Export successful"

    print ""
    print "✅ Nickel file valid"
}

def validate-yaml-file [path: string] {
    print "Validating YAML file..."

    let result = do {
        yq eval '.' $path
    } | complete

    if $result.exit_code != 0 {
        error make {msg: "Invalid YAML syntax"}
    }

    print "  ✓ Valid YAML"
    print ""
    print "✅ YAML file valid"
}

def validate-toml-file [path: string] {
    print "Validating TOML file..."

    # Basic check: should parse and have [sections]
    let content = (open $path)
    if not ($content | str contains "[") {
        error make {msg: "Invalid TOML: no sections found"}
    }

    print "  ✓ Valid TOML structure"
    print ""
    print "✅ TOML file valid"
}

# Run main function
main
