# Hetzner Cloud HTTP API Client
use env.nu *

# Get Bearer token for API authentication
export def hetzner_api_auth []: nothing -> string {
    let token = (hetzner_api_token)
    if ($token | is-empty) {
        error make {msg: "HCLOUD_TOKEN environment variable not set. Set your Hetzner API token before using the API interface."}
    }
    $token
}

# Build full API URL
export def hetzner_api_url [path: string]: nothing -> string {
    let base = (hetzner_api_url_base)
    $"($base)($path)"
}

# Generic HTTP request with error handling
export def hetzner_api_request [method: string, path: string, data?: any]: nothing -> any {
    let token = (hetzner_api_auth)
    let url = (hetzner_api_url $path)

    if (hetzner_debug) {
        print $"DEBUG: hetzner_api_request method=($method) path=($path) url=($url)" | encode utf8 | into string
    }

    let headers = [Authorization $"Bearer ($token)"]

    let result = (do {
        match $method {
            "GET" => {
                http get --headers $headers --allow-errors $url
            }
            "POST" => {
                http post --headers $headers --content-type application/json --allow-errors $url $data
            }
            "PUT" => {
                http put --headers $headers --content-type application/json --allow-errors $url $data
            }
            "DELETE" => {
                http delete --headers $headers --allow-errors $url
            }
            _ => {
                error make {msg: $"Unsupported HTTP method: ($method)"}
            }
        }
    } | complete)
    if $result.exit_code != 0 {
        error make {msg: $"Hetzner API request failed: ($result.stderr)"}
    } else {
        $result.stdout
    }
}

# List all servers
export def hetzner_api_list_servers []: nothing -> list {
    let response = (hetzner_api_request "GET" "/servers")

    if ($response | describe) =~ "error" {
        error make {msg: "Failed to list servers from API"}
    }

    if ($response | has servers) {
        $response.servers
    } else {
        []
    }
}

# Get server info by ID or name
export def hetzner_api_server_info [id_or_name: string]: nothing -> record {
    let response = (hetzner_api_request "GET" $"/servers/($id_or_name)")

    if ($response | describe) =~ "error" {
        error make {msg: $"Server not found: ($id_or_name)"}
    }

    if ($response | has server) {
        $response.server
    } else {
        $response
    }
}

# Create a new server
export def hetzner_api_create_server [config: record]: nothing -> record {
    if (hetzner_debug) {
        print $"DEBUG: Creating server with config: ($config | to json)" | encode utf8 | into string
    }

    let response = (hetzner_api_request "POST" "/servers" $config)

    if ($response | describe) =~ "error" {
        error make {msg: $"Failed to create server: ($response)"}
    }

    if ($response | has server) {
        $response.server
    } else {
        $response
    }
}

# Delete a server
export def hetzner_api_delete_server [id: string]: nothing -> nothing {
    let response = (hetzner_api_request "DELETE" $"/servers/($id)")
    null
}

# Perform server action (start, stop, reboot, etc.)
export def hetzner_api_server_action [id: string, action: string]: nothing -> record {
    let data = {action: $action}
    let response = (hetzner_api_request "POST" $"/servers/($id)/actions/($action)" $data)

    if ($response | has action) {
        $response.action
    } else {
        $response
    }
}

# List all locations
export def hetzner_api_list_locations []: nothing -> list {
    let response = (hetzner_api_request "GET" "/locations")

    if ($response | has locations) {
        $response.locations
    } else {
        []
    }
}

# List all server types
export def hetzner_api_list_server_types []: nothing -> list {
    let response = (hetzner_api_request "GET" "/server_types")

    if ($response | has server_types) {
        $response.server_types
    } else {
        []
    }
}

# Get server type info
export def hetzner_api_server_type_info [id_or_name: string]: nothing -> record {
    let response = (hetzner_api_request "GET" $"/server_types/($id_or_name)")

    if ($response | has server_type) {
        $response.server_type
    } else {
        $response
    }
}

# List all images
export def hetzner_api_list_images []: nothing -> list {
    let response = (hetzner_api_request "GET" "/images")

    if ($response | has images) {
        $response.images
    } else {
        []
    }
}

# List all volumes
export def hetzner_api_list_volumes []: nothing -> list {
    let response = (hetzner_api_request "GET" "/volumes")

    if ($response | has volumes) {
        $response.volumes
    } else {
        []
    }
}

# Create a volume
export def hetzner_api_create_volume [config: record]: nothing -> record {
    let response = (hetzner_api_request "POST" "/volumes" $config)

    if ($response | has volume) {
        $response.volume
    } else {
        $response
    }
}

# Delete a volume
export def hetzner_api_delete_volume [id: string]: nothing -> nothing {
    hetzner_api_request "DELETE" $"/volumes/($id)"
    null
}

# Attach volume to server
export def hetzner_api_attach_volume [volume_id: string, server_id: string]: nothing -> record {
    let data = {
        server: ($server_id | into int)
        automount: false
    }
    let response = (hetzner_api_request "POST" $"/volumes/($volume_id)/actions/attach" $data)

    if ($response | has action) {
        $response.action
    } else {
        $response
    }
}

# Detach volume from server
export def hetzner_api_detach_volume [volume_id: string]: nothing -> record {
    let response = (hetzner_api_request "POST" $"/volumes/($volume_id)/actions/detach" {})

    if ($response | has action) {
        $response.action
    } else {
        $response
    }
}

# List all networks
export def hetzner_api_list_networks []: nothing -> list {
    let response = (hetzner_api_request "GET" "/networks")

    if ($response | has networks) {
        $response.networks
    } else {
        []
    }
}

# Get network info
export def hetzner_api_network_info [id_or_name: string]: nothing -> record {
    let response = (hetzner_api_request "GET" $"/networks/($id_or_name)")

    if ($response | has network) {
        $response.network
    } else {
        $response
    }
}

# Attach network to server
export def hetzner_api_attach_network [server_id: string, network_id: string, ip?: string]: nothing -> record {
    let data = if ($ip != null) {
        {server: ($server_id | into int), network: ($network_id | into int), ip: $ip}
    } else {
        {server: ($server_id | into int), network: ($network_id | into int)}
    }

    let response = (hetzner_api_request "POST" $"/servers/($server_id)/actions/attach_to_network" $data)

    if ($response | has action) {
        $response.action
    } else {
        $response
    }
}

# Detach network from server
export def hetzner_api_detach_network [server_id: string, network_id: string]: nothing -> record {
    let data = {network: ($network_id | into int)}
    let response = (hetzner_api_request "POST" $"/servers/($server_id)/actions/detach_from_network" $data)

    if ($response | has action) {
        $response.action
    } else {
        $response
    }
}

# List all floating IPs
export def hetzner_api_list_floating_ips []: nothing -> list {
    let response = (hetzner_api_request "GET" "/floating_ips")

    if ($response | has floating_ips) {
        $response.floating_ips
    } else {
        []
    }
}

# Get pricing information
export def hetzner_api_get_pricing []: nothing -> record {
    let response = (hetzner_api_request "GET" "/pricing")

    if ($response | has pricing) {
        $response.pricing
    } else {
        $response
    }
}

# List SSH keys
export def hetzner_api_list_ssh_keys []: nothing -> list {
    let response = (hetzner_api_request "GET" "/ssh_keys")

    if ($response | has ssh_keys) {
        $response.ssh_keys
    } else {
        []
    }
}

# Get SSH key info
export def hetzner_api_ssh_key_info [id_or_name: string]: nothing -> record {
    let response = (hetzner_api_request "GET" $"/ssh_keys/($id_or_name)")

    if ($response | has ssh_key) {
        $response.ssh_key
    } else {
        $response
    }
}

# List firewalls
export def hetzner_api_list_firewalls []: nothing -> list {
    let response = (hetzner_api_request "GET" "/firewalls")

    if ($response | has firewalls) {
        $response.firewalls
    } else {
        []
    }
}

# Get firewall info
export def hetzner_api_firewall_info [id_or_name: string]: nothing -> record {
    let response = (hetzner_api_request "GET" $"/firewalls/($id_or_name)")

    if ($response | has firewall) {
        $response.firewall
    } else {
        $response
    }
}

# Create firewall
export def hetzner_api_create_firewall [config: record]: nothing -> record {
    let response = (hetzner_api_request "POST" "/firewalls" $config)

    if ($response | has firewall) {
        $response.firewall
    } else {
        $response
    }
}
