# Layer Resolution Utilities
# Supporting functions for layer management and resolution testing

# Test layer resolution for a specific module
export def test_layer_resolution [
    module_name: string,
    infra: string,
    provider: string
] {
    print $"🧪 Testing layer resolution for ($module_name)"
    print $"   Context: infra=($infra), provider=($provider)"

    # Test each layer in resolution order
    test_layer_core $module_name
    test_layer_workspace $module_name
    test_layer_infra $module_name $infra

    print $"📊 Resolution Summary:"
    summarize_resolution $module_name $infra
}

# Test core layer
def test_layer_core [module_name: string] {
    print "  🔍 Layer 1 (Core): Priority 100"

    # Use discovery system to find taskserv in grouped structure
    let discovery_result = (do {
        use ../../core/nulib/taskservs/discover.nu *
        let taskserv_info = get-taskserv-info $module_name
        ($taskserv_info.name == $module_name)
    } | complete)
    let taskserv_exists = if $discovery_result.exit_code == 0 { $discovery_result.stdout } else { false }

    let provider_path = $"provisioning/extensions/providers/($module_name)"
    let provider_exists = ($provider_path | path exists)

    if $taskserv_exists {
        print $"    ✅ Taskserv found in grouped structure"
    } else {
        print $"    ❌ Taskserv not found in extensions"
    }

    if $provider_exists {
        print $"    ✅ Provider found: ($provider_path)"
    } else {
        print $"    ❌ Provider not found: ($provider_path)"
    }
}

# Test workspace layer
def test_layer_workspace [module_name: string] {
    print "  🔍 Layer 2 (Workspace): Priority 200"

    # Find workspace root (look for workspace with infra/ subdirectory)
    let workspace_root = find_workspace_root

    if ($workspace_root | is-empty) {
        print $"    ⚠️ No workspace found"
        return
    }

    # Check workspace-level loaded modules (new 3-layer architecture)
    let loaded_taskserv = ($workspace_root | path join ".taskservs" $module_name)
    let loaded_provider = ($workspace_root | path join ".providers" $module_name)
    let loaded_cluster = ($workspace_root | path join ".clusters" $module_name)

    let taskserv_loaded = ($loaded_taskserv | path exists)
    let provider_loaded = ($loaded_provider | path exists)
    let cluster_loaded = ($loaded_cluster | path exists)

    if $taskserv_loaded {
        print $"    ✅ Taskserv loaded at workspace level: .taskservs/($module_name)"
    } else {
        print $"    ❌ Taskserv not loaded at workspace level"
    }

    if $provider_loaded {
        print $"    ✅ Provider loaded at workspace level: .providers/($module_name)"
    } else {
        print $"    ❌ Provider not loaded at workspace level"
    }

    if $cluster_loaded {
        print $"    ✅ Cluster loaded at workspace level: .clusters/($module_name)"
    } else {
        print $"    ❌ Cluster not loaded at workspace level"
    }
}

# Find workspace root (directory with infra/ subdirectory)
def find_workspace_root []: nothing -> string {
    let pwd = $env.PWD

    # Check current directory
    if (($pwd | path join "infra") | path exists) and (($pwd | path join ".taskservs") | path exists) {
        return $pwd
    }

    # Check if we're inside infra/ directory, go up
    if ($pwd | str contains "/infra/") {
        let parts = ($pwd | path split)
        let infra_idx = ($parts | enumerate | where item == "infra" | get index | first)
        if ($infra_idx | is-not-empty) {
            let workspace_parts = ($parts | take $infra_idx)
            let workspace_path = ($workspace_parts | path join)
            if ($workspace_path | path exists) {
                return $workspace_path
            }
        }
    }

    ""
}

# Test infrastructure layer
def test_layer_infra [module_name: string, infra: string] {
    print "  🔍 Layer 3 (Infrastructure): Priority 300"

    if ($infra | is-empty) {
        print $"    ⚠️ No infrastructure context provided"
        return
    }

    # Find workspace root and build infra path
    let workspace_root = find_workspace_root
    if ($workspace_root | is-empty) {
        print $"    ⚠️ No workspace found"
        return
    }

    let infra_path = ($workspace_root | path join "infra" $infra)

    # Check infrastructure-level loaded modules (new 3-layer architecture)
    let infra_taskserv = ($infra_path | path join ".taskservs" $module_name)
    let infra_provider = ($infra_path | path join ".providers" $module_name)
    let infra_cluster = ($infra_path | path join ".clusters" $module_name)

    let taskserv_exists = ($infra_taskserv | path exists)
    let provider_exists = ($infra_provider | path exists)
    let cluster_exists = ($infra_cluster | path exists)

    if $taskserv_exists {
        print $"    ✅ Infrastructure taskserv override: infra/($infra)/.taskservs/($module_name)"
    } else {
        print $"    ❌ Infrastructure taskserv not overridden"
    }

    if $provider_exists {
        print $"    ✅ Infrastructure provider override: infra/($infra)/.providers/($module_name)"
    } else {
        print $"    ❌ Infrastructure provider not overridden"
    }

    if $cluster_exists {
        print $"    ✅ Infrastructure cluster override: infra/($infra)/.clusters/($module_name)"
    } else {
        print $"    ❌ Infrastructure cluster not overridden"
    }
}

# Summarize resolution results
def summarize_resolution [module_name: string, infra: string] {
    mut resolution_chain = []

    let workspace_root = find_workspace_root

    # Check infra layer first (highest priority - Layer 3)
    if not ($infra | is-empty) and not ($workspace_root | is-empty) {
        let infra_path = ($workspace_root | path join "infra" $infra)
        let infra_taskserv = ($infra_path | path join ".taskservs" $module_name)
        let infra_provider = ($infra_path | path join ".providers" $module_name)
        let infra_cluster = ($infra_path | path join ".clusters" $module_name)

        if ($infra_taskserv | path exists) or ($infra_provider | path exists) or ($infra_cluster | path exists) {
            $resolution_chain = ($resolution_chain | append "infra")
        }
    }

    # Check workspace layer (Layer 2)
    if not ($workspace_root | is-empty) {
        let workspace_taskserv = ($workspace_root | path join ".taskservs" $module_name)
        let workspace_provider = ($workspace_root | path join ".providers" $module_name)
        let workspace_cluster = ($workspace_root | path join ".clusters" $module_name)

        if ($workspace_taskserv | path exists) or ($workspace_provider | path exists) or ($workspace_cluster | path exists) {
            $resolution_chain = ($resolution_chain | append "workspace")
        }
    }

    # Check core layer using discovery system (Layer 1)
    let core_discovery_result = (do {
        use ../../core/nulib/taskservs/discover.nu *
        let taskserv_info = get-taskserv-info $module_name
        ($taskserv_info.name == $module_name)
    } | complete)
    let core_exists = if $core_discovery_result.exit_code == 0 { $core_discovery_result.stdout } else { false }

    if $core_exists {
        $resolution_chain = ($resolution_chain | append "system")
    }

    if ($resolution_chain | length) > 0 {
        let final_resolution = ($resolution_chain | first)
        print $"  🎯 Final Resolution: ($final_resolution)"
        print $"  📋 Full Chain: (($resolution_chain | str join ' → '))"
    } else {
        print $"  ❌ No resolution found for ($module_name)"
    }

    $resolution_chain
}

# Get available modules in each layer
export def get_layer_modules [layer: string] {
    match $layer {
        "system" | "core" => {
            # Use the discovery system to get all modules from system extensions
            let discover_result = (do {
                use ../../core/nulib/taskservs/discover.nu *
                discover-taskservs | get name
            } | complete)
            if $discover_result.exit_code == 0 { $discover_result.stdout } else { [] }
        }
        "workspace" => {
            # Get loaded modules from workspace layer
            let workspace_root = find_workspace_root
            if ($workspace_root | is-empty) {
                return []
            }

            mut modules = []

            # Check workspace-level loaded modules
            let taskservs_dir = ($workspace_root | path join ".taskservs")
            let providers_dir = ($workspace_root | path join ".providers")
            let clusters_dir = ($workspace_root | path join ".clusters")

            if ($taskservs_dir | path exists) {
                let taskservs = (ls $taskservs_dir | where type == dir | get name | each {|path| $path | path basename})
                $modules = ($modules | append $taskservs)
            }

            if ($providers_dir | path exists) {
                let providers = (ls $providers_dir | where type == dir | get name | each {|path| $path | path basename})
                $modules = ($modules | append $providers)
            }

            if ($clusters_dir | path exists) {
                let clusters = (ls $clusters_dir | where type == dir | get name | each {|path| $path | path basename})
                $modules = ($modules | append $clusters)
            }

            $modules | uniq
        }
        "infra" => {
            # Get loaded modules from infrastructure layer
            let workspace_root = find_workspace_root
            if ($workspace_root | is-empty) {
                return []
            }

            # Get all infrastructure directories
            let infra_root = ($workspace_root | path join "infra")
            if not ($infra_root | path exists) {
                return []
            }

            let infras = (ls $infra_root | where type == dir | get name)

            mut all_modules = []
            for infra_path in $infras {
                let taskservs_dir = ($infra_path | path join ".taskservs")
                let providers_dir = ($infra_path | path join ".providers")
                let clusters_dir = ($infra_path | path join ".clusters")

                if ($taskservs_dir | path exists) {
                    let taskservs = (ls $taskservs_dir | where type == dir | get name | each {|path| $path | path basename})
                    $all_modules = ($all_modules | append $taskservs)
                }

                if ($providers_dir | path exists) {
                    let providers = (ls $providers_dir | where type == dir | get name | each {|path| $path | path basename})
                    $all_modules = ($all_modules | append $providers)
                }

                if ($clusters_dir | path exists) {
                    let clusters = (ls $clusters_dir | where type == dir | get name | each {|path| $path | path basename})
                    $all_modules = ($all_modules | append $clusters)
                }
            }

            $all_modules | uniq
        }
        _ => []
    }
}

# Validate layer configuration
export def validate_layer_config [] {
    print "🔍 Validating layer configuration"

    # Check layer definition files
    let core_layer = "provisioning/workspace/layers/core.layer.k"
    let workspace_layer = "provisioning/workspace/layers/workspace.layer.k"
    let infra_layer = "provisioning/workspace/layers/infra.layer.k"

    print $"  Layer definitions:"
    print $"    Core: ({($core_layer | path exists)})"
    print $"    Workspace: ({($workspace_layer | path exists)})"
    print $"    Infrastructure: ({($infra_layer | path exists)})"

    # Check registry files
    let manifest = "provisioning/workspace/registry/manifest.yaml"
    let imports = "provisioning/workspace/registry/imports.k"

    print $"  Registry:"
    print $"    Manifest: ({($manifest | path exists)})"
    print $"    Imports: ({($imports | path exists)})"

    # Check composition utilities
    let compose = "provisioning/workspace/templates/lib/compose.k"
    let override = "provisioning/workspace/templates/lib/override.k"

    print $"  Composition utilities:"
    print $"    Compose: ({($compose | path exists)})"
    print $"    Override: ({($override | path exists)})"

    print "✅ Layer validation completed"
}

# Show layer statistics
export def show_layer_stats [] {
    print "📊 Layer Statistics"

    let core_modules = get_layer_modules "core"
    let workspace_modules = get_layer_modules "workspace"

    print $"  Core layer: (($core_modules | length)) modules"
    if ($core_modules | length) > 0 {
        print $"    Modules: (($core_modules | str join ', '))"
    }

    print $"  Workspace layer: (($workspace_modules | length)) templates"
    if ($workspace_modules | length) > 0 {
        print $"    Templates: (($workspace_modules | str join ', '))"
    }

    # Check for workspace infrastructures
    if ("workspace/infra" | path exists) {
        let infras = ls "workspace/infra" | where type == dir | get name | each {|path| $path | path basename}
        print $"  Infrastructure layer: (($infras | length)) infrastructures"
        if ($infras | length) > 0 {
            print $"    Infrastructures: (($infras | str join ', '))"
        }
    } else {
        print $"  Infrastructure layer: 0 infrastructures"
    }
}
