#!/usr/bin/env nu
# Thin entry for taskserv commands.
# Bypasses full dispatcher — loads only taskservs/* + targeted lib_provisioning pieces.
# Order matters: lib_provisioning symbols must be in scope BEFORE use taskservs *
# because taskservs/create.nu relies on provisioning_init etc. being pre-loaded.

export-env {
    let lib_dirs_raw = ($env.NU_LIB_DIRS? | default "")
    let current_lib_dirs = if ($lib_dirs_raw | type) == "string" {
        if ($lib_dirs_raw | is-empty) { [] } else { ($lib_dirs_raw | split row ":") }
    } else {
        $lib_dirs_raw
    }
    let dynamic = ($env.PROVISIONING? | default "" | path join "core" "nulib")
    $env.NU_LIB_DIRS = ([
        "/opt/provisioning/core/nulib"
        "/usr/local/provisioning/core/nulib"
    ] | append $current_lib_dirs | append (if ($dynamic | is-not-empty) { [$dynamic] } else { [] }))

    # Session timestamp used by taskservs/handlers.nu for working directory paths
    if ($env.NOW? | is-empty) {
        $env.NOW = (date now | format date "%Y_%m_%d_%H_%M_%S")
    }

    # SSH options — disable strict host checking for provisioning (mirrors env.nu:117)
    if ($env.SSH_OPS? | is-empty) {
        $env.SSH_OPS = [
            "StrictHostKeyChecking=accept-new"
            $"UserKnownHostsFile=(if $nu.os-info.name == 'windows' { 'NUL' } else { '/dev/null' })"
        ]
    }

    # Taskservs extension path — used by get-taskservs-path / get-run-taskservs-path
    let prov = ($env.PROVISIONING? | default "")
    if ($env.PROVISIONING_TASKSERVS_PATH? | is-empty) and ($prov | is-not-empty) {
        $env.PROVISIONING_TASKSERVS_PATH = ($prov | path join "extensions" "taskservs")
    }

    # Strip leading "taskserv"/"task"/"t" token so get-provisioning-args returns the sub-command
    # e.g. "taskserv create --infra x" → "create --infra x"
    let args_raw = ($env.PROVISIONING_ARGS? | default "")
    $env.PROVISIONING_ARGS = ($args_raw | str replace --regex '^(taskserv|task|t)\s+' '')

    let _coerce = {|raw| $raw == "true" or $raw == "1" }
    let raw_no_titles = ($env.PROVISIONING_NO_TITLES? | default "")
    if ($raw_no_titles | describe) == "string" and ($raw_no_titles | is-not-empty) {
        $env.PROVISIONING_NO_TITLES = (do $_coerce $raw_no_titles)
    }
    let raw_no_terminal = ($env.PROVISIONING_NO_TERMINAL? | default "")
    if ($raw_no_terminal | describe) == "string" and ($raw_no_terminal | is-not-empty) {
        $env.PROVISIONING_NO_TERMINAL = (do $_coerce $raw_no_terminal)
    }
    let raw_titles_shown = ($env.PROVISIONING_TITLES_SHOWN? | default "")
    if ($raw_titles_shown | describe) == "string" and ($raw_titles_shown | is-not-empty) {
        $env.PROVISIONING_TITLES_SHOWN = (do $_coerce $raw_titles_shown)
    }
    let raw_debug = ($env.PROVISIONING_DEBUG? | default "")
    if ($raw_debug | describe) == "string" and ($raw_debug | is-not-empty) {
        $env.PROVISIONING_DEBUG = (do $_coerce $raw_debug)
    }
}

# ── lib_provisioning pieces (MUST precede use taskservs * so create.nu resolves at parse time) ──
use lib_provisioning/utils/init.nu *
use lib_provisioning/utils/interface.nu [
    _print
    _ansi
    set-provisioning-out
    set-provisioning-no-terminal
    get-provisioning-no-terminal
    get-provisioning-out
    end_run
    desktop_run_notify
    show_clip_to
    log_debug
]
use lib_provisioning/utils/logging.nu [
    set-debug-enabled
    set-metadata-enabled
    is-debug-enabled
    is-debug-check-enabled
    is-metadata-enabled
]
use lib_provisioning/utils/settings.nu [
    find_get_settings
    settings_with_env
    set-wk-cnprov
    get_file_format
]
use lib_provisioning/sops/lib.nu [get_def_sops, get_def_age]
use lib_provisioning/utils/templates.nu [on_template_path, run_from_template]
use lib_provisioning/plugins_defs.nu [port_scan]
use ../../extensions/providers/prov_lib/middleware.nu *

# ── taskservs module (resolves provisioning_init etc. from above) ──
use taskservs *

def main [
    ...args: string            # args[0] = "taskserv"/"t", args[1] = subcommand
    --infra (-i): string  = ""
    --settings (-s): string = ""
    --iptype: string = "public"
    --reset          # Force reinstall: kubeadm reset before re-install (sets CMD_TSK=reinstall)
    --cmd: string = ""  # Override cmd_task: scripts, config, update, restart, reinstall, remove
    --check (-c)
    --upload (-u)
    --force          # Delete taskservs no longer in servers.ncl (reads from state file)
    --yes (-y)       # Confirm delete without prompt
    --debug (-x)
    --xc
    --xr
    --xm
    --metadata
    --notitles
    --out: string = ""
]: nothing -> nothing {
    if $debug { $env.PROVISIONING_DEBUG = true }

    let first = ($args | get 0? | default "")
    let rest  = if $first in ["taskserv", "task", "t"] { $args | skip 1 } else { $args }

    let sub        = ($rest | get 0? | default "create")
    let task_name  = ($rest | get 1? | default "")
    let server_arg = ($rest | get 2? | default "")

    match $sub {
        "create" | "c" => {
            if ($task_name | is-not-empty) and ($server_arg | is-not-empty) {
                if $reset {
                    main create $task_name $server_arg --reset --infra $infra --settings $settings --iptype $iptype --check=$check --upload=$upload --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd $cmd
                } else {
                    main create $task_name $server_arg --infra $infra --settings $settings --iptype $iptype --check=$check --upload=$upload --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd $cmd
                }
            } else if ($task_name | is-not-empty) {
                if $reset {
                    main create $task_name --reset --infra $infra --settings $settings --iptype $iptype --check=$check --upload=$upload --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd $cmd
                } else {
                    main create $task_name --infra $infra --settings $settings --iptype $iptype --check=$check --upload=$upload --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd $cmd
                }
            } else {
                if $reset {
                    main create --reset --infra $infra --settings $settings --iptype $iptype --check=$check --upload=$upload --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd $cmd
                } else {
                    main create --infra $infra --settings $settings --iptype $iptype --check=$check --upload=$upload --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd $cmd
                }
            }
        }
        "update" | "u" => {
            # Update: bump version or reconfigure — no state-gate, always runs
            if ($task_name | is-not-empty) and ($server_arg | is-not-empty) {
                main create $task_name $server_arg --infra $infra --settings $settings --iptype $iptype --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd "update"
            } else if ($task_name | is-not-empty) {
                main create $task_name --infra $infra --settings $settings --iptype $iptype --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd "update"
            } else {
                main create --infra $infra --settings $settings --iptype $iptype --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd "update"
            }
        }
        "reset" | "r" => {
            # Reset: stop + clean data + reinstall from scratch
            if ($task_name | is-not-empty) and ($server_arg | is-not-empty) {
                main create $task_name $server_arg --reset --infra $infra --settings $settings --iptype $iptype --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out
            } else if ($task_name | is-not-empty) {
                main create $task_name --reset --infra $infra --settings $settings --iptype $iptype --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out
            } else {
                main create --reset --infra $infra --settings $settings --iptype $iptype --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out
            }
        }
        "run" => {
            # Run: arbitrary cmd_task op (scripts, config, restart, remove, ...)
            let op = if ($cmd | is-not-empty) { $cmd } else { $task_name }
            let ts = if ($cmd | is-not-empty) { $task_name } else { $server_arg }
            let sv = if ($cmd | is-not-empty) { $server_arg } else { "" }
            if ($ts | is-not-empty) and ($sv | is-not-empty) {
                main create $ts $sv --infra $infra --settings $settings --iptype $iptype --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd $op
            } else if ($ts | is-not-empty) {
                main create $ts --infra $infra --settings $settings --iptype $iptype --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd $op
            } else {
                main create --infra $infra --settings $settings --iptype $iptype --debug=$debug --xc=$xc --xr=$xr --notitles=$notitles --out=$out --cmd $op
            }
        }
        "delete" | "d" => {
            if ($task_name | is-not-empty) and ($server_arg | is-not-empty) {
                if $force {
                    main delete $task_name $server_arg --force --infra $infra --settings $settings --yes=$yes --debug=$debug --notitles=$notitles
                } else {
                    main delete $task_name $server_arg --infra $infra --settings $settings --yes=$yes --debug=$debug --notitles=$notitles
                }
            } else if ($task_name | is-not-empty) {
                if $force {
                    main delete $task_name --force --infra $infra --settings $settings --yes=$yes --debug=$debug --notitles=$notitles
                } else {
                    main delete $task_name --infra $infra --settings $settings --yes=$yes --debug=$debug --notitles=$notitles
                }
            } else {
                main delete --infra $infra --settings $settings --yes=$yes --debug=$debug --notitles=$notitles
            }
        }
        "generate" | "g" => {
            if ($task_name | is-not-empty) {
                main generate $task_name --infra $infra --settings $settings --debug=$debug --notitles=$notitles
            } else {
                main generate --infra $infra --settings $settings --debug=$debug --notitles=$notitles
            }
        }
        "status" | "st" => {
            if ($task_name | is-not-empty) {
                main status --server $task_name --infra $infra --settings $settings
            } else {
                main status --infra $infra --settings $settings
            }
        }
        "list" | "ls" => {
            use ./components/mod.nu [component-list]
            let workspace = ($env.PROVISIONING_KLOUD? | default "")
            component-list "taskserv" $workspace
        }
        "show" | "s" => {
            use ./components/mod.nu [component-show]
            let workspace = ($env.PROVISIONING_KLOUD? | default "")
            component-show $task_name $workspace false
        }
        _ => {
            print "Usage: provisioning taskserv <create|update|reset|run|delete|generate|status|list|show> [taskserv] [server] [flags]"
            print "  create   (c)  — initial install (state-gate: skips completed nodes)"
            print "  update   (u)  — update version/config (always runs, no state-gate)"
            print "  reset    (r)  — stop + clean data + reinstall from scratch"
            print "  run           — run arbitrary op: scripts, config, restart, remove, ..."
            print "  delete   (d)  — remove taskservs"
            print "  generate (g)  — generate taskserv configs"
            print "  status   (st) — show DAG formula progress per server"
            print "  list     (ls) — list taskserv-mode components"
            print "  show     (s)  — show component details [--workspace <ws>] [--ext]"
        }
    }
}
