# REMOVED: use lib_provisioning * - causes circular import
use utils.nu *
use ../lib_provisioning/config/accessor.nu *
use ../lib_provisioning/utils/init.nu [provisioning_init]
use ../lib_provisioning/utils/settings.nu [find_get_settings]
use ../lib_provisioning/utils/interface.nu [set-provisioning-no-terminal set-provisioning-out get-provisioning-out _print end_run]
use ../lib_provisioning/utils/logging.nu [set-debug-enabled set-metadata-enabled is-debug-enabled]
use delete.nu [sync-servers-state-post-op]

# List all servers
export def "main list" [
    ...args                     # Args for list command
    --infra (-i): string        # Infra directory
    --settings (-s): string     # Settings path
    --outfile (-o): string      # Output file
    --check (-c)                # Only check mode
    --debug (-x)                # Use Debug mode
    --xm                        # Debug with PROVISIONING_METADATA
    --xc                        # Debug for task and services locally
    --xr                        # Debug for remote servers
    --xld                       # Log level with DEBUG
    --metadata                  # Error with metadata
    --notitles                  # not titles
    --helpinfo (-h)             # For more details use options "help"
    --out: string               # Print Output format: json, yaml, text (default)
] {
    if ($out | is-not-empty) {
        set-provisioning-out $out
        set-provisioning-no-terminal true
    }

    provisioning_init $helpinfo "servers list" $args

    if $debug { set-debug-enabled true }
    if $metadata { set-metadata-enabled true }

    # Load server settings
    let curr_settings = (find_get_settings --infra $infra --settings $settings)
    if (($curr_settings | describe) == "nothing") or ($curr_settings == null) {
        let target = if ($infra | is-not-empty) { $infra } else if ($settings | is-not-empty) { $settings } else { "current context" }
        error make { msg: $"Unable to load server settings for '($target)'" }
    }

    # Get servers info
    let servers_table = (mw_servers_info $curr_settings)

    # Check if any servers exist
    if ($servers_table | length) == 0 {
        if (get-provisioning-out | is-empty) {
            _print "No servers configured"
        } else {
            _print ([] | to json) "json" "result" "table"
        }
    } else {
        # Display servers
        if ($out | is-empty) {
            # Terminal output with formatting
            _print ($servers_table | table -i false)
        } else {
            # Structured output (JSON, YAML)
            match (get-provisioning-out) {
                "json" => { _print ($servers_table | to json) "json" "result" "table" }
                "yaml" => { _print ($servers_table | to yaml) "yaml" "result" "table" }
                _ => { _print ($servers_table | table -i false) }
            }
        }
    }

    if not $notitles and not (is-debug-enabled) { end_run "" }
}

# Sync server state from Hetzner Cloud to .servers-state.json.
# Run after server create, delete, or any manual change in Hetzner.
export def "main sync" [
    --infra (-i): string = ""
]: nothing -> nothing {
    # Resolve workspace path from user config (same as query-servers.nu — env var not propagated)
    let user_config_path = (
        $env.HOME
        | path join "Library" "Application Support" "provisioning" "user_config.yaml"
    )
    if not ($user_config_path | path exists) {
        error make { msg: $"user_config.yaml not found at ($user_config_path)" }
    }

    let config        = (open $user_config_path)
    let active_name   = ($config | get -o active_workspace | default "")
    let workspaces    = ($config | get -o workspaces | default [])

    if ($active_name | is-empty) {
        error make { msg: "active_workspace not set in user_config.yaml" }
    }

    let active_ws = ($workspaces | where { $in.name == $active_name } | first | default null)
    if $active_ws == null {
        error make { msg: $"Workspace '($active_name)' not found in user_config.yaml" }
    }

    let ws_root    = $active_ws.path
    let infra_name = if ($infra | is-not-empty) {
        $infra | path basename
    } else {
        $active_ws | get -o default_infra | default ""
    }

    if ($infra_name | is-empty) {
        error make { msg: "Specify --infra <name> or set a default_infra in the workspace config" }
    }

    print $"Syncing server state: workspace=($active_ws.name) infra=($infra_name)"
    sync-servers-state-post-op $ws_root $infra_name
}
