#!/usr/bin/env nu
# Minimal Library - Fast path for interactive commands
# NO config loading, NO platform bootstrap
# Follows: @.claude/guidelines/nushell/NUSHELL_GUIDELINES.md
# Error handling: Result pattern (hybrid, no try-catch)

use lib_provisioning/result.nu *

# Get user config path (centralized location)
# Rule 2: Single purpose function
# Cross-platform support (macOS, Linux, Windows)
def get-user-config-path [] {
    let home = $env.HOME
    let os_name = (uname | get operating-system | str downcase)

    let config_path = match $os_name {
        "darwin" => $"($home)/Library/Application Support/provisioning/user_config.yaml",
        _ => $"($home)/.config/provisioning/user_config.yaml"
    }

    $config_path | path expand
}

# List all registered workspaces
# Rule 1: Explicit types, Rule 4: Early returns
# Rule 2: Single purpose - only list workspaces
# Result: {ok: list, err: null} on success; {ok: null, err: message} on error
export def workspace-list [] {
    let user_config = (get-user-config-path)

    # Guard: Early return if config doesn't exist
    if not ($user_config | path exists) {
        return (ok [])
    }

    # Guard: File is guaranteed to exist, open directly (no try-catch)
    let config = (open $user_config)

    let active = ($config | get --optional active_workspace | default "")
    let workspaces = ($config | get --optional workspaces | default [])

    # Guard: No workspaces registered
    if ($workspaces | length) == 0 {
        return (ok [])
    }

    # Pure transformation
    let result = ($workspaces | each {|ws|
        {
            name: $ws.name
            path: $ws.path
            active: ($ws.name == $active)
            last_used: ($ws | get --optional last_used | default "Never")
        }
    })

    ok $result
}

# Get active workspace name
# Rule 1: Explicit types, Rule 4: Early returns
# Result: {ok: string, err: null} on success; {ok: null, err: message} on error
export def workspace-active [] {
    let user_config = (get-user-config-path)

    # Guard: Config doesn't exist
    if not ($user_config | path exists) {
        return (ok "")
    }

    # Guard: File exists, read directly
    let active_name = (open $user_config | get --optional active_workspace | default "")
    ok $active_name
}

# Get workspace info by name
# Rule 1: Explicit types, Rule 4: Early returns
# Result: {ok: record, err: null} on success; {ok: null, err: message} on error
export def workspace-info [name: string] {
    # Guard: Input validation
    if ($name | is-empty) {
        return (err "workspace name is required")
    }

    let user_config = (get-user-config-path)

    # Guard: Config doesn't exist
    if not ($user_config | path exists) {
        return (ok {name: $name, path: "", exists: false})
    }

    # Guard: File exists, read directly
    let config = (open $user_config)
    let workspaces = ($config | get --optional workspaces | default [])
    let ws = ($workspaces | where { $in.name == $name } | first)

    # Guard: Workspace not found
    if ($ws | is-empty) {
        return (ok {name: $name, path: "", exists: false, default_infra: "", infrastructures: []})
    }

    # Collect infra dirs with server counts
    let infra_root = ($ws.path | path join 'infra')
    let infrastructures = if ($infra_root | path exists) {
        ls $infra_root
        | where type == 'dir'
        | each {|inf|
            let inf_name = ($inf.name | path basename)
            let sf_direct = ($infra_root | path join $inf_name | path join 'servers.ncl')
            let sf_defs   = ($infra_root | path join $inf_name | path join 'defs' | path join 'servers.ncl')
            let sf = if ($sf_direct | path exists) { $sf_direct } else { $sf_defs }
            let server_count = if ($sf | path exists) {
                open $sf --raw | split row "\n" | where {|l| $l =~ 'hostname\s*=\s*"' } | length
            } else { 0 }
            { name: $inf_name, servers: $server_count }
        }
    } else { [] }

    ok {
        name: $ws.name
        path: $ws.path
        exists: true
        last_used: ($ws | get --optional last_used | default "Never")
        default_infra: ($ws | get --optional default_infra | default "")
        infrastructures: $infrastructures
    }
}

# Quick status check (orchestrator health + active workspace)
# Rule 1: Explicit types, Rule 4: Early returns
# Result: {ok: record, err: null} on success; {ok: null, err: message} on error
export def status-quick [] {
    # Guard: HTTP check with do/complete pattern (no try-catch)
    let health_result = (do { http get --max-time 2sec "http://localhost:9090/health" } | complete)
    let orch_health = if ($health_result.exit_code == 0) { $health_result.stdout } else { null }
    let orch_status = if ($orch_health != null) { "running" } else { "stopped" }

    # Guard: Get active workspace safely
    let ws_result = (workspace-active)
    let active_ws = (if (is-ok $ws_result) { $ws_result.ok } else { "" })

    # Pure transformation
    ok {
        orchestrator: $orch_status
        workspace: $active_ws
        timestamp: (date now | format date "%Y-%m-%d %H:%M:%S")
    }
}

# Display essential environment variables
# Rule 1: Explicit types, Rule 8: Pure function (read-only)
# Result: {ok: record, err: null} on success; {ok: null, err: message} on error
export def env-quick [] {
    # Pure transformation with optional operator
    let vars = {
        PROVISIONING_ROOT: ($env.PROVISIONING_ROOT? | default "not set")
        PROVISIONING_ENV: ($env.PROVISIONING_ENV? | default "not set")
        PROVISIONING_DEBUG: ($env.PROVISIONING_DEBUG? | default "false")
        HOME: $env.HOME
        PWD: $env.PWD
    }

    ok $vars
}

# Show quick help for fast-path commands
# Rule 1: Explicit types, Rule 8: Pure function
export def quick-help [] {
    "Provisioning CLI - Fast Path Commands

Quick Commands (< 100ms):
  workspace list              List all registered workspaces
  workspace active            Show currently active workspace
  status                      Quick health check
  env                         Show essential environment variables
  help [command]              Show help for a command

For full help:
  provisioning help           Show all available commands
  provisioning help <command> Show help for specific command"
}
