#!/usr/bin/env nu

# Enhanced Module Loader CLI with Template and Layer Support
# Supports the new layered template architecture

use ../nulib/taskservs/discover.nu *
use ../nulib/taskservs/load.nu *
use ../nulib/providers/discover.nu *
use ../nulib/providers/load.nu *
use ../nulib/clusters/discover.nu *
use ../nulib/clusters/load.nu *

# Load workspace template utilities
source ../../workspace/tools/template-utils.nu
source ../../workspace/tools/layer-utils.nu

# Main module loader command with enhanced features
def main [subcommand?: string] {
    if ($subcommand | is-empty) {
        print_enhanced_help
        return
    }

    match $subcommand {
        "help" => print_enhanced_help
        "discover" => print_discover_help
        "load" => print_load_help
        "list" => print_list_help
        "unload" => print_unload_help
        "template" => print_template_help
        "layer" => print_layer_help
        "override" => print_override_help
        _ => {
            print $"Unknown command: ($subcommand)"
            print_enhanced_help
        }
    }
}

# === TEMPLATE COMMANDS ===

# List available templates
export def "main template list" [
    --type = "all",        # Template type: taskservs, providers, servers, clusters, all
    --format = "table"     # Output format: table, yaml, json
] {
    let manifest = open ../../workspace/registry/manifest.yaml

    let templates = match $type {
        "taskservs" => $manifest.templates.taskservs
        "providers" => $manifest.templates.providers
        "servers" => $manifest.templates.servers
        "clusters" => $manifest.templates.clusters
        "all" => $manifest.templates
        _ => {
            error make {msg: $"Invalid type: ($type). Use: taskservs, providers, servers, clusters, all"}
        }
    }

    match $format {
        "json" => ($templates | to json)
        "yaml" => ($templates | to yaml)
        "table" => ($templates | table)
        _ => ($templates | table)
    }
}

# Extract infrastructure patterns to templates
export def "main template extract" [
    infra_name: string,    # Infrastructure to extract from (e.g., "wuji")
    --to: string = "templates",  # Target: templates, workspace
    --type = "all",        # Extract type: taskservs, providers, all
    --overwrite = false    # Overwrite existing templates
] {
    print $"🔄 Extracting patterns from ($infra_name) infrastructure"

    let infra_path = $"workspace/infra/($infra_name)"

    if not ($infra_path | path exists) {
        error make {msg: $"Infrastructure ($infra_name) not found at ($infra_path)"}
    }

    # Extract taskservs if requested
    if $type in ["taskservs", "all"] {
        extract_taskserv_patterns $infra_name $to $overwrite
    }

    # Extract provider configurations if requested
    if $type in ["providers", "all"] {
        extract_provider_patterns $infra_name $to $overwrite
    }

    print $"✅ Extraction completed for ($infra_name)"
}

# Apply template to infrastructure
export def "main template apply" [
    template_name: string,     # Template to apply (e.g., "kubernetes-ha")
    target_infra: string,      # Target infrastructure name
    --provider = "upcloud",    # Target provider
    --customize = false        # Open for customization after apply
] {
    print $"🔄 Applying template ($template_name) to ($target_infra)"

    let manifest = open ../../workspace/registry/manifest.yaml
    let template_info = get_template_info $manifest $template_name

    if ($template_info | is-empty) {
        error make {msg: $"Template ($template_name) not found"}
    }

    # Create target directory if it doesn't exist
    let target_dir = $"workspace/infra/($target_infra)"
    mkdir $target_dir

    apply_template_to_infra $template_info $target_infra $provider

    if $customize {
        print $"🔧 Opening template for customization..."
        ^$env.EDITOR $"($target_dir)/taskservs/($template_name).k"
    }

    print $"✅ Template applied successfully to ($target_infra)"
}

# === LAYER COMMANDS ===

# Show layer resolution order
export def "main layer show" [
    --infra?: string       # Show resolution for specific infrastructure
] {
    print "📋 Layer Resolution Order:"
    print "1. Core Layer (Priority: 100) - provisioning/extensions"
    print "2. Workspace Layer (Priority: 200) - provisioning/workspace/templates"

    if ($infra | is-not-empty) {
        print $"3. Infra Layer (Priority: 300) - workspace/infra/($infra)"
    } else {
        print "3. Infra Layer (Priority: 300) - workspace/infra/{name}"
    }

    let layers = open ../../workspace/layers/core.layer.k | get core_layer
    let workspace_layer = open ../../workspace/layers/workspace.layer.k | get workspace_layer

    print "\n📊 Layer Details:"
    print $"Core provides: (($layers.provides | str join ', '))"
    print $"Workspace provides: (($workspace_layer.provides | str join ', '))"
}

# Test layer resolution for a specific module
export def "main layer test" [
    module_name: string,       # Module to test (e.g., "kubernetes")
    --infra?: string,          # Infrastructure context
    --provider = "upcloud"     # Provider context
] {
    print $"🧪 Testing layer resolution for ($module_name)"

    test_layer_resolution $module_name $infra $provider
}

# === OVERRIDE COMMANDS ===

# Create override for existing configuration
export def "main override create" [
    module_type: string,       # Type: taskservs, providers, servers
    infra_name: string,        # Target infrastructure
    module_name: string,       # Module to override
    --from?: string,           # Source template to override from
    --interactive = false      # Interactive override creation
] {
    print $"🔧 Creating override for ($module_name) in ($infra_name)"

    let override_dir = $"workspace/infra/($infra_name)/overrides"
    mkdir $override_dir

    if ($from | is-not-empty) {
        copy_template_as_override $from $override_dir $module_name
    }

    if $interactive {
        ^$env.EDITOR $"($override_dir)/($module_name).k"
    }

    print $"✅ Override created for ($module_name)"
}

# === ENHANCED LOAD COMMANDS ===

# Enhanced load with layer support
export def "main load enhanced" [
    type: string,              # Module type: taskservs, providers, clusters
    workspace: string,         # Workspace path
    modules: list<string>,     # Module names to load
    --layer = "workspace",     # Layer to load from: core, workspace, templates
    --force = false,           # Force overwrite
    --with-overrides = false   # Apply infrastructure overrides
] {
    print $"🔄 Loading ($type) from ($layer) layer into: ($workspace)"

    match $type {
        "taskservs" => {
            load_taskservs_with_layer $workspace $modules $layer $force $with_overrides
        }
        "providers" => {
            load_providers_with_layer $workspace $modules $layer $force $with_overrides
        }
        "clusters" => {
            load_clusters_with_layer $workspace $modules $layer $force $with_overrides
        }
        _ => {
            error make {msg: $"Invalid type: ($type). Use: taskservs, providers, clusters"}
        }
    }

    print $"✅ Enhanced loading completed"
}

# === HELPER FUNCTIONS ===

def extract_taskserv_patterns [infra_name: string, target: string, overwrite: bool] {
    let source_dir = $"workspace/infra/($infra_name)/taskservs"
    let target_dir = $"provisioning/workspace/templates/taskservs"

    if ($source_dir | path exists) {
        print $"  📦 Extracting taskserv patterns..."

        for file in (ls $source_dir | get name) {
            let filename = ($file | path basename)
            let target_file = $"($target_dir)/($filename)"

            if ($overwrite or not ($target_file | path exists)) {
                print $"    ➜ Extracting ($filename)"
                cp $file $target_file
            } else {
                print $"    ⚠️ Skipping ($filename) (already exists)"
            }
        }
    }
}

def extract_provider_patterns [infra_name: string, target: string, overwrite: bool] {
    let source_dir = $"workspace/infra/($infra_name)/defs"
    let target_dir = $"provisioning/workspace/templates/providers"

    if ($source_dir | path exists) {
        print $"  📦 Extracting provider patterns..."

        for file in (ls $source_dir | where name =~ "_defaults\.k$" | get name) {
            let filename = ($file | path basename)
            let provider_name = ($filename | str replace "_defaults.k" "")
            let target_file = $"($target_dir)/($provider_name)/defaults.k"

            mkdir ($"($target_dir)/($provider_name)")

            if ($overwrite or not ($target_file | path exists)) {
                print $"    ➜ Extracting ($provider_name) defaults"
                cp $file $target_file
            } else {
                print $"    ⚠️ Skipping ($provider_name) defaults (already exists)"
            }
        }
    }
}

def get_template_info [manifest: record, template_name: string] -> record {
    # Search through all template categories
    let taskserv_templates = $manifest.templates.taskservs | items {|key, value|
        if $key == $template_name {
            $value | insert type "taskserv" | insert name $key
        } else if ($value | describe) == "record" {
            $value | items {|variant_key, variant_value|
                if $variant_key == $template_name {
                    $variant_value | insert type "taskserv" | insert name $key | insert variant $variant_key
                } else {
                    null
                }
            } | where {|x| $x != null} | first
        } else {
            null
        }
    } | where {|x| $x != null} | first

    $taskserv_templates
}

def test_layer_resolution [module_name: string, infra: string, provider: string] {
    print $"  Layer 1 (Core): Checking provisioning/extensions/taskservs/($module_name)"
    let core_exists = ("provisioning/extensions/taskservs" | path join $module_name | path exists)
    print $"    Core layer: ($core_exists)"

    print $"  Layer 2 (Workspace): Checking provisioning/workspace/templates/taskservs/($module_name)"
    let workspace_exists = ("provisioning/workspace/templates/taskservs" | path join $module_name | path exists)
    print $"    Workspace layer: ($workspace_exists)"

    if ($infra | is-not-empty) {
        print $"  Layer 3 (Infra): Checking workspace/infra/($infra)/taskservs/($module_name).k"
        let infra_exists = ("workspace/infra" | path join $infra "taskservs" $"($module_name).k" | path exists)
        print $"    Infra layer: ($infra_exists)"
    }
}

# === HELP FUNCTIONS ===

def print_enhanced_help [] {
    print "Enhanced Module Loader CLI - Discovery, Templates, and Layers"
    print ""
    print "Usage: module-loader-enhanced <command> [options]"
    print ""
    print "Commands:"
    print "  discover <type> [query] [--format <fmt>] - Discover available modules"
    print "  load <type> <workspace> <modules...>     - Load modules into workspace"
    print "  load enhanced <type> <workspace> <modules...> [--layer <layer>] - Enhanced load with layers"
    print "  list <type> <workspace>                  - List loaded modules"
    print "  unload <type> <workspace> <module>       - Unload module from workspace"
    print ""
    print "Template Commands:"
    print "  template list [--type <type>]            - List available templates"
    print "  template extract <infra> [--to <target>] - Extract patterns to templates"
    print "  template apply <template> <infra>        - Apply template to infrastructure"
    print ""
    print "Layer Commands:"
    print "  layer show [--infra <name>]              - Show layer resolution order"
    print "  layer test <module> [--infra <name>]     - Test layer resolution"
    print ""
    print "Override Commands:"
    print "  override create <type> <infra> <module>  - Create configuration override"
    print ""
    print "Types: taskservs, providers, clusters"
    print "Layers: core, workspace, infra"
    print ""
    print "Examples:"
    print "  module-loader-enhanced template extract wuji --to templates"
    print "  module-loader-enhanced template apply kubernetes-ha new-infra"
    print "  module-loader-enhanced load enhanced taskservs workspace/infra/new-infra [kubernetes] --layer workspace"
    print "  module-loader-enhanced layer test kubernetes --infra new-infra"
}

def print_template_help [] {
    print "Template Management Commands"
    print ""
    print "Usage: module-loader-enhanced template <command> [options]"
    print ""
    print "Commands:"
    print "  list [--type <type>] [--format <format>] - List available templates"
    print "  extract <infra> [--to <target>]          - Extract infrastructure patterns to templates"
    print "  apply <template> <infra> [--provider]    - Apply template to infrastructure"
    print ""
    print "Options:"
    print "  --type <type>        Template type: taskservs, providers, servers, clusters, all"
    print "  --format <format>    Output format: table, yaml, json"
    print "  --to <target>        Target location: templates, workspace"
    print "  --provider <name>    Target provider: upcloud, aws, local"
    print ""
    print "Examples:"
    print "  module-loader-enhanced template list --type taskservs"
    print "  module-loader-enhanced template extract wuji --type taskservs"
    print "  module-loader-enhanced template apply kubernetes-ha new-infra --provider upcloud"
}

def print_layer_help [] {
    print "Layer Management Commands"
    print ""
    print "Usage: module-loader-enhanced layer <command> [options]"
    print ""
    print "Commands:"
    print "  show [--infra <name>]           - Show layer resolution order"
    print "  test <module> [--infra <name>]  - Test layer resolution for module"
    print ""
    print "Layer Priority Order:"
    print "  1. Core (100)      - provisioning/extensions"
    print "  2. Workspace (200) - provisioning/workspace/templates"
    print "  3. Infra (300)     - workspace/infra/{name}"
    print ""
    print "Examples:"
    print "  module-loader-enhanced layer show --infra wuji"
    print "  module-loader-enhanced layer test kubernetes --infra wuji"
}

def print_override_help [] {
    print "Override Management Commands"
    print ""
    print "Usage: module-loader-enhanced override <command> [options]"
    print ""
    print "Commands:"
    print "  create <type> <infra> <module> [--from <template>] - Create configuration override"
    print ""
    print "Options:"
    print "  --from <template>    Source template to copy as base"
    print "  --interactive        Open editor for customization"
    print ""
    print "Examples:"
    print "  module-loader-enhanced override create taskservs wuji kubernetes --from templates/kubernetes/ha-cluster"
}

main