#!/usr/bin/env nu
# Volume management commands — hcloud-backed, workspace-aware.

use lib_provisioning/utils/interface.nu [_print set-provisioning-out set-provisioning-no-terminal]
use lib_provisioning/utils/settings.nu [find_get_settings]
use lib_provisioning/utils/nickel_processor.nu [ncl-eval-soft]

def main [
    ...args: string
    --infra (-i): string = ""
    --yes (-y)
    --out: string = ""
]: nothing -> nothing {
    if ($out | is-not-empty) {
        set-provisioning-out $out
        set-provisioning-no-terminal true
    }

    let subcmd = ($args | get 0? | default "")
    let rest   = if ($args | length) > 1 { $args | skip 1 } else { [] }

    match $subcmd {
        "list"   | "l"  => { main list --infra $infra --out $out }
        "create" | "c"  => {
            let name    = ($rest | get 0? | default "")
            let size    = ($rest | get 1? | default "20")
            let loc     = ($rest | get 2? | default "")
            main create $name --size ($size | into int) --location $loc --yes=$yes
        }
        "attach" | "a"  => {
            let name   = ($rest | get 0? | default "")
            let server = ($rest | get 1? | default "")
            main attach $name --server $server --yes=$yes
        }
        "detach" | "d"  => {
            let name = ($rest | get 0? | default "")
            main detach $name --yes=$yes
        }
        "delete" | "rm" => {
            let name = ($rest | get 0? | default "")
            main delete $name --yes=$yes
        }
        "" | "help" => { show-volume-help }
        _ => {
            _print $"❌ Unknown volume subcommand: ($subcmd)"
            show-volume-help
        }
    }
}

def show-volume-help [] {
    _print "
Volume Management
=================
Usage: provisioning volume <command> [args]

Commands:
  list                              List all volumes with attachment status
  create <name> [size] [location]   Create a new volume (default: 20GB, infra location)
  attach <name> <server>            Attach a volume to a server
  detach <name>                     Detach a volume from its server
  delete <name>                     Delete a volume (must be detached)

Examples:
  prvng volume list
  prvng volume create libre-daoshi-data 20 fsn1
  prvng volume attach libre-daoshi-data libre-daoshi-0
  prvng volume detach libre-daoshi-data
  prvng volume delete libre-daoshi-data
"
}

export def "main list" [
    --infra (-i): string = ""
    --out: string = ""
]: nothing -> nothing {
    if ($out | is-not-empty) {
        set-provisioning-out $out
        set-provisioning-no-terminal true
    }

    let res = (do { ^hcloud volume list -o json } | complete)
    if $res.exit_code != 0 or ($res.stdout | str trim | is-empty) {
        _print "⚠  hcloud unavailable or no volumes found"
        return
    }

    let vols = ($res.stdout | from json)
    if ($vols | is-empty) {
        _print "No volumes found"
        return
    }

    # Resolve infra filter from workspace context
    let infra_filter = if ($infra | is-not-empty) { $infra | path basename } else {
        let ws_config = ($env.PWD | path join "config" "provisioning.ncl")
        if ($ws_config | path exists) {
            (ncl-eval-soft $ws_config [] {} | get -o current_infra | default "")
        } else { "" }
    }

    let rows = ($vols | each {|v|
        let server_name = ($v.server?.name? | default "—")
        let protection  = if ($v.protection?.delete? | default false) { "🔒" } else { "" }
        {
            name:       $v.name
            size:       $"($v.size)GB"
            location:   ($v.location?.name? | default "")
            format:     ($v.format? | default "—")
            server:     $server_name
            status:     $v.status
            protection: $protection
        }
    })

    _print ($rows | table -i false)
}

export def "main create" [
    name: string
    --size (-s): int = 20
    --location (-l): string = ""
    --format (-f): string = "ext4"
    --yes (-y)
]: nothing -> nothing {
    if ($name | is-empty) {
        error make { msg: "Usage: provisioning volume create <name> [--size <GB>] [--location <loc>]" }
    }

    # Resolve location: flag > infra settings > fsn1
    let loc = if ($location | is-not-empty) { $location } else {
        let ws_config = ($env.PWD | path join "config" "provisioning.ncl")
        if ($ws_config | path exists) {
            (ncl-eval-soft $ws_config [] {} | get -o region | default "fsn1")
        } else { "fsn1" }
    }

    # Check if already exists
    let existing = (do { ^hcloud volume describe $name -o json } | complete)
    if $existing.exit_code == 0 {
        _print $"ℹ️  Volume '($name)' already exists"
        return
    }

    if not $yes {
        _print $"Create volume '($name)' — ($size)GB, ($loc), format: ($format)"
        _print "Confirm? [y/N] "
        let c = (input "")
        if $c not-in ["y", "Y", "yes"] { _print "Aborted."; return }
    }

    let res = (do { ^hcloud volume create --name $name --size ($size | into string) --location $loc --format $format } | complete)
    if $res.exit_code != 0 {
        error make { msg: $"Failed to create volume: ($res.stderr)" }
    }
    _print $"✓ Volume '($name)' created — ($size)GB at ($loc)"
}

export def "main attach" [
    name: string
    --server (-s): string = ""
    --yes (-y)
]: nothing -> nothing {
    if ($name | is-empty) or ($server | is-empty) {
        error make { msg: "Usage: provisioning volume attach <name> --server <hostname>" }
    }

    let vol_res = (do { ^hcloud volume describe $name -o json } | complete)
    if $vol_res.exit_code != 0 {
        error make { msg: $"Volume '($name)' not found" }
    }
    let vol = ($vol_res.stdout | from json)
    let current_srv = ($vol.server?.name? | default "")
    if ($current_srv | is-not-empty) {
        if $current_srv == $server {
            _print $"ℹ️  Volume '($name)' already attached to '($server)'"
            return
        }
        error make { msg: $"Volume '($name)' is attached to '($current_srv)' — detach first" }
    }

    let res = (do { ^hcloud volume attach $name --server $server } | complete)
    if $res.exit_code != 0 {
        error make { msg: $"Failed to attach: ($res.stderr)" }
    }
    _print $"✓ Volume '($name)' attached to '($server)'"
}

export def "main detach" [
    name: string
    --yes (-y)
]: nothing -> nothing {
    if ($name | is-empty) {
        error make { msg: "Usage: provisioning volume detach <name>" }
    }

    let vol_res = (do { ^hcloud volume describe $name -o json } | complete)
    if $vol_res.exit_code != 0 {
        error make { msg: $"Volume '($name)' not found" }
    }
    let vol = ($vol_res.stdout | from json)
    let current_srv = ($vol.server?.name? | default "")
    if ($current_srv | is-empty) {
        _print $"ℹ️  Volume '($name)' is not attached"
        return
    }

    if not $yes {
        _print $"Detach '($name)' from '($current_srv)'? [y/N] "
        let c = (input "")
        if $c not-in ["y", "Y", "yes"] { _print "Aborted."; return }
    }

    let res = (do { ^hcloud volume detach $name } | complete)
    if $res.exit_code != 0 {
        error make { msg: $"Failed to detach: ($res.stderr)" }
    }
    _print $"✓ Volume '($name)' detached from '($current_srv)'"
}

export def "main delete" [
    name: string
    --yes (-y)
]: nothing -> nothing {
    if ($name | is-empty) {
        error make { msg: "Usage: provisioning volume delete <name>" }
    }

    let vol_res = (do { ^hcloud volume describe $name -o json } | complete)
    if $vol_res.exit_code != 0 {
        error make { msg: $"Volume '($name)' not found" }
    }
    let vol = ($vol_res.stdout | from json)
    if ($vol.server? | default null) != null {
        error make { msg: $"Volume '($name)' is attached to '($vol.server.name)' — detach first" }
    }

    if not $yes {
        _print $"Permanently delete volume '($name)' (($vol.size)GB)? Type '($name)' to confirm: "
        let c = (input "")
        if $c != $name { _print "Aborted."; return }
    }

    # Disable protection if set
    if ($vol.protection?.delete? | default false) {
        let unlock = (do { ^hcloud volume disable-protection $name delete } | complete)
        if $unlock.exit_code != 0 {
            error make { msg: $"Failed to disable protection: ($unlock.stderr)" }
        }
    }

    let res = (do { ^hcloud volume delete $name } | complete)
    if $res.exit_code != 0 {
        error make { msg: $"Failed to delete: ($res.stderr)" }
    }
    _print $"✓ Volume '($name)' deleted"
}
