# Orchestrator Plugin Wrapper with HTTP Fallback
# Provides graceful degradation to HTTP/file-based access when nu_plugin_orchestrator is unavailable

use ../config/accessor.nu *

# Check if orchestrator plugin is available (registered with Nushell)
def is-plugin-available [] {
    let installed = (version | get installed_plugins)
    $installed | str contains "orchestrator"
}

# Check if orchestrator plugin is enabled in config
def is-plugin-enabled [] {
    config-get "plugins.orchestrator_enabled" true
}

# Get orchestrator base URL
def get-orchestrator-url [] {
    if ($env.PROVISIONING_ORCHESTRATOR_URL? | is-not-empty) {
        $env.PROVISIONING_ORCHESTRATOR_URL
    } else {
        config-get "platform.orchestrator.url" "http://localhost:9011"
    }
}

# Get orchestrator data directory
def get-orchestrator-data-dir [] {
    let base = config-get "paths.base" $env.PWD
    $"($base)/provisioning/platform/orchestrator/data"
}

# Helper to safely execute a closure and return null on error
def try-plugin [callback: closure] {
    do -i $callback
}

# Get orchestrator status (fastest: direct file access)
export def plugin-orch-status [] {
    let enabled = is-plugin-enabled
    let available = is-plugin-available

    if $enabled and $available {
        let plugin_result = (try-plugin {
            orch status
        })

        if $plugin_result != null {
            return $plugin_result
        }

        print "⚠️ Plugin orchestrator status failed, falling back to file/HTTP"
    }

    # File-based fallback (fastest)
    let data_dir = get-orchestrator-data-dir

    if ($data_dir | path exists) {
        let status_file = $"($data_dir)/orchestrator.status"

        let file_result = (do -i {
            if ($status_file | path exists) {
                open $status_file
            } else {
                null
            }
        })

        if $file_result != null {
            return $file_result
        }

        print "⚠️ File access failed, trying HTTP"
    }

    # HTTP fallback
    print "⚠️ nu_plugin_orchestrator not available - using HTTP fallback for orchestration"

    let url = $"(get-orchestrator-url)/health"

    let http_result = (do -i {
        http get $url
    })

    if $http_result != null {
        return $http_result
    }

    {
        status: "unavailable"
        message: "Orchestrator unreachable"
        plugin_available: $available
        plugin_enabled: $enabled
    }
}

# List orchestrator tasks
export def plugin-orch-tasks [
    --status: string = ""  # pending, running, completed, failed
    --limit: int = 100     # Maximum number of tasks
] {
    let enabled = is-plugin-enabled
    let available = is-plugin-available

    if $enabled and $available {
        let plugin_result = (try-plugin {
            let args = if ($status | is-empty) {
                [tasks --limit $limit]
            } else {
                [tasks --status $status --limit $limit]
            }

            orch ...$args
        })

        if $plugin_result != null {
            return $plugin_result
        }

        print "⚠️ Plugin orchestrator tasks failed, falling back to file/HTTP"
    }

    # File-based fallback (fastest)
    let data_dir = get-orchestrator-data-dir

    if ($data_dir | path exists) {
        let tasks_dir = $"($data_dir)/tasks"

        let file_result = (do -i {
            if ($tasks_dir | path exists) {
                ls $tasks_dir
                    | where type == file
                    | get name
                    | each { |file|
                        do -i {
                            open $file | from json
                        }
                    }
                    | where $it != null
                    | if ($status | is-empty) {
                        $in
                    } else {
                        where status == $status
                    }
                    | first $limit
            } else {
                null
            }
        })

        if $file_result != null {
            return $file_result
        }

        print "⚠️ File access failed, trying HTTP"
    }

    # HTTP fallback
    print "⚠️ nu_plugin_orchestrator not available - using HTTP fallback for orchestration"

    let orch_url = get-orchestrator-url
    let url = if ($status | is-empty) {
        $"($orch_url)/tasks?limit=($limit)"
    } else {
        $"($orch_url)/tasks?status=($status)&limit=($limit)"
    }

    let http_result = (do -i {
        let response = (http get $url)
        $response.tasks? | default []
    })

    if $http_result != null {
        return $http_result
    }

    []
}

# Get specific task details
export def plugin-orch-task [
    task_id: string
] {
    let enabled = is-plugin-enabled
    let available = is-plugin-available

    if $enabled and $available {
        let plugin_result = (try-plugin {
            orch task $task_id
        })

        if $plugin_result != null {
            return $plugin_result
        }

        print "⚠️ Plugin orchestrator task failed, falling back to file/HTTP"
    }

    # File-based fallback (fastest)
    let data_dir = get-orchestrator-data-dir

    if ($data_dir | path exists) {
        let task_file = $"($data_dir)/tasks/($task_id).json"

        let file_result = (do -i {
            if ($task_file | path exists) {
                open $task_file
            } else {
                null
            }
        })

        if $file_result != null {
            return $file_result
        }

        print "⚠️ File access failed, trying HTTP"
    }

    # HTTP fallback
    print "⚠️ nu_plugin_orchestrator not available - using HTTP fallback for orchestration"

    let orch_url = get-orchestrator-url
    let url = $"($orch_url)/tasks/($task_id)"

    let http_result = (do -i {
        http get $url
    })

    if $http_result != null {
        return $http_result
    }

    error make {
        msg: "Task not found"
        label: {
            text: $"Task ($task_id) does not exist"
            span: (metadata $task_id).span
        }
    }
}

# Validate orchestrator configuration
export def plugin-orch-validate [] {
    let enabled = is-plugin-enabled
    let available = is-plugin-available

    # Note: Plugin validation requires workflow file, so we skip plugin call
    # and go directly to HTTP health check
    let available_check = $enabled and $available

    if $available_check {
        print "⚠️ Plugin orchestrator validation requires workflow file, using HTTP health check"
    }

    # HTTP fallback
    print "⚠️ nu_plugin_orchestrator not available - using HTTP fallback for orchestration"

    let orch_url = get-orchestrator-url
    let url = $"($orch_url)/validate"

    let http_result = (do -i {
        http get $url
    })

    if $http_result != null {
        return $http_result
    }

    {
        valid: false
        message: "Orchestrator unreachable or validation failed"
    }
}

# Get orchestrator statistics
export def plugin-orch-stats [] {
    let enabled = is-plugin-enabled
    let available = is-plugin-available

    if $enabled and $available {
        let plugin_result = (try-plugin {
            orch stats
        })

        if $plugin_result != null {
            return $plugin_result
        }

        print "⚠️ Plugin orchestrator stats failed, falling back to file/HTTP"
    }

    # File-based fallback (compute from files)
    let data_dir = get-orchestrator-data-dir

    if ($data_dir | path exists) {
        let tasks_dir = $"($data_dir)/tasks"

        let file_result = (do -i {
            if ($tasks_dir | path exists) {
                let tasks = (ls $tasks_dir
                    | where type == file
                    | get name
                    | each { |file|
                        do -i {
                            open $file | from json | get status
                        }
                    }
                    | where $it != null
                )

                let total = ($tasks | length)
                let pending = ($tasks | where $it == "pending" | length)
                let running = ($tasks | where $it == "running" | length)
                let completed = ($tasks | where $it == "completed" | length)
                let failed = ($tasks | where $it == "failed" | length)

                {
                    total: $total
                    pending: $pending
                    running: $running
                    completed: $completed
                    failed: $failed
                }
            } else {
                null
            }
        })

        if $file_result != null {
            return $file_result
        }

        print "⚠️ File access failed, trying HTTP"
    }

    # HTTP fallback
    print "⚠️ nu_plugin_orchestrator not available - using HTTP fallback for orchestration"

    let orch_url = get-orchestrator-url
    let url = $"($orch_url)/stats"

    let http_result = (do -i {
        http get $url
    })

    if $http_result != null {
        return $http_result
    }

    {
        total: 0
        pending: 0
        running: 0
        completed: 0
        failed: 0
        message: "Orchestrator unreachable"
    }
}

# Get orchestrator plugin information
export def plugin-orch-info [] {
    let plugin_available = is-plugin-available
    let plugin_enabled = is-plugin-enabled
    let orchestrator_url = get-orchestrator-url
    let data_dir = get-orchestrator-data-dir

    {
        plugin_available: $plugin_available
        plugin_enabled: $plugin_enabled
        orchestrator_url: $orchestrator_url
        data_dir: $data_dir
        mode: (if ($plugin_enabled and $plugin_available) { "plugin" } else { "file/http" })
    }
}
