# Provider Configuration Module
# Manages infrastructure provider setup and configuration (UpCloud, AWS, Hetzner)
# Follows Nushell guidelines: explicit types, single purpose, no try-catch

use ./mod.nu *
use ./validation.nu *

# ============================================================================
# PROVIDER VALIDATION
# ============================================================================

# Check if provider is available in current workspace
export def is-provider-available [
    provider_name: string
    workspace_path: string
] {
    let provider_config = $"($workspace_path)/config/providers/($provider_name).toml"
    ($provider_config | path exists)
}

# Get list of available providers
export def get-available-providers [
    config_base: string
] {
    let providers_dir = $"($config_base)/providers"

    if not ($providers_dir | path exists) {
        return []
    }

    let result = (do {
        ls -la $providers_dir | where name =~ r'\.toml$' | get name | str replace ".toml" ""
    } | complete)

    if ($result.exit_code == 0) {
        $result.stdout | lines | where { |x| ($x | str length) > 0 }
    } else {
        []
    }
}

# ============================================================================
# PROVIDER CONFIGURATION FILES
# ============================================================================

# Create UpCloud provider configuration
export def create-upcloud-config [
    config_base: string
] {
    let provider_config = $"($config_base)/providers/upcloud.toml"

    let upcloud_config = {
        api_url: "https://api.upcloud.com/1.3"
        interface: "API"
        credentials_source: "rustyvault://system/providers/upcloud"
        timeout_seconds: 30
        zones: ["de-fra1", "nl-ams1", "sg-sin1", "us-nyc1", "us-sfo1", "gb-lnd1"]
    }

    save-config-toml $provider_config $upcloud_config
}

# Create AWS provider configuration
export def create-aws-config [
    config_base: string
] {
    let provider_config = $"($config_base)/providers/aws.toml"

    let aws_config = {
        region: "us-east-1"
        credentials_source: "rustyvault://system/providers/aws"
        timeout_seconds: 30
        regions: ["us-east-1", "us-west-2", "eu-west-1", "ap-southeast-1"]
    }

    save-config-toml $provider_config $aws_config
}

# Create Hetzner provider configuration
export def create-hetzner-config [
    config_base: string
] {
    let provider_config = $"($config_base)/providers/hetzner.toml"

    let hetzner_config = {
        api_url: "https://api.hetzner.cloud/v1"
        credentials_source: "rustyvault://system/providers/hetzner"
        timeout_seconds: 30
        locations: ["fsn1", "nbg1", "ash", "hel1", "sin"]
    }

    save-config-toml $provider_config $hetzner_config
}

# Create local provider configuration
export def create-local-config [
    config_base: string
] {
    let provider_config = $"($config_base)/providers/local.toml"

    let local_config = {
        base_path: "/tmp/provisioning-local"
        timeout_seconds: 10
    }

    save-config-toml $provider_config $local_config
}

# ============================================================================
# PROVIDER SETUP
# ============================================================================

# Setup provider configuration
export def setup-provider [
    provider_name: string
    config_base: string = ""
    --interactive = false
] {
    let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base })

    # Validate provider name
    let validation = (validate-provider-name $provider_name)
    if not $validation.valid {
        print-setup-error $validation.error
        return {
            success: false
            error: $validation.error
        }
    }

    print-setup-header $"Setting up ($provider_name) Provider"
    print ""

    # Create provider configuration
    let creation_result = (match $provider_name {
        "upcloud" => { create-upcloud-config $base }
        "aws" => { create-aws-config $base }
        "hetzner" => { create-hetzner-config $base }
        "local" => { create-local-config $base }
        _ => { false }
    })

    if not $creation_result {
        print-setup-error $"Failed to create ($provider_name) provider configuration"
        return {
            success: false
            error: $"Failed to create provider configuration for ($provider_name)"
        }
    }

    print-setup-success $"($provider_name) provider configuration created"
    print-setup-info "Credentials will be loaded from RustyVault at runtime"

    let timestamp_value = (get-timestamp-iso8601)
    {
        success: true
        provider: $provider_name
        config_path: $"($base)/providers/($provider_name).toml"
        timestamp: $timestamp_value
    }
}

# Setup all selected providers
export def setup-providers [
    providers: list<string>
    config_base: string = ""
] {
    let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base })

    print-setup-header "Setting up Providers"
    print ""

    mut results = []
    mut errors = []

    for provider in $providers {
        print-setup-info $"Configuring ($provider)..."
        let result = (setup-provider $provider $base)

        if $result.success {
            $results = ($results | append $result)
            print-setup-success $"($provider) configured"
        } else {
            $errors = ($errors | append $result.error)
            print-setup-warning $result.error
        }
    }

    print ""

    let success_status = ($errors | length) == 0
    let provider_list = ($results | map { |r| $r.provider })
    let configured_count = ($results | length)
    let error_count = ($errors | length)
    let timestamp_value = (get-timestamp-iso8601)
    {
        success: $success_status
        providers: $provider_list
        configured_count: $configured_count
        error_count: $error_count
        errors: $errors
        timestamp: $timestamp_value
    }
}

# ============================================================================
# PROVIDER CREDENTIALS (References to RustyVault)
# ============================================================================

# Get provider credentials reference
export def get-provider-credentials-reference [
    provider_name: string
    workspace_name: string = "system"
] {
    $"rustyvault://($workspace_name)/providers/($provider_name)"
}

# Validate credentials reference format
export def validate-credentials-reference [
    credentials_source: string
] {
    let is_valid = (
        ($credentials_source | str starts-with "rustyvault://") or
        ($credentials_source | str starts-with "vault://") or
        ($credentials_source | str starts-with "kms://")
    )

    let error_message = (if not $is_valid {
        "Credentials source must start with rustyvault://, vault://, or kms://"
    } else {
        null
    })

    {
        value: $credentials_source
        valid: $is_valid
        error: $error_message
    }
}

# ============================================================================
# PROVIDER INFORMATION
# ============================================================================

# Print provider setup instructions
export def print-provider-setup-instructions [] {
    print ""
    print "╔═══════════════════════════════════════════════════════════════╗"
    print "║            PROVIDER SETUP INSTRUCTIONS                       ║"
    print "╚═══════════════════════════════════════════════════════════════╝"
    print ""

    print "📋 PROVIDER CREDENTIALS"
    print "─────────────────────────────────────────────────────────────"
    print ""
    print "Provider credentials are stored SECURELY in RustyVault with:"
    print "  ✅ Encryption at rest (AES-256)"
    print "  ✅ Dynamic secrets with TTL"
    print "  ✅ Automatic rotation policies"
    print "  ✅ Audit logging of all access"
    print ""

    print "UpCloud Provider"
    print "─────────────────────────────────────────────────────────────"
    print "To setup UpCloud credentials in RustyVault:"
    print ""
    print "  1. Obtain API credentials from https://hub.upcloud.com/account"
    print "  2. Store in RustyVault:"
    print "     provisioning secrets store upcloud-creds \\"
    print "       --username <username> \\"
    print "       --password <api-token>"
    print ""
    print "  3. Credentials available as: rustyvault://system/providers/upcloud"
    print ""

    print "AWS Provider"
    print "─────────────────────────────────────────────────────────────"
    print "To setup AWS credentials in RustyVault:"
    print ""
    print "  1. Create IAM user with programmatic access"
    print "  2. Store in RustyVault:"
    print "     provisioning secrets store aws-creds \\"
    print "       --access-key-id <key-id> \\"
    print "       --secret-access-key <secret-key> \\"
    print "       --ttl 3600"
    print ""
    print "  3. Credentials available as: rustyvault://system/providers/aws"
    print ""

    print "Hetzner Provider"
    print "─────────────────────────────────────────────────────────────"
    print "To setup Hetzner credentials in RustyVault:"
    print ""
    print "  1. Create API token from https://console.hetzner.cloud"
    print "  2. Store in RustyVault:"
    print "     provisioning secrets store hetzner-creds \\"
    print "       --api-token <token>"
    print ""
    print "  3. Credentials available as: rustyvault://system/providers/hetzner"
    print ""

    print "Local Provider"
    print "─────────────────────────────────────────────────────────────"
    print "Local provider requires no credentials - perfect for testing!"
    print ""

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

# Print available providers
export def print-available-providers [
    config_base: string = ""
] {
    let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base })
    let available = (get-available-providers $base)

    print ""
    print "Configured Providers:"
    print "─────────────────────────────────────────────────────────────"

    if ($available | length) == 0 {
        print "  (No providers configured yet)"
    } else {
        for provider in $available {
            let config_path = $"($base)/providers/($provider).toml"
            print $"  ✅ ($provider)"
            print $"      Path: ($config_path)"
        }
    }

    print ""
}

# Get provider information
export def get-provider-info [
    provider_name: string
    config_base: string = ""
] {
    let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base })
    let config_path = $"($base)/providers/($provider_name).toml"

    let config = if ($config_path | path exists) {
        load-config-toml $config_path
    } else {
        {}
    }

    let exists_status = ($config_path | path exists)
    {
        provider: $provider_name
        exists: $exists_status
        config_path: $config_path
        configuration: $config
    }
}
