# Enhanced middleware with extension support
# This file can replace middleware.nu to support dynamic provider loading

use ../../core/nulib/lib_provisioning/extensions/registry.nu *

# Import core providers (keep existing functionality)
use ../aws/nulib/aws/env.nu
use ../aws/nulib/aws/servers.nu *
use ../aws/nulib/aws/cache.nu *
use ../aws/nulib/aws/prices.nu *
use ../local/nulib/local/env.nu
use ../local/nulib/local/servers.nu *
use ../upcloud/nulib/upcloud/env.nu
use ../upcloud/nulib/upcloud/servers.nu *
use ../upcloud/nulib/upcloud/cache.nu *
use ../upcloud/nulib/upcloud/prices.nu *

# Initialize extension registry on first load
init-registry

def provider_undefined [
    server: record
] {
    let str_providers_list = (providers_list "selection" | each { |it| $it.name} | str join " ")
    print ($"(_ansi blue_bold)($server.hostname)(_ansi reset) with provider " +
       $"(_ansi green_bold)($server.provider)(_ansi reset) ($server.zone) ")
    let text = ( $"expected to be one of available providers [(_ansi green_italic)($str_providers_list)(_ansi reset)], " +
        $"got (_ansi green_bold)($server.provider)(_ansi reset)")
    print $"Error 🛑 provider ($text)"
}

# Load extension provider dynamically
def load_extension_provider [provider_name: string] {
    let provider_info = (get-provider $provider_name)
    if ($provider_info | is-not-empty) and $provider_info.available {
        try {
            use ($provider_info.entry_point) *
            return true
        } catch {
            return false
        }
    }
    false
}

# Enhanced query with extension support
export def mw_query_servers [
    settings: record
    find?: string
    cols?: string
    --prov: string
    --serverpos: int
] {
    let str_find = if $find != null { $find } else { "" }
    let str_cols = if $cols != null { $cols } else { "" }
    $settings.data.servers | enumerate | each { |it|
        if $prov == null or $it.item.provider == $prov {
            if $serverpos == null or $serverpos == $it.index  {
                let res = match $it.item.provider {
                    "aws" => {
                        (aws_query_servers $str_find $str_cols)
                    },
                    "local" => {
                        (local_query_servers $str_find $str_cols)
                    },
                    "upcloud" => {
                        (upcloud_query_servers $str_find $str_cols)
                    },
                    _ => {
                        # Try loading extension provider
                        if (load_extension_provider $it.item.provider) {
                            # Dynamically call provider function
                            try {
                                # Convention: {provider}_query_servers
                                let func_name = $"($it.item.provider)_query_servers"
                                (nu -c $"use ($env.PROVISIONING_PROV_LIB | path join 'middleware_enhanced.nu') *; ($func_name) ($str_find) ($str_cols)")
                            } catch {
                                provider_undefined $it.item
                                []
                            }
                        } else {
                            provider_undefined $it.item
                            []
                        }
                    }
                }
                $res
            }
        }
    } | flatten
}

# Enhanced server creation with extension support
export def mw_create_servers [
    settings: record
    servers: table
    check: bool
    wait: bool
] {
    $servers | each { |server|
        # Check if provider is allowed by profile
        use ../../core/nulib/lib_provisioning/extensions/profiles.nu is-provider-allowed
        if not (is-provider-allowed $server.provider) {
            print $"🛑 Provider ($server.provider) blocked by profile"
            continue
        }

        let res = match $server.provider {
            "aws" => {
                (aws_create_servers $settings [$server] $check $wait)
            },
            "local" => {
                (local_create_servers $settings [$server] $check $wait)
            },
            "upcloud" => {
                (upcloud_create_servers $settings [$server] $check $wait)
            },
            _ => {
                # Try loading extension provider
                if (load_extension_provider $server.provider) {
                    try {
                        let func_name = $"($server.provider)_create_servers"
                        (nu -c $"use ($env.PROVISIONING_PROV_LIB | path join 'middleware_enhanced.nu') *; ($func_name) ($settings | to json) ([$server] | to json) ($check) ($wait)")
                    } catch {
                        provider_undefined $server
                        []
                    }
                } else {
                    provider_undefined $server
                    []
                }
            }
        }
        $res
    }
}

# Enhanced server deletion with extension support
export def mw_delete_servers [
    settings: record
    servers: table
    check: bool
] {
    $servers | each { |server|
        # Check if provider is allowed by profile
        use ../../core/nulib/lib_provisioning/extensions/profiles.nu is-provider-allowed
        if not (is-provider-allowed $server.provider) {
            print $"🛑 Provider ($server.provider) blocked by profile"
            continue
        }

        let res = match $server.provider {
            "aws" => {
                (aws_delete_servers $settings [$server] $check)
            },
            "local" => {
                (local_delete_servers $settings [$server] $check)
            },
            "upcloud" => {
                (upcloud_delete_servers $settings [$server] $check)
            },
            _ => {
                # Try loading extension provider
                if (load_extension_provider $server.provider) {
                    try {
                        let func_name = $"($server.provider)_delete_servers"
                        (nu -c $"use ($env.PROVISIONING_PROV_LIB | path join 'middleware_enhanced.nu') *; ($func_name) ($settings | to json) ([$server] | to json) ($check)")
                    } catch {
                        provider_undefined $server
                        []
                    }
                } else {
                    provider_undefined $server
                    []
                }
            }
        }
        $res
    }
}

# Get IP with extension support
export def mw_get_ip [
    settings: record
    server: record
    ip_type: string
    public_fallback: bool
] -> string {
    match $server.provider {
        "aws" => {
            (aws_get_ip $settings $server $ip_type $public_fallback)
        },
        "local" => {
            (local_get_ip $settings $server $ip_type $public_fallback)
        },
        "upcloud" => {
            (upcloud_get_ip $settings $server $ip_type $public_fallback)
        },
        _ => {
            # Try loading extension provider
            if (load_extension_provider $server.provider) {
                try {
                    let func_name = $"($server.provider)_get_ip"
                    (nu -c $"use ($env.PROVISIONING_PROV_LIB | path join 'middleware_enhanced.nu') *; ($func_name) ($settings | to json) ($server | to json) ($ip_type) ($public_fallback)")
                } catch {
                    ""
                }
            } else {
                ""
            }
        }
    }
}

# List all providers (core + extensions)
export def mw_list_all_providers [] {
    let core_providers = [
        { name: "aws", type: "core", path: "../aws" }
        { name: "local", type: "core", path: "../local" }
        { name: "upcloud", type: "core", path: "../upcloud" }
    ]

    let extension_providers = (list-providers | each {|ext|
        {
            name: $ext.name
            type: "extension"
            path: $ext.source
            version: $ext.version
        }
    })

    $core_providers | append $extension_providers
}