# Environment Management Commands
# CLI commands for managing provisioning environments

use ../config/accessor.nu *
use ../config/loader.nu *
use ../utils/ui.nu *
use std log

# List all available environments
export def "env list" [
    --config: record                # Optional pre-loaded config
] {
    print "Available environments:"
    let environments = (list-available-environments --config $config)
    let current_env = (get-current-environment --config $config)

    for env in $environments {
        if $env == $current_env {
            print $"  ✓ ($env) (current)"
        } else {
            print $"    ($env)"
        }
    }

    print ""
    print $"Current environment: ($current_env)"
}

# Show current environment information
export def "env current" [
    --config: record                # Optional pre-loaded config
] {
    let current_env = (get-current-environment --config $config)
    let config_data = if ($config | is-empty) {
        get-config --environment $current_env
    } else {
        $config
    }

    print $"Current environment: ($current_env)"
    print ""

    # Show environment-specific configuration
    let env_config = (config-get $"environments.($current_env)" {} --config $config_data)
    if ($env_config | is-not-empty) {
        print "Environment-specific configuration:"
        $env_config | to yaml | print
    } else {
        print "No environment-specific configuration found"
    }
}

# Switch to a different environment
export def "env switch" [
    environment: string             # Environment to switch to
    --validate = true               # Validate environment before switching
] {
    switch-environment $environment --validate=$validate
}

# Validate environment configuration
export def "env validate" [
    environment?: string            # Environment to validate (default: current)
    --strict = false                # Use strict validation
] {
    let target_env = if ($environment | is-not-empty) {
        $environment
    } else {
        get-current-environment
    }

    print $"Validating environment: ($target_env)"
    validate-current-config --environment=$target_env --strict=$strict
}

# Compare configurations between environments
export def "env compare" [
    env1: string                    # First environment
    env2: string                    # Second environment
    --section: string               # Specific section to compare
] {
    compare-environments $env1 $env2 --section=$section
}

# Show environment configuration
export def "env show" [
    environment?: string            # Environment to show (default: current)
    --section: string               # Show only specific section
    --format: string = "yaml"       # Output format (yaml, json, table)
] {
    let target_env = if ($environment | is-not-empty) {
        $environment
    } else {
        get-current-environment
    }

    print $"Environment: ($target_env)"
    print ""

    show-config --environment=$target_env --section=$section --format=$format
}

# Initialize environment-specific configuration
export def "env init" [
    environment: string             # Environment to initialize
    --template: string              # Template to use (dev, test, prod)
    --force = false                 # Overwrite existing config
] {
    init-environment-config $environment --template=$template --force=$force
}

# Detect current environment automatically
export def "env detect" [] {
    let detected_env = (detect-current-environment)
    print $"Detected environment: ($detected_env)"

    # Show detection details
    print ""
    print "Detection criteria:"

    # Check environment variables
    if ($env.PROVISIONING_ENV? | is-not-empty) {
        print $"  - PROVISIONING_ENV: ($env.PROVISIONING_ENV)"
    }

    if ($env.CI? | is-not-empty) {
        print "  - CI environment detected"
    }

    if ($env.NODE_ENV? | is-not-empty) {
        print $"  - NODE_ENV: ($env.NODE_ENV)"
    }

    if ($env.ENVIRONMENT? | is-not-empty) {
        print $"  - ENVIRONMENT: ($env.ENVIRONMENT)"
    }

    # Check directory indicators
    if ($env.PWD | path join ".git" | path exists) {
        print "  - Git repository detected (dev indicator)"
    }

    $detected_env
}

# Set environment variable and update configuration
export def "env set" [
    environment: string             # Environment to set
    --persist = false               # Persist to shell profile
] {
    # Validate environment first
    let config_data = (get-config)
    let validation = (validate-environment $environment $config_data)
    if not $validation.valid {
        error make {
            msg: $validation.message
        }
    }

    # Set environment variable
    $env.PROVISIONING_ENV = $environment
    print $"Set PROVISIONING_ENV=($environment)"

    if $persist {
        # Add to shell profile (simplified approach)
        let shell_config = match ($env.SHELL? | default "") {
            "/bin/bash" | "/usr/bin/bash" => "~/.bashrc"
            "/bin/zsh" | "/usr/bin/zsh" => "~/.zshrc"
            _ => "~/.profile"
        }

        print $"To persist this setting, add to your ($shell_config):"
        print $"export PROVISIONING_ENV=($environment)"
    }
}

# Get environment-specific paths
export def "env paths" [
    environment?: string            # Environment to get paths for
] {
    let target_env = if ($environment | is-not-empty) {
        $environment
    } else {
        get-current-environment
    }

    print $"Paths for environment: ($target_env)"
    let paths = (get-environment-paths --environment=$target_env)
    $paths | to yaml | print
}

# Create a new environment configuration template
export def "env create" [
    environment: string             # Environment name
    --template: string = "dev"      # Base template to copy from
    --description: string           # Description for the environment
] {
    # Create environment-specific config file
    let config_path = ($env.PWD | path join $"config.($environment).toml")

    if ($config_path | path exists) {
        let response = (input $"Environment config ($config_path) already exists. Overwrite? [y/N]: ")
        if ($response | str downcase) != "y" {
            print "Cancelled."
            return
        }
    }

    # Load base template
    let template_path = match $template {
        "dev" => "config.dev.toml.example"
        "test" => "config.test.toml.example"
        "prod" => "config.prod.toml.example"
        _ => "config.user.toml.example"
    }

    let base_path = (get-config-base-path)
    let source_template = ($base_path | path join $template_path)

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

    # Copy and customize template
    cp $source_template $config_path

    # Update the config with environment-specific details
    let config_content = (open $config_path)
    let updated_content = ($config_content | str replace --all "TEMPLATE_NAME" $environment)
    $updated_content | save $config_path

    print $"Created environment configuration: ($config_path)"
    if ($description | is-not-empty) {
        print $"Description: ($description)"
    }

    print ""
    print "Next steps:"
    print $"1. Edit the configuration: ($config_path)"
    print $"2. Validate: ./core/nulib/provisioning env validate ($environment)"
    print $"3. Switch to environment: ./core/nulib/provisioning env switch ($environment)"
}

# Delete environment configuration
export def "env delete" [
    environment: string             # Environment to delete
    --force = false                 # Skip confirmation
] {
    # Prevent deletion of system environments
    let protected_envs = ["dev" "test" "prod"]
    if ($environment in $protected_envs) {
        error make {
            msg: $"Cannot delete protected environment: ($environment)"
        }
    }

    if not $force {
        let response = (input $"Delete environment '($environment)'? This cannot be undone. [y/N]: ")
        if ($response | str downcase) != "y" {
            print "Cancelled."
            return
        }
    }

    # Remove environment-specific config files
    let config_files = [
        ($env.PWD | path join $"config.($environment).toml")
        ($env.HOME | path join ".config" | path join "provisioning" | path join $"config.($environment).toml")
    ]

    mut deleted_files = []
    for file in $config_files {
        if ($file | path exists) {
            rm $file
            $deleted_files = ($deleted_files | append $file)
        }
    }

    if ($deleted_files | length) > 0 {
        print $"Deleted environment configuration files:"
        for file in $deleted_files {
            print $"  - ($file)"
        }
    } else {
        print $"No configuration files found for environment: ($environment)"
    }
}

# Export environment configuration
export def "env export" [
    environment?: string            # Environment to export (default: current)
    --output: string               # Output file path
    --format: string = "toml"      # Export format (toml, yaml, json)
] {
    let target_env = if ($environment | is-not-empty) {
        $environment
    } else {
        get-current-environment
    }

    let config_data = (get-config --environment=$target_env)

    let output_path = if ($output | is-not-empty) {
        $output
    } else {
        $"exported-config-($target_env).($format)"
    }

    match $format {
        "yaml" => { $config_data | to yaml | save $output_path }
        "json" => { $config_data | to json --indent 2 | save $output_path }
        "toml" => { $config_data | to toml | save $output_path }
        _ => {
            error make {
                msg: $"Unsupported format: ($format). Use toml, yaml, or json."
            }
        }
    }

    print $"Exported ($target_env) environment configuration to: ($output_path)"
}

# Environment status and health check
export def "env status" [
    environment?: string            # Environment to check (default: current)
    --detailed = false              # Show detailed status
] {
    let target_env = if ($environment | is-not-empty) {
        $environment
    } else {
        get-current-environment
    }

    print $"Environment Status: ($target_env)"
    print ""

    # Validate configuration
    let validation = (validate-current-config --environment=$target_env)

    if $validation.valid {
        print "✅ Configuration: Valid"
    } else {
        print "❌ Configuration: Invalid"
        if $detailed {
            for error in $validation.errors {
                print $"  Error: ($error.message)"
            }
        }
    }

    # Check environment-specific settings
    let config_data = (get-config --environment=$target_env)

    # Check paths
    let base_path = (config-get "paths.base" "" --config $config_data)
    if ($base_path | path exists) {
        print "✅ Base path: Accessible"
    } else {
        print "❌ Base path: Not found"
    }

    # Check SOPS configuration
    let use_sops = (config-get "sops.use_sops" false --config $config_data)
    if $use_sops {
        let sops_key = (find-sops-key --config $config_data)
        if ($sops_key | is-not-empty) {
            print "✅ SOPS: Key found"
        } else {
            print "⚠️ SOPS: No key found"
        }
    } else {
        print "ℹ️ SOPS: Disabled"
    }

    # Check provider configuration
    let default_provider = (config-get "providers.default" "" --config $config_data)
    if ($default_provider | is-not-empty) {
        print $"✅ Provider: ($default_provider)"
    } else {
        print "❌ Provider: Not configured"
    }

    if $detailed {
        print ""
        print "Environment Configuration:"
        let env_config = (config-get $"environments.($target_env)" {} --config $config_data)
        if ($env_config | is-not-empty) {
            $env_config | to yaml | print
        } else {
            print "No environment-specific configuration"
        }
    }
}
