# Cache Management CLI Commands
# Provides user-facing commands for cache operations and configuration
# Follows Nushell 0.109.0+ guidelines

use ./core.nu *
use ./metadata.nu *
# Avoid importing all modules - use only what's needed
# use ./config_manager.nu *
# use ./nickel.nu *
# use ./sops.nu *
# use ./final.nu *

# ============================================================================
# Data Operations: Clear, List, Warm, Validate
# ============================================================================

# Clear all or specific type of cache
export def cache-clear [
    --type: string = "all"    # "all", "nickel", "sops", "final", "provider", "platform"
    --force = false           # Skip confirmation
] {
    if (not $force) and ($type == "all") {
        let response = (input "Clear ALL cache? This cannot be undone. (yes/no): ")
        if $response != "yes" {
            print "Cancelled."
            return
        }
    }

    match $type {
        "all" => {
            print "Clearing all caches..."
            do {
                cache-clear-type "nickel"
                cache-clear-type "sops"
                cache-clear-type "final"
                cache-clear-type "provider"
                cache-clear-type "platform"
            } | complete | ignore
            print "✅ All caches cleared"
        },
        "nickel" => {
            print "Clearing Nickel compilation cache..."
            clear-nickel-cache
            print "✅ Nickel cache cleared"
        },
        "sops" => {
            print "Clearing SOPS decryption cache..."
            clear-sops-cache
            print "✅ SOPS cache cleared"
        },
        "final" => {
            print "Clearing final configuration cache..."
            clear-final-cache
            print "✅ Final config cache cleared"
        },
        _ => {
            print $"❌ Unknown cache type: ($type)"
        }
    }
}

# List cache entries
export def cache-list [
    --type: string = "*"      # "nickel", "sops", "final", etc or "*" for all
    --format: string = "table" # "table", "json", "yaml"
] {
    let stats = (get-cache-stats)

    if ($stats.total_entries | is-empty) or ($stats.total_entries == 0) {
        print "📭 Cache is empty"
        return
    }

    let home = ($env.HOME? | default "~" | path expand)
    let base = ($home | path join ".provisioning" "cache" "config")

    mut entries = []

    let type_dir = match $type {
        "all" => $base,
        "nickel" => ($base | path join "nickel"),
        "sops" => ($base | path join "sops"),
        "final" => ($base | path join "workspaces"),
        _ => ($base | path join $type)
    }

    if not ($type_dir | path exists) {
        print $"No cache directory for type: ($type)"
        return
    }

    for meta_file in (glob $"($type_dir)/**/*.meta") {
        let cache_file = ($meta_file | str substring 0..-6)
        let meta = (do { open $meta_file } | complete | get stdout)

        if $meta.exit_code == 0 {
            let size_result = (do {
                if ($cache_file | path exists) {
                    $cache_file | stat | get size
                } else {
                    0
                }
            } | complete)

            if $size_result.exit_code == 0 {
                let size_kb = ($size_result.stdout / 1024)
                let cache_type = ($meta_file | path dirname | path basename)

                $entries = ($entries | append {
                    type: $cache_type,
                    key: ($cache_file | path basename),
                    size_kb: ($size_kb | math round -p 2),
                    created: ($meta.stdout.created_at? | default "unknown"),
                    expires: ($meta.stdout.expires_at? | default "unknown")
                })
            }
        }
    }

    if ($entries | length) == 0 {
        print "📭 No cache entries found"
        return
    }

    match $format {
        "json" => {
            $entries | to json --indent 2 | print
        },
        "yaml" => {
            $entries | to yaml | print
        },
        _ => {
            print $"📦 Cache Entries (($entries | length)) total):\n"
            $entries | table
        }
    }
}

# Warm cache (pre-populate)
export def cache-warm [
    --workspace: string = ""
    --environment: string = "*"
] {
    print "🔥 Warming cache..."

    if ($workspace | is-empty) {
        # Try to get active workspace
        use ../user/config.nu get-active-workspace
        let active = (get-active-workspace)

        if ($active | is-empty) {
            print "❌ No active workspace. Use: provisioning workspace activate <name>"
            return
        }

        print $"Warming cache for workspace: ($active.name)"
        do {
            warm-nickel-cache $active.path
        } | complete | ignore
    } else {
        print $"Warming cache for workspace: ($workspace)"
    }

    print "✅ Cache warming complete"
}

# Validate cache integrity
export def cache-validate [] {
    print "🔍 Validating cache integrity..."

    let home = ($env.HOME? | default "~" | path expand)
    let base = ($home | path join ".provisioning" "cache" "config")

    if not ($base | path exists) {
        return {
            valid: true,
            total_files: 0,
            errors: [],
            warnings: []
        }
    }

    mut errors = []
    mut warnings = []
    mut total_files = 0

    # Check SOPS permissions
    let sops_stats = (get-sops-cache-stats)
    if ($sops_stats.permission_errors | default 0) > 0 {
        $errors = ($errors | append $"SOPS cache: ($sops_stats.permission_errors) files with invalid permissions")
    }

    # Check all metadata files
    for meta_file in (glob $"($base)/**/*.meta") {
        $total_files += 1
        let cache_file = ($meta_file | str substring 0..-6)

        let meta_result = (do { open $meta_file } | complete)
        if $meta_result.exit_code != 0 {
            $errors = ($errors | append $"Cannot read metadata: ($meta_file)")
            continue
        }

        let meta = $meta_result.stdout

        # Check expiration
        let now = (date now | format date "%Y-%m-%dT%H:%M:%SZ")
        if $now > $meta.expires_at {
            $warnings = ($warnings | append $"Expired cache: ($cache_file)")
        }
    }

    let result = {
        valid: ($errors | length) == 0,
        total_files: $total_files,
        errors: $errors,
        warnings: $warnings
    }

    if $result.valid {
        print "✅ Cache validation passed"
    } else {
        print "❌ Cache validation failed"
        for error in $errors {
            print $"  ❌ ($error)"
        }
    }

    if ($warnings | length) > 0 {
        for warning in $warnings {
            print $"  ⚠️  ($warning)"
        }
    }

    $result
}

# ============================================================================
# Configuration Commands: Show, Get, Set, Reset
# ============================================================================

# Show cache configuration (enhanced with paths and all settings)
export def cache-config-show [
    --format: string = "table"
] {
    let config = (get-cache-config)

    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print "📋 Cache Configuration"
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print ""

    print "▸ Core Settings:"
    print $"  Enabled: ($config.enabled)"
    print $"  Max Size: ($config.max_cache_size / 1048576 | math round -p 0) MB"
    print ""

    print "▸ Cache Location:"
    print $"  Base Path: ($config.paths.base)"
    print ""

    print "▸ Time-To-Live (TTL) Settings:"
    print $"  Final Config: ($config.ttl.final_config)s (5 minutes)"
    print $"  Nickel Compilation: ($config.ttl.nickel_compilation)s (30 minutes)"
    print $"  SOPS Decryption: ($config.ttl.sops_decryption)s (15 minutes)"
    print $"  Provider Config: ($config.ttl.provider_config)s (10 minutes)"
    print $"  Platform Config: ($config.ttl.platform_config)s (10 minutes)"
    print ""

    print "▸ Security Settings:"
    print $"  SOPS File Permissions: ($config.security.sops_file_permissions)"
    print $"  SOPS Dir Permissions: ($config.security.sops_dir_permissions)"
    print ""

    print "▸ Validation Settings:"
    print $"  Strict mtime Checking: ($config.validation.strict_mtime)"
    print ""

    print "▸ Metadata:"
    print $"  Last Modified: ($config.metadata.last_modified)"
    print $"  Modified By: ($config.metadata.modified_by)"
    print $"  Config Version: ($config.metadata.version)"
    print ""
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}

# Get specific cache configuration setting
export def cache-config-get [
    setting_path: string    # "enabled", "ttl.final_config", etc.
] {
    let value = (cache-config-get $setting_path)

    if ($value | is-empty) {
        print $"Setting not found: ($setting_path)"
        return
    }

    print $"($setting_path): ($value)"
    $value
}

# Set cache configuration
export def cache-config-set [
    setting_path: string
    value: any
] {
    print $"Setting ($setting_path) = ($value)"
    cache-config-set $setting_path $value
    print "✅ Configuration updated"
}

# Reset cache configuration
export def cache-config-reset [
    setting_path?: string = ""
] {
    if ($setting_path | is-empty) {
        let confirm = (input "Reset ALL cache configuration to defaults? (yes/no): ")
        if $confirm != "yes" {
            print "Cancelled."
            return
        }
        cache-config-reset
        print "✅ All configuration reset to defaults"
    } else {
        print $"Resetting ($setting_path) to default..."
        cache-config-reset $setting_path
        print "✅ Setting reset to default"
    }
}

# Validate cache configuration
export def cache-config-validate [] {
    print "Validating cache configuration..."
    let result = (cache-config-validate)

    if $result.valid {
        print "✅ Configuration is valid"
    } else {
        print "❌ Configuration has errors:"
        for error in $result.errors {
            print $"  ❌ ($error)"
        }
    }

    if ($result.warnings | length) > 0 {
        print "⚠️  Warnings:"
        for warning in $result.warnings {
            print $"  ⚠️  ($warning)"
        }
    }

    $result
}

# ============================================================================
# Monitoring: Status, Stats
# ============================================================================

# Show comprehensive cache status (configuration + statistics)
export def cache-status [] {
    let status = (get-cache-status)

    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print "📊 Cache Configuration"
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

    let config = $status.configuration
    print $"  Enabled: ($config.enabled)"
    print $"  Max Size: ($status.max_size_mb) MB"
    print $"  Current Usage: ($status.current_usage_percent)%"

    print ""
    print "  TTL Settings:"
    print $"    Final Config: ($config.ttl.final_config)s (5 min)"
    print $"    Nickel Compilation: ($config.ttl.nickel_compilation)s (30 min)"
    print $"    SOPS Decryption: ($config.ttl.sops_decryption)s (15 min)"
    print $"    Provider Config: ($config.ttl.provider_config)s (10 min)"
    print $"    Platform Config: ($config.ttl.platform_config)s (10 min)"

    print ""
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print "📈 Cache Statistics"
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

    let stats = $status.statistics
    print $"  Total Entries: ($stats.total_entries)"
    print $"  Total Size: ($stats.total_size_mb | math round -p 2) MB"

    print ""
    print "  By Type:"

    let nickel_stats = (get-nickel-cache-stats)
    print $"    Nickel: ($nickel_stats.total_entries) entries, ($nickel_stats.total_size_mb | math round -p 2) MB"

    let sops_stats = (get-sops-cache-stats)
    print $"    SOPS: ($sops_stats.total_entries) entries, ($sops_stats.total_size_mb | math round -p 2) MB"

    let final_stats = (get-final-cache-stats)
    print $"    Final Config: ($final_stats.total_entries) entries, ($final_stats.total_size_mb | math round -p 2) MB"

    print ""
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}

# Show cache statistics only
export def cache-stats [
    --format: string = "table"
] {
    let stats = (get-cache-stats)

    print $"📊 Cache Statistics\n"
    print $"  Total Entries: ($stats.total_entries)"
    print $"  Total Size: ($stats.total_size_mb | math round -p 2) MB"
    print ""

    let nickel_stats = (get-nickel-cache-stats)
    let sops_stats = (get-sops-cache-stats)
    let final_stats = (get-final-cache-stats)

    let summary = [
        { type: "Nickel Compilation", entries: $nickel_stats.total_entries, size_mb: ($nickel_stats.total_size_mb | math round -p 2) },
        { type: "SOPS Decryption", entries: $sops_stats.total_entries, size_mb: ($sops_stats.total_size_mb | math round -p 2) },
        { type: "Final Config", entries: $final_stats.total_entries, size_mb: ($final_stats.total_size_mb | math round -p 2) }
    ]

    match $format {
        "json" => {
            $summary | to json --indent 2 | print
        },
        "yaml" => {
            $summary | to yaml | print
        },
        _ => {
            print "By Type:"
            $summary | table
        }
    }
}

# ============================================================================
# Helper: Dispatch cache commands
# ============================================================================

# Main cache command dispatcher
export def main [
    ...args: string
] {
    if ($args | is-empty) {
        cache-status
        return
    }

    let command = ($args | get 0)
    let rest = (if ($args | length) > 1 { $args | skip 1 } else { [] })

    match $command {
        "clear" => {
            let cache_type = ($rest | get 0 | default "all")
            cache-clear --type $cache_type
        },
        "list" => {
            cache-list
        },
        "warm" => {
            cache-warm
        },
        "validate" => {
            cache-validate | ignore
        },
        "config" => {
            let subcommand = ($rest | get 0 | default "show")
            match $subcommand {
                "show" => { cache-config-show },
                "get" => {
                    let path = ($rest | get 1 | default "")
                    if ($path | is-empty) {
                        print "Usage: cache config get <setting>"
                    } else {
                        cache-config-get $path | ignore
                    }
                },
                "set" => {
                    let path = ($rest | get 1 | default "")
                    let value = ($rest | get 2 | default "")
                    if ($path | is-empty) or ($value | is-empty) {
                        print "Usage: cache config set <setting> <value>"
                    } else {
                        cache-config-set $path $value
                    }
                },
                "reset" => {
                    let path = ($rest | get 1 | default "")
                    cache-config-reset $path
                },
                "validate" => {
                    cache-config-validate | ignore
                },
                _ => {
                    print $"Unknown config subcommand: ($subcommand)"
                }
            }
        },
        "status" => {
            cache-status
        },
        "stats" => {
            cache-stats
        },
        "help" => {
            print "Cache Management Commands:

  cache clear [--type <type>]     Clear cache (all, nickel, sops, final)
  cache list                       List cache entries
  cache warm                       Pre-populate cache
  cache validate                   Validate cache integrity

  cache config show                Show configuration
  cache config get <path>          Get specific setting
  cache config set <path> <value>  Set configuration
  cache config reset [path]        Reset to defaults
  cache config validate            Validate configuration

  cache status                     Show full status (config + stats)
  cache stats                      Show statistics only

  cache help                       Show this help"
        },
        _ => {
            print $"Unknown cache command: ($command)"
            print "Use 'cache help' for available commands"
        }
    }
}
