# Module: Extension Loader
# Purpose: Dynamically loads and initializes extensions, manages extension lifecycle.
# Dependencies: discovery, mod

# Extension Loader
# Discovers and loads extensions from multiple sources
# config/accessor star-import was dead — dropped (ADR-025 Phase 3 Layer 2).

# Extension discovery paths in priority order
export def get-extension-paths [] {
    [
        # Project-specific extensions (highest priority)
        ($env.PWD | path join ".provisioning" "extensions")
        # User extensions
        ($env.HOME | path join ".provisioning-extensions")
        # System-wide extensions
        "/opt/provisioning-extensions"
        # Environment variable override
        (get-extensions-path)
    ] | where ($it | is-not-empty) | where ($it | path exists)
}

# Load extension manifest
export def load-manifest [extension_path: string] {
    let manifest_file = ($extension_path | path join "manifest.yaml")
    if ($manifest_file | path exists) {
        open $manifest_file
    } else {
        {
            name: ($extension_path | path basename)
            version: "1.0.0"
            type: "unknown"
            requires: []
            permissions: []
            hooks: {}
        }
    }
}

# Check if extension is allowed
export def is-extension-allowed [manifest: record] {
    let mode = (get-extension-mode)
    let allowed = (get-allowed-extensions | split row "," | each { str trim })
    let blocked = (get-blocked-extensions | split row "," | each { str trim })

    match $mode {
        "disabled" => false,
        "restricted" => {
            if ($blocked | any {|x| $x == $manifest.name}) {
                false
            } else if ($allowed | is-empty) {
                true
            } else {
                ($allowed | any {|x| $x == $manifest.name})
            }
        },
        _ => {
            not ($blocked | any {|x| $x == $manifest.name})
        }
    }
}

# Discover providers in extension paths
export def discover-providers [] {
    get-extension-paths | each {|ext_path|
        let providers_path = ($ext_path | path join "providers")
        if ($providers_path | path exists) {
            glob ($providers_path | path join "*")
            | where ($it | path type) == "dir"
            | each {|provider_path|
                let manifest = (load-manifest $provider_path)
                if (is-extension-allowed $manifest) and $manifest.type == "provider" {
                    {
                        name: ($provider_path | path basename)
                        path: $provider_path
                        manifest: $manifest
                        source: $ext_path
                    }
                } else {
                    null
                }
            }
            | where ($it != null)
        } else {
            []
        }
    } | flatten
}

# Discover taskservs in extension paths
export def discover-taskservs [] {
    get-extension-paths | each {|ext_path|
        let taskservs_path = ($ext_path | path join "taskservs")
        if ($taskservs_path | path exists) {
            glob ($taskservs_path | path join "*")
            | where ($it | path type) == "dir"
            | each {|taskserv_path|
                let manifest = (load-manifest $taskserv_path)
                if (is-extension-allowed $manifest) and $manifest.type == "taskserv" {
                    {
                        name: ($taskserv_path | path basename)
                        path: $taskserv_path
                        manifest: $manifest
                        source: $ext_path
                    }
                } else {
                    null
                }
            }
            | where ($it != null)
        } else {
            []
        }
    } | flatten
}

# Check extension requirements
export def check-requirements [manifest: record] {
    if ($manifest.requires | is-empty) {
        true
    } else {
        $manifest.requires | all {|req|
            (which $req | length) > 0
        }
    }
}

# Load extension hooks
export def load-hooks [extension_path: string, manifest: record] {
    if ($manifest.hooks | is-not-empty) {
        $manifest.hooks | items {|key, value|
            let hook_file = ($extension_path | path join $value)
            if ($hook_file | path exists) {
                {key: $key, value: $hook_file}
            }
        } | reduce --fold {} {|it, acc| $acc | insert $it.key $it.value}
    } else {
        {}
    }
}
