# provctl Integration Module
# Optional integration with provctl for enhanced service management
# Graceful fallback when provctl is not installed
# Follows Nushell guidelines: explicit types, single purpose, no try-catch

use ./mod.nu *
use ./detection.nu *

# ============================================================================
# PROVCTL DETECTION
# ============================================================================

# Check if provctl is installed
export def has-provctl [] {
    let which_result = (do { which provctl } | complete)
    ($which_result.exit_code == 0)
}

# Check if provctl is accessible and functional
export def provctl-available [] {
    let installed = (has-provctl)
    if not $installed {
        return false
    }

    # Verify provctl can run
    let version_check = (do { provctl --version o> /dev/null e> /dev/null } | complete)
    ($version_check.exit_code == 0)
}

# Get provctl version
export def get-provctl-version [] {
    let result = (do { provctl --version } | complete)
    if ($result.exit_code == 0) {
        $result.stdout | str trim
    } else {
        "unknown"
    }
}

# Get provctl configuration directory
export def get-provctl-config-dir [] {
    match $nu.os-info.name {
        "macos" => {
            let home = ($env.HOME? | default "~" | path expand)
            $"($home)/Library/Application Support/provctl"
        }
        "windows" => {
            let appdata = ($env.APPDATA? | default "~" | path expand)
            $"($appdata)/provctl"
        }
        _ => {
            let home = ($env.HOME? | default "~" | path expand)
            $"($home)/.config/provctl"
        }
    }
}

# ============================================================================
# PROVCTL CONFIGURATION GENERATION
# ============================================================================

# Generate provctl configuration from provisioning config
export def generate-provctl-config [
    config_base: string
] {
    let provisioning_config = (load-config-toml $"($config_base)/system.toml")
    let platform_config = (load-config-toml $"($config_base)/platform/deployment.toml")

    {
        version: "1.0.0"
        provisioning: {
            path: $config_base
            system_config: $"($config_base)/system.toml"
            platform_config: $"($config_base)/platform"
            providers: $"($config_base)/providers"
        }
        deployment: {
            mode: ($platform_config.deployment.mode? | default "docker-compose")
            location_type: ($platform_config.deployment.location_type? | default "local")
        }
        services: {
            orchestrator: {
                endpoint: ($platform_config.services.orchestrator.endpoint? | default "http://localhost:9090")
            }
            control_center: {
                endpoint: ($platform_config.services.control_center.endpoint? | default "http://localhost:3000")
            }
            kms_service: {
                endpoint: ($platform_config.services.kms_service.endpoint? | default "http://localhost:3001")
            }
        }
        generated_at: (get-timestamp-iso8601)
    }
}

# ============================================================================
# PROVCTL SETUP
# ============================================================================

# Initialize provctl configuration directory
export def setup-provctl-config-dir [] {
    let provctl_dir = (get-provctl-config-dir)
    let mkdir_result = (do { mkdir $provctl_dir } | complete)
    ($mkdir_result.exit_code == 0)
}

# Write provisioning configuration to provctl
export def write-provctl-config [
    config_base: string
] {
    if not (setup-provctl-config-dir) {
        return false
    }

    let provctl_dir = (get-provctl-config-dir)
    let provctl_config = (generate-provctl-config $config_base)
    let config_path = $"($provctl_dir)/provisioning-config.toml"

    save-config-toml $config_path $provctl_config
}

# Register platform services with provctl
export def register-services-with-provctl [
    --verbose = false
] {
    if not (provctl-available) {
        return {
            success: false
            reason: "provctl not available"
            services_registered: []
        }
    }

    let services = ["orchestrator", "control-center", "kms-service"]
    mut registered = []
    mut errors = []

    for service in $services {
        if $verbose {
            print-setup-info $"Registering ($service) with provctl..."
        }

        let result = (do {
            provctl service register $service o> /dev/null e> /dev/null
        } | complete)

        if ($result.exit_code == 0) {
            $registered = ($registered | append $service)
            if $verbose {
                print-setup-success $"Registered ($service)"
            }
        } else {
            $errors = ($errors | append $service)
            if $verbose {
                print-setup-warning $"Failed to register ($service)"
            }
        }
    }

    let success_status = ($errors | length) == 0
    let timestamp_value = (get-timestamp-iso8601)
    {
        success: $success_status
        services_registered: $registered
        registration_errors: $errors
        timestamp: $timestamp_value
    }
}

# ============================================================================
# FALLBACK DETECTION
# ============================================================================

# Determine if provctl fallback is needed
export def needs-provctl-fallback [] {
    not (provctl-available)
}

# Get fallback deployment method
export def get-fallback-method [
    detection_report: record
] {
    let caps = $detection_report.capabilities

    if ($caps.docker_available and $caps.docker_compose_available) {
        "docker-compose"
    } else if ($caps.kubectl_available) {
        "kubernetes"
    } else if ($caps.ssh_available) {
        "remote-ssh"
    } else if ($caps.systemd_available) {
        "systemd"
    } else {
        "unknown"
    }
}

# ============================================================================
# DEPLOYMENT MODE ENHANCEMENT
# ============================================================================

# Enhance deployment configuration with provctl features (if available)
export def enhance-deployment-with-provctl [
    config_base: string
    --verbose = false
] {
    if not (provctl-available) {
        if $verbose {
            print-setup-info "provctl not available - using standard deployment"
        }
        return {
            enhanced: false
            method: "standard"
            reason: "provctl not installed"
        }
    }

    if $verbose {
        print-setup-info $"Using provctl v(get-provctl-version) for enhanced deployment"
    }

    # Write provctl configuration
    let config_result = (write-provctl-config $config_base)
    if not $config_result {
        if $verbose {
            print-setup-warning "Failed to write provctl configuration"
        }
        return {
            enhanced: false
            method: "fallback"
            reason: "Failed to configure provctl"
        }
    }

    # Register services with provctl
    let registration_result = (register-services-with-provctl --verbose=$verbose)
    if not $registration_result.success {
        if $verbose {
            print-setup-warning "Failed to register services with provctl"
        }
        return {
            enhanced: true
            method: "partial"
            registered_services: $registration_result.services_registered
            reason: "Partial provctl integration"
        }
    }

    {
        enhanced: true
        method: "provctl"
        registered_services: $registration_result.services_registered
        provctl_version: (get-provctl-version)
        provctl_config_dir: (get-provctl-config-dir)
        timestamp: (get-timestamp-iso8601)
    }
}

# ============================================================================
# SERVICE LIFECYCLE WITH PROVCTL
# ============================================================================

# Start services using provctl if available, fallback to direct commands
export def start-services-optimized [
    deployment_mode: string
    --use_provctl = true
    --verbose = false
] {
    # Check if provctl should/can be used
    let provctl_ok = ($use_provctl and (provctl-available))

    if $provctl_ok {
        if $verbose {
            print-setup-info "Starting services via provctl..."
        }

        let result = (do {
            provctl service deploy --mode $deployment_mode o> /dev/null e> /dev/null
        } | complete)

        if ($result.exit_code == 0) {
            if $verbose {
                print-setup-success "Services started via provctl"
            }

            return {
                success: true
                method: "provctl"
                deployment_mode: $deployment_mode
                timestamp: (get-timestamp-iso8601)
            }
        } else {
            if $verbose {
                print-setup-warning "provctl deployment failed - using fallback"
            }
        }
    }

    # Fallback: Direct deployment without provctl
    if $verbose {
        print-setup-info "Starting services directly (no provctl)..."
    }

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

# ============================================================================
# PROVCTL STATUS AND MONITORING
# ============================================================================

# Get status of services via provctl
export def get-provctl-service-status [] {
    if not (provctl-available) {
        return {
            provctl_available: false
            services: []
        }
    }

    let result = (do {
        provctl service status --output json
    } | complete)

    if ($result.exit_code == 0) {
        let services = (do { $result.stdout | from json } | complete)
        {
            provctl_available: true
            services: ($services.stdout? | default [])
        }
    } else {
        {
            provctl_available: true
            services: []
            error: "Failed to query service status"
        }
    }
}

# Watch services with provctl
export def watch-services [
    --interval: int = 5
    --duration: int = 300
] {
    if not (provctl-available) {
        print-setup-error "provctl not available"
        return
    }

    print-setup-info $"Watching services every ($interval) seconds for ($duration) seconds..."
    print ""

    let end_time = ((date now) + ($duration | into duration --unit sec))

    loop {
        let current_time = (date now)
        if ($current_time > $end_time) {
            break
        }

        let status = (get-provctl-service-status)
        print $"($current_time | format date '%H:%M:%S') - Services: ($status.services | length)"

        sleep ($interval | into duration --unit sec)
    }

    print ""
    print-setup-success "Service watch completed"
}

# ============================================================================
# PROVCTL SETUP REPORT
# ============================================================================

# Print provctl integration status
export def print-provctl-status [] {
    print ""
    print "╔═══════════════════════════════════════════════════════════════╗"
    print "║            PROVCTL INTEGRATION STATUS                        ║"
    print "╚═══════════════════════════════════════════════════════════════╝"
    print ""

    if (provctl-available) {
        print "✅ provctl is installed and available"
        print ""
        print $"Version: (get-provctl-version)"
        print $"Config Directory: (get-provctl-config-dir)"
        print ""
        print "Status: Enhanced deployment features available"
        print "  • Service lifecycle management"
        print "  • Zero-downtime updates"
        print "  • Advanced monitoring"
        print "  • Hot-reload capabilities"
    } else if (has-provctl) {
        print "⚠️  provctl is installed but not functional"
        print ""
        print "Fallback: Using standard deployment methods"
    } else {
        print "ℹ️  provctl is not installed (optional)"
        print ""
        print "Fallback: Using standard deployment methods"
        print "  • docker-compose / kubernetes / SSH / systemd"
        print ""
        print "To enable advanced features, install provctl:"
        print "  https://github.com/provisioning/provctl"
    }

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

# ============================================================================
# COMPLETE PROVCTL SETUP
# ============================================================================

# Execute complete provctl integration setup
export def setup-provctl-integration [
    config_base: string
    --verbose = false
] {
    print-setup-header "provctl Integration Setup"
    print ""

    if not (provctl-available) {
        print-setup-info "provctl not available - setup is optional"
        print-setup-info "Provisioning will use fallback deployment methods"
        print ""
        return {
            success: true
            provctl_integrated: false
            reason: "provctl not installed"
            fallback_available: true
        }
    }

    print-setup-success "provctl detected - setting up integration..."
    print ""

    # Enhance deployment with provctl
    let enhancement = (enhance-deployment-with-provctl $config_base --verbose=$verbose)

    if $enhancement.enhanced {
        print-setup-success "provctl integration completed"
        print ""
        if $verbose {
            print-setup-info $"Registered services: ($enhancement.registered_services | str join ', ')"
        }
    } else {
        print-setup-warning "provctl integration partial - using fallback"
    }

    print ""

    {
        success: true
        provctl_integrated: $enhancement.enhanced
        provctl_version: (get-provctl-version)
        deployment_method: $enhancement.method
        registered_services: ($enhancement.registered_services? | default [])
        timestamp: (get-timestamp-iso8601)
    }
}

# ============================================================================
# PROVCTL OPTIONAL MODE HELPERS
# ============================================================================

# Check if setup mode requires provctl
export def mode-requires-provctl [
    mode: string
] {
    match $mode {
        "enterprise" => true  # Only enterprise mode requires provctl
        _ => false
    }
}

# Get setup mode recommendation based on provctl availability
export def recommend-setup-mode [
    detection_report: record
] {
    let provctl_ok = (provctl-available)

    if $provctl_ok {
        "enterprise"  # Can use all features
    } else {
        # Recommend mode based on available tools
        let fallback = (get-fallback-method $detection_report)
        match $fallback {
            "docker-compose" => "solo"
            "kubernetes" => "cicd"
            "remote-ssh" => "remote"
            _ => "minimal"
        }
    }
}

# ============================================================================
# COMPATIBILITY CHECK
# ============================================================================

# Check if provisioning and provctl versions are compatible
export def check-provctl-compatibility [] {
    if not (provctl-available) {
        return {
            compatible: true
            reason: "provctl not installed - compatibility check skipped"
        }
    }

    let provctl_version = (get-provctl-version)
    let provisioning_version = "1.0.0"

    # Simple compatibility check: both should be 1.x
    let provctl_major = (
        if ($provctl_version | str contains "1.") { "1" }
        else { "2" }
    )

    let provisioning_major = "1"

    {
        compatible: ($provctl_major == $provisioning_major)
        provisioning_version: $provisioning_version
        provctl_version: $provctl_version
        warning: (
            if ($provctl_major != $provisioning_major) {
                "Version mismatch detected - functionality may be limited"
            } else {
                null
            }
        )
    }
}
