# Platform Services Setup Module
# Manages deployment and initialization of platform services (Orchestrator, Control Center, KMS)
# Follows Nushell guidelines: explicit types, single purpose, no try-catch

# Selective imports (ADR-025 Phase 3 Layer 2).
# setup/validation.nu star-import was dead — dropped.
use lib_provisioning/setup/mod.nu [
    get-config-base-path get-cpu-count get-system-memory-gb
    get-timestamp-iso8601 load-config-toml print-setup-error print-setup-header
    print-setup-info print-setup-success print-setup-warning save-config-toml
]
use lib_provisioning/setup/detection.nu [
    has-docker has-docker-compose has-kubectl has-ssh has-systemd
]
use lib_provisioning/platform/bootstrap.nu [bootstrap-platform]

# ============================================================================
# DEPLOYMENT MODE VALIDATION
# ============================================================================

# Validate deployment mode is supported
export def validate-deployment-mode [
    mode: string
] {
    let valid_modes = ["docker-compose", "kubernetes", "remote-ssh", "systemd"]
    let is_valid = ($mode | inside $valid_modes)

    {
        mode: $mode
        valid: $is_valid
        valid_modes: $valid_modes
        error: (if not $is_valid { $"Invalid deployment mode: ($mode)" } else { null })
    }
}

# Check deployment mode support on current system
export def check-deployment-mode-support [
    mode: string
] {
    let support = (match $mode {
        "docker-compose" => {
            let docker_ok = (has-docker)
            let compose_ok = (has-docker-compose)
            {
                supported: ($docker_ok and $compose_ok)
                docker: $docker_ok
                docker_compose: $compose_ok
                reason: (if not $docker_ok { "Docker not installed" } else if not $compose_ok { "Docker Compose not found" } else { "OK" })
            }
        }
        "kubernetes" => {
            let kubectl_ok = (has-kubectl)
            {
                supported: $kubectl_ok
                kubectl: $kubectl_ok
                reason: (if not $kubectl_ok { "kubectl not installed" } else { "OK" })
            }
        }
        "remote-ssh" => {
            let ssh_ok = (has-ssh)
            {
                supported: $ssh_ok
                ssh: $ssh_ok
                reason: (if not $ssh_ok { "SSH not installed" } else { "OK" })
            }
        }
        "systemd" => {
            let systemd_ok = (has-systemd)
            {
                supported: $systemd_ok
                systemd: $systemd_ok
                reason: (if not $systemd_ok { "systemd not available" } else { "OK" })
            }
        }
        _ => {
            {
                supported: false
                reason: $"Unknown deployment mode: ($mode)"
            }
        }
    })

    {
        mode: $mode
        support: $support
    }
}

# ============================================================================
# SERVICE PORT MANAGEMENT
# ============================================================================

# Reserve ports for platform services
export def reserve-service-ports [
    orchestrator_port: int = 9090
    control_center_port: int = 3000
    kms_port: int = 3001
] {
    mut reserved_ports = []
    mut port_conflicts = []

    # Check orchestrator port
    let orch_validation = (validate-port-available $orchestrator_port)
    if not $orch_validation.valid {
        $port_conflicts = ($port_conflicts | append $orch_validation.error)
    } else {
        $reserved_ports = ($reserved_ports | append {name: "orchestrator", port: $orchestrator_port})
    }

    # Check control center port
    let cc_validation = (validate-port-available $control_center_port)
    if not $cc_validation.valid {
        $port_conflicts = ($port_conflicts | append $cc_validation.error)
    } else {
        $reserved_ports = ($reserved_ports | append {name: "control-center", port: $control_center_port})
    }

    # Check KMS port
    let kms_validation = (validate-port-available $kms_port)
    if not $kms_validation.valid {
        $port_conflicts = ($port_conflicts | append $kms_validation.error)
    } else {
        $reserved_ports = ($reserved_ports | append {name: "kms-service", port: $kms_port})
    }

    {
        reserved_ports: $reserved_ports,
        conflicts: $port_conflicts,
        all_available: (($port_conflicts | length) == 0)
    }
}

# ============================================================================
# PLATFORM SERVICES STARTUP
# ============================================================================

# Bootstrap and start platform services
export def start-platform-services [
    deployment_mode: string
    --auto_start = true
    --verbose = false
] {
    # Validate deployment mode
    let mode_validation = (validate-deployment-mode $deployment_mode)
    if not $mode_validation.valid {
        print-setup-error $mode_validation.error
        return {
            success: false
            error: $mode_validation.error
        }
    }

    # Check deployment mode support
    let support_check = (check-deployment-mode-support $deployment_mode)
    if not $support_check.support.supported {
        print-setup-error $support_check.support.reason
        return {
            success: false
            error: $support_check.support.reason
        }
    }

    print-setup-info $"Starting platform services using ($deployment_mode) mode..."

    # Bootstrap services (from bootstrap.nu)
    let bootstrap_result = (do {
        bootstrap-platform --auto-start=$auto_start --verbose=$verbose --timeout=60
    } | complete)

    if ($bootstrap_result.exit_code != 0) {
        print-setup-warning "Platform services bootstrap encountered issues"
        return {
            success: true
            warning: "Bootstrap completed with warnings"
            deployment_mode: $deployment_mode
        }
    }

    print-setup-success "Platform services started successfully"

    {
        success: true
        deployment_mode: $deployment_mode
        timestamp: (get-timestamp-iso8601)
    }
}

# ============================================================================
# SERVICE CONFIGURATION
# ============================================================================

# Apply platform services configuration
export def apply-platform-config [
    config_base: string
    config_data: record
] {
    let deployment_config_path = $"($config_base)/platform/deployment.toml"

    # Load current deployment config if it exists
    let current_config = (do {
        if ($deployment_config_path | path exists) {
            load-config-toml $deployment_config_path
        } else {
            {}
        }
    } | complete)

    # Merge with new configuration
    let updated_config = (
        if ($current_config.exit_code == 0) {
            $current_config.stdout | merge $config_data
        } else {
            $config_data
        }
    )

    # Save updated configuration
    let save_result = (save-config-toml $deployment_config_path $updated_config)

    {
        success: $save_result
        config_path: $deployment_config_path
        timestamp: (get-timestamp-iso8601)
    }
}

# ============================================================================
# SERVICE VERIFICATION
# ============================================================================

# Verify platform services are running
export def verify-platform-services [] {
    let orch_health = (do { curl -s -f http://localhost:9090/health o> /dev/null e> /dev/null } | complete).exit_code == 0
    let cc_health = (do { curl -s -f http://localhost:3000/health o> /dev/null e> /dev/null } | complete).exit_code == 0
    let kms_health = (do { curl -s -f http://localhost:3001/health o> /dev/null e> /dev/null } | complete).exit_code == 0

    {
        orchestrator: {
            running: $orch_health
            endpoint: "http://localhost:9090"
        }
        control_center: {
            running: $cc_health
            endpoint: "http://localhost:3000"
        }
        kms_service: {
            running: $kms_health
            endpoint: "http://localhost:3001"
        }
        all_healthy: ($orch_health and $cc_health and $kms_health)
    }
}

# ============================================================================
# PLATFORM SETUP MODES
# ============================================================================

# Setup platform for solo development
export def setup-platform-solo [
    config_base: string
    --verbose = false
] {
    print-setup-header "Setting up Platform (Solo Mode)"
    print ""
    print "Solo mode: Single-user local development setup"
    print ""

    # Check Docker availability
    if not (has-docker) {
        print-setup-error "Docker is required for solo mode"
        return {
            success: false
            error: "Docker not installed"
        }
    }

    # Reserve ports
    let port_check = (reserve-service-ports)
    if not $port_check.all_available {
        print-setup-warning $"Port conflicts: ($port_check.conflicts | str join ', ')"
    }

    # Apply configuration
    let config_result = (apply-platform-config $config_base {
        deployment: {
            mode: "docker-compose"
            location_type: "local"
        }
    })

    # Start services
    let start_result = (start-platform-services "docker-compose" --verbose=$verbose)

    {
        success: ($config_result.success and $start_result.success)
        mode: "solo"
        deployment: "docker-compose"
        timestamp: (get-timestamp-iso8601)
    }
}

# Setup platform for multi-user team
export def setup-platform-multiuser [
    config_base: string
    --verbose = false
] {
    print-setup-header "Setting up Platform (Multi-user Mode)"
    print ""
    print "Multi-user mode: Shared team environment"
    print ""

    # Check Docker Compose availability (preferred)
    let preferred_mode = if (has-docker-compose) {
        "docker-compose"
    } else if (has-kubectl) {
        "kubernetes"
    } else if (has-systemd) {
        "systemd"
    } else {
        ""
    }

    if ($preferred_mode == "") {
        print-setup-error "No suitable deployment method found for multi-user setup"
        return {
            success: false
            error: "Missing required tools"
        }
    }

    print-setup-info $"Using deployment mode: ($preferred_mode)"

    # Reserve ports
    let port_check = (reserve-service-ports)
    if not $port_check.all_available {
        print-setup-warning $"Port conflicts: ($port_check.conflicts | str join ', ')"
    }

    # Apply configuration
    let config_result = (apply-platform-config $config_base {
        deployment: {
            mode: $preferred_mode
            location_type: "local"
        }
    })

    # Start services
    let start_result = (start-platform-services $preferred_mode --verbose=$verbose)

    {
        success: ($config_result.success and $start_result.success)
        mode: "multiuser"
        deployment: $preferred_mode
        timestamp: (get-timestamp-iso8601)
    }
}

# Setup platform for CI/CD
export def setup-platform-cicd [
    config_base: string
    --verbose = false
] {
    print-setup-header "Setting up Platform (CI/CD Mode)"
    print ""
    print "CI/CD mode: Automated deployment pipeline setup"
    print ""

    # Check Kubernetes availability
    let deployment_mode = if (has-kubectl) {
        "kubernetes"
    } else if (has-docker-compose) {
        "docker-compose"
    } else {
        ""
    }

    if ($deployment_mode == "") {
        print-setup-error "Kubernetes or Docker Compose required for CI/CD mode"
        return {
            success: false
            error: "Missing required tools"
        }
    }

    print-setup-info $"Using deployment mode: ($deployment_mode)"

    # Apply configuration
    let config_result = (apply-platform-config $config_base {
        deployment: {
            mode: $deployment_mode
            location_type: "local"
        }
    })

    # Start services with longer timeouts
    let start_result = (start-platform-services $deployment_mode --verbose=$verbose)

    {
        success: ($config_result.success and $start_result.success)
        mode: "cicd"
        deployment: $deployment_mode
        timestamp: (get-timestamp-iso8601)
    }
}

# ============================================================================
# PROFILE-BASED SETUP (NICKEL-ALWAYS)
# ============================================================================

# Setup platform for developer profile (fast, local, type-safe)
export def setup-platform-developer [
    config_base: string = ""
    --verbose = false
] {
    print-setup-header "Setting up Platform (Developer Profile)"
    print ""
    print "Developer profile: Fast local setup with type-safe Nickel validation"
    print ""

    let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base })

    # Check Docker availability
    if not (has-docker) {
        print-setup-error "Docker is required for developer profile"
        return {
            success: false
            error: "Docker not installed"
        }
    }

    print-setup-info "Generating Nickel platform configuration..."
    if not (create-platform-config-nickel $base "docker-compose" "developer") {
        print-setup-error "Failed to generate Nickel platform config"
        return {
            success: false
            error: "Failed to generate Nickel platform config"
        }
    }

    print-setup-info "Validating Nickel configuration..."
    let validation = (validate-nickel-config $"($base)/platform/deployment.ncl")
    if not $validation {
        print-setup-error "Nickel validation failed"
        return {
            success: false
            error: "Nickel validation failed"
        }
    }

    # Reserve ports
    let port_check = (reserve-service-ports)
    if not $port_check.all_available {
        print-setup-warning $"Port conflicts: ($port_check.conflicts | str join ', ')"
    }

    # Start services
    let start_result = (start-platform-services "docker-compose" --verbose=$verbose)

    {
        success: $start_result.success
        profile: "developer"
        deployment: "docker-compose"
        config_base: $base
        timestamp: (get-timestamp-iso8601)
    }
}

# Setup platform for production profile (validated, secure, HA)
export def setup-platform-production [
    config_base: string = ""
    --verbose = false
] {
    print-setup-header "Setting up Platform (Production Profile)"
    print ""
    print "Production profile: Validated deployment with security and HA"
    print ""

    let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base })

    # Check Kubernetes availability (preferred for production)
    let deployment_mode = if (has-kubectl) {
        "kubernetes"
    } else if (has-docker-compose) {
        "docker-compose"
    } else {
        ""
    }

    if ($deployment_mode == "") {
        print-setup-error "Kubernetes or Docker Compose required for production profile"
        return {
            success: false
            error: "Missing required tools"
        }
    }

    print-setup-info $"Using deployment mode: ($deployment_mode)"

    # Check Nickel is available for production-grade validation
    let nickel_check = (do { which nickel } | complete)
    if ($nickel_check.exit_code != 0) {
        print-setup-warning "Nickel not installed - validation will be skipped (recommended to install for production)"
    }

    print-setup-info "Generating Nickel platform configuration..."
    if not (create-platform-config-nickel $base $deployment_mode "production") {
        print-setup-error "Failed to generate Nickel platform config"
        return {
            success: false
            error: "Failed to generate Nickel platform config"
        }
    }

    print-setup-info "Validating Nickel configuration..."
    let validation = (validate-nickel-config $"($base)/platform/deployment.ncl")
    if not $validation {
        print-setup-error "Nickel validation failed"
        return {
            success: false
            error: "Nickel validation failed"
        }
    }

    # Pre-flight checks for production
    print-setup-info "Running production pre-flight checks..."
    let cpu_count = (get-cpu-count)
    let memory_gb = (get-system-memory-gb)

    if ($deployment_mode == "kubernetes") {
        if ($cpu_count < 4) {
            print-setup-warning "Production Kubernetes deployment recommended with at least 4 CPUs"
        }
        if ($memory_gb < 8) {
            print-setup-warning "Production Kubernetes deployment recommended with at least 8GB RAM"
        }
    }

    # Reserve ports
    let port_check = (reserve-service-ports)
    if not $port_check.all_available {
        print-setup-warning $"Port conflicts: ($port_check.conflicts | str join ', ')"
    }

    # Start services
    let start_result = (start-platform-services $deployment_mode --verbose=$verbose)

    {
        success: $start_result.success
        profile: "production"
        deployment: $deployment_mode
        config_base: $base
        timestamp: (get-timestamp-iso8601)
    }
}

# Setup platform for CI/CD profile (ephemeral, automated, fast)
export def setup-platform-cicd-nickel [
    config_base: string = ""
    --verbose = false
] {
    print-setup-header "Setting up Platform (CI/CD Profile)"
    print ""
    print "CI/CD profile: Ephemeral deployment for automated pipelines"
    print ""

    let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base })

    # Prefer Docker Compose for CI/CD (faster startup)
    let deployment_mode = if (has-docker-compose) {
        "docker-compose"
    } else if (has-kubectl) {
        "kubernetes"
    } else {
        ""
    }

    if ($deployment_mode == "") {
        print-setup-error "Docker Compose or Kubernetes required for CI/CD profile"
        return {
            success: false
            error: "Missing required tools"
        }
    }

    print-setup-info $"Using deployment mode: ($deployment_mode)"

    print-setup-info "Generating Nickel platform configuration..."
    if not (create-platform-config-nickel $base $deployment_mode "cicd") {
        print-setup-error "Failed to generate Nickel platform config"
        return {
            success: false
            error: "Failed to generate Nickel platform config"
        }
    }

    print-setup-info "Validating Nickel configuration..."
    let validation = (validate-nickel-config $"($base)/platform/deployment.ncl")
    if not $validation {
        print-setup-warning "Nickel validation skipped - continuing with setup"
    }

    # Start services (CI/CD uses longer timeouts for reliability)
    let start_result = (start-platform-services $deployment_mode --verbose=$verbose)

    {
        success: $start_result.success
        profile: "cicd"
        deployment: $deployment_mode
        config_base: $base
        timestamp: (get-timestamp-iso8601)
    }
}

# ============================================================================
# COMPLETE PLATFORM SETUP
# ============================================================================

# Execute complete platform setup by profile
export def setup-platform-complete-by-profile [
    profile: string = "developer"
    config_base: string = ""
    --verbose = false
] {
    match $profile {
        "developer" => { setup-platform-developer $config_base --verbose=$verbose }
        "production" => { setup-platform-production $config_base --verbose=$verbose }
        "cicd" => { setup-platform-cicd-nickel $config_base --verbose=$verbose }
        _ => {
            print-setup-error $"Unknown profile: ($profile)"
            {
                success: false
                error: $"Unknown profile: ($profile)"
            }
        }
    }
}

# Execute complete platform setup (backward compatible)
export def setup-platform-complete [
    setup_mode: string = "solo"
    config_base: string = ""
    --verbose = false
] {
    let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base })

    # Map legacy modes to profiles (backward compatibility)
    let profile = match $setup_mode {
        "solo" => "developer"
        "developer" => "developer"
        "multiuser" => "production"
        "production" => "production"
        "cicd" => "cicd"
        _ => "developer"
    }

    setup-platform-complete-by-profile $profile $base --verbose=$verbose
}

# Print platform services status report
export def print-platform-status [] {
    let status = (verify-platform-services)

    print ""
    print "╔═══════════════════════════════════════════════════════════════╗"
    print "║            PLATFORM SERVICES STATUS REPORT                   ║"
    print "╚═══════════════════════════════════════════════════════════════╝"
    print ""

    let orch_icon = if $status.orchestrator.running { "✅" } else { "❌" }
    let cc_icon = if $status.control_center.running { "✅" } else { "❌" }
    let kms_icon = if $status.kms_service.running { "✅" } else { "❌" }

    print $"($orch_icon) Orchestrator"
    print $"   Endpoint: ($status.orchestrator.endpoint)"
    print $"   Status: (if $status.orchestrator.running { 'Running' } else { 'Not Running' })"
    print ""

    print $"($cc_icon) Control Center"
    print $"   Endpoint: ($status.control_center.endpoint)"
    print $"   Status: (if $status.control_center.running { 'Running' } else { 'Not Running' })"
    print ""

    print $"($kms_icon) KMS Service"
    print $"   Endpoint: ($status.kms_service.endpoint)"
    print $"   Status: (if $status.kms_service.running { 'Running' } else { 'Not Running' })"
    print ""

    if $status.all_healthy {
        print "✅ All platform services are healthy!"
    } else {
        print "❌ Some platform services are not running"
    }

    print ""
    print "═══════════════════════════════════════════════════════════════"
    print ""
}
