use ../../lib_provisioning/config/accessor.nu *
use ../../lib_provisioning/utils/interface.nu [_print]
use ../../workspace/state.nu *
use ../../workspace/sync.nu *

export def handle_state_command [cmd: string, ops: string, flags: record] {
    let workspace_path = if ($env.PROVISIONING_WORKSPACE_PATH? | is-not-empty) {
        $env.PROVISIONING_WORKSPACE_PATH
    } else {
        $env.PWD
    }

    let infra = ($flags | get -o infra | default "")
    let server = ($flags | get -o server | default "")
    let taskserv = ($flags | get -o taskserv | default "")
    let kubeconfig = ($flags | get -o kubeconfig | default "")

    # When help_category == command name ("state"), the subcommand lands in $ops, not $cmd.
    let subcmd = if ($ops | is-not-empty) { ($ops | split row " " | first) } else { $cmd }

    match $subcmd {
        "show" | "s" => {
            state-show $workspace_path --server $server
        },

        "init" | "i" => {
            let curr_settings = (find_get_settings --infra $infra)
            state-init $workspace_path $curr_settings
            _print $"State initialized at (state-path $workspace_path)"
        },

        "reset" | "r" => {
            if ($server | is-empty) or ($taskserv | is-empty) {
                error make { msg: "state reset requires --server <hostname> --taskserv <name>" }
            }
            state-node-reset $workspace_path $server $taskserv
            _print $"($server)/($taskserv) reset to pending"
        },

        "migrate" | "m" => {
            state-migrate-from-json $workspace_path
        },

        "sync" => {
            let curr_settings = (find_get_settings --infra $infra)

            # 1. Drift detection + reconcile against servers.ncl
            let drift_rows = (state-drift $workspace_path $curr_settings --server $server)
            let has_drift = ($drift_rows | where drift != "ok" | is-not-empty)
            if $has_drift {
                _print "── drift ──"
                print ($drift_rows | where drift != "ok" | table)
                let result = (state-reconcile $workspace_path $curr_settings --server $server)
                if ($result.removed | is-not-empty) {
                    _print $"🗑 Removed ($result.removed | length) orphaned"
                }
                if ($result.added | is-not-empty) {
                    _print $"➕ Added ($result.added | length) pending"
                }
            } else {
                _print "✅ No drift against servers.ncl"
            }

            # 2. External API sync (Hetzner, K8s, SSH)
            let skip_ssh = ($flags | get -o skip_ssh | default false)
            state-sync $workspace_path $curr_settings --kubeconfig $kubeconfig --skip-ssh=$skip_ssh
        },

        "drift" | "d" => {
            let curr_settings = (find_get_settings --infra $infra)
            let rows = (state-drift $workspace_path $curr_settings --server $server)
            let has_drift = ($rows | where drift != "ok" | is-not-empty)
            if ($rows | is-empty) {
                _print "(no state entries to compare)"
            } else {
                print ($rows | table)
                if $has_drift {
                    _print $"\n⚠ Drift detected. Run (_ansi yellow_bold)provisioning state reconcile(_ansi reset) to fix."
                } else {
                    _print "\n✅ No drift — state matches servers.ncl"
                }
            }
        },

        "reconcile" | "rec" => {
            let curr_settings = (find_get_settings --infra $infra)
            let dry_run = ($flags | get -o dry_run | default false)

            # Always show drift first
            let drift_rows = (state-drift $workspace_path $curr_settings --server $server)
            let has_drift = ($drift_rows | where drift != "ok" | is-not-empty)
            if not $has_drift {
                _print "✅ No drift — nothing to reconcile"
                return
            }
            print ($drift_rows | where drift != "ok" | table)

            if $dry_run {
                _print "\n(dry-run: no changes applied)"
                return
            }

            let result = (state-reconcile $workspace_path $curr_settings --server $server)
            if ($result.removed | is-not-empty) {
                _print $"\n🗑 Removed ($result.removed | length) orphaned entries:"
                for r in $result.removed { _print $"  ($r.server)/($r.taskserv)" }
            }
            if ($result.added | is-not-empty) {
                _print $"\n➕ Added ($result.added | length) pending entries:"
                for a in $result.added { _print $"  ($a.server)/($a.taskserv)" }
            }
            _print "\n✅ State reconciled with servers.ncl"
        },

        _ => {
            _print "Usage: provisioning state <subcommand> [--infra <path>]"
            _print ""
            _print "  show      [--server <hostname>]                  — display state table"
            _print "  init      [--infra <path>]                       — bootstrap state from settings"
            _print "  reset     --server <hostname> --taskserv <name>  — reset node to pending"
            _print "  migrate                                          — migrate .json → .ncl"
            _print "  sync      [--infra <path>] [--kubeconfig <path>] — reconcile from APIs"
            _print "  drift     [--infra <path>] [--server <hostname>] — detect state vs servers.ncl divergence"
            _print "  reconcile [--infra <path>] [--server <hostname>] — fix drift (remove orphaned, add missing)"
        },
    }
}
