#!/usr/bin/env nu
# lian_build catalog CLI — OCI registry management via crane.
# Entry: prvng registry <ls|tags|manifest|rm> [ref]
#
# crane must be in PATH. Credentials read from ~/.docker/config.json.
# To authenticate: crane auth login registry.example.com

export-env {
    let lib_dirs_raw = ($env.NU_LIB_DIRS? | default "")
    let current_lib_dirs = if ($lib_dirs_raw | describe) == "string" {
        if ($lib_dirs_raw | is-empty) { [] } else { ($lib_dirs_raw | split row ":") }
    } else { $lib_dirs_raw }
    let dynamic = ($env.PROVISIONING? | default "" | path join "core" "nulib")
    $env.NU_LIB_DIRS = ([
        "/opt/provisioning/core/nulib"
        "/usr/local/provisioning/core/nulib"
    ] | append $current_lib_dirs
      | append (if ($dynamic | is-not-empty) { [$dynamic] } else { [] }))
}

use cli/flags.nu [parse_common_flags]

const REGISTRY = "registry.example.com"

def crane [...args: string]: nothing -> string {
    let r = (do { ^crane ...$args } | complete)
    if $r.exit_code != 0 {
        let msg = ($r.stderr | str trim)
        if ($msg | str contains "UNAUTHORIZED") or ($msg | str contains "401") {
            error make { msg: $"registry auth failed — run: crane auth login ($REGISTRY)" }
        }
        error make { msg: $"crane failed: ($msg)" }
    }
    $r.stdout
}

def registry-ls []: nothing -> nothing {
    let repos = (crane "catalog" $REGISTRY | lines | where { |l| $l | is-not-empty })
    if ($repos | is-empty) {
        print "no repositories found"
        return
    }
    $repos | each { |r| { repository: $r } } | table
}

def registry-tags [repo: string]: nothing -> nothing {
    if ($repo | is-empty) {
        error make { msg: "registry tags requires a repository name (e.g. example.com/website)" }
    }
    let ref = $"($REGISTRY)/($repo)"
    let tags = (crane "ls" $ref | lines | where { |l| $l | is-not-empty })
    if ($tags | is-empty) {
        print $"no tags in ($repo)"
        return
    }
    $tags | each { |t| { tag: $t, ref: $"($ref):($t)" } } | table
}

def registry-manifest [ref: string]: nothing -> nothing {
    if ($ref | is-empty) {
        error make { msg: "registry manifest requires an image ref (e.g. example.com/website:latest)" }
    }
    let full_ref = if ($ref | str contains $REGISTRY) { $ref } else { $"($REGISTRY)/($ref)" }
    let manifest = (crane "manifest" $full_ref)
    print $manifest
}

def registry-rm [ref: string, confirmed: bool]: nothing -> nothing {
    if ($ref | is-empty) {
        error make { msg: "registry rm requires an image ref (e.g. example.com/website:latest)" }
    }
    let full_ref = if ($ref | str contains $REGISTRY) { $ref } else { $"($REGISTRY)/($ref)" }
    if not $confirmed {
        let answer = (input $"Delete '($full_ref)'? [y/N]: " | str downcase | str trim)
        if $answer != "y" { print "aborted"; return }
    }
    crane "delete" $full_ref | ignore
    print $"deleted ($full_ref)"
}

def registry-help []: nothing -> nothing {
    print $"Usage: prvng registry <command> [ref]  — registry: ($REGISTRY)"
    print ""
    print "Commands:"
    print "  ls                    List all repositories"
    print "  tags <repo>           List tags  (e.g. example.com/website)"
    print "  manifest <ref>        Show manifest (e.g. example.com/website:latest)"
    print "  rm <ref>              Delete a tag/manifest"
    print ""
    print "Auth:  crane auth login ($REGISTRY)"
}

def main [
    command: string = ""
    ...rest: string
    --yes (-y)
    --debug (-x)
    --notitles
]: nothing -> nothing {
    if $debug { $env.PROVISIONING_DEBUG = true }
    let ref = ($rest | str join " " | str trim)
    let flags = (parse_common_flags { yes: $yes, debug: $debug, notitles: $notitles })
    let confirmed = ($flags.auto_confirm? | default false)
    match $command {
        "ls" | "list" | "" => { registry-ls }
        "tags" | "t"       => { registry-tags $ref }
        "manifest" | "m"   => { registry-manifest $ref }
        "rm" | "delete"    => { registry-rm $ref $confirmed }
        _                  => { registry-help }
    }
}
