#!/usr/bin/env nu
# provctl - Provisioning orchestrator
#
# Coordinates pack, unpack, install, and deploy operations
#
# Usage:
#   nu scripts/provisioning/provctl.nu build-bundle --target x86_64-linux
#   nu scripts/provisioning/provctl.nu install-bundle bundle.tar.gz
#   nu scripts/provisioning/provctl.nu status
#

def show-help [] {
    print "
provctl - syntaxis Provisioning Orchestrator

USAGE:
  nu scripts/provisioning/provctl.nu <ACTION> [OPTIONS]

ACTIONS:
  build-bundle            Create a distribution bundle
  install-bundle          Extract and install a bundle
  deploy-bundle           Deploy configs from extracted bundle
  full-install            Extract, install, and deploy (complete setup)
  status                  Show installation status
  list-targets            List available build targets
  verify-bundle           Verify bundle integrity
  clean                   Clean staging directories
  help                    Show this help message

OPTIONS (build-bundle):
  --target <TARGET>       Target triple (e.g., x86_64-unknown-linux-gnu)
  --format <FORMAT>       Package format (tar.gz, zip, deb, rpm)
  --output <DIR>          Output directory
  --verify                Verify bundle after creation

OPTIONS (install-bundle):
  --bundle <FILE>         Bundle file path
  --dest <DIR>            Extraction destination
  --prefix <PATH>         Installation prefix
  --force                 Force overwrite

OPTIONS (deploy-bundle):
  --source <DIR>          Source bundle directory
  --config-dir <PATH>     Target config directory
  --backup                Backup existing configs

OPTIONS (full-install):
  --bundle <FILE>         Bundle file
  --prefix <PATH>         Installation prefix
  --config-dir <PATH>     Config directory
  --verify                Verify throughout

EXAMPLES:
  # Build bundle for current platform
  provctl build-bundle

  # Build bundle for Linux
  provctl build-bundle --target x86_64-unknown-linux-gnu --output dist/

  # Show available targets
  provctl list-targets

  # Extract bundle
  provctl install-bundle --bundle ./bundle.tar.gz --prefix ~/.local

  # Complete installation from bundle
  provctl full-install --bundle ./bundle.tar.gz --verify

  # Check installation status
  provctl status
"
}

def action-build-bundle [--target: string = "", --format: string = "tar.gz", --output: path = "dist/", --verify = false] {
    print "🔨 Building distribution bundle..."
    print ""

    let args = [
        "scripts/provisioning/pack.nu"
        (if ($target != "") { ["--target", $target] } else { [] })
        (if ($format != "tar.gz") { ["--format", $format] } else { [] })
        (if ($output != "dist/") { ["--output", ($output | into string)] } else { [] })
        (if $verify { ["--verify"] } else { [] })
    ] | flatten

    try {
        nu ...$args
    } catch {
        error make {msg: "Failed to build bundle"}
    }
}

def action-install-bundle [--bundle: path = "", --dest: path = ".", --prefix: path = "", --force = false] {
    if ($bundle == "") {
        error make {msg: "Bundle file must be specified with --bundle"}
    }

    if (not (($bundle | path exists))) {
        let msg = "Bundle file not found: " + ($bundle | into string)
error make {msg: $msg}
    }

    print "📦 Installing bundle..."
    print ""

    let args = [
        "scripts/provisioning/unpack.nu"
        ($bundle | into string)
        "--dest"
        ($dest | into string)
    ] | flatten

    try {
        nu ...$args
    } catch {
        error make {msg: "Failed to extract bundle"}
    }

    # Find extracted bundle and install
    print ""
    print "📂 Installing binaries..."

    let bundle_dirs = (
        glob ($dest | path join "*")
        | where {|d| (($d | path type) == "dir")}
    )
    if ($bundle_dirs | is-empty) {
        error make {msg: "No bundle directory found after extraction"}
    }

    let bundle_root = $bundle_dirs.0
    let prefix_arg = if ($prefix == "") { [] } else { ["--prefix", ($prefix | into string)] }

    let install_args = [
        "scripts/provisioning/install.nu"
        "--source"
        ($bundle_root | path join "bin" | into string)
        ...$prefix_arg
        (if $force { ["--force"] } else { [] })
    ] | flatten

    try {
        nu ...$install_args
    } catch {
        error make {msg: "Failed to install binaries"}
    }
}

def action-deploy-bundle [--source: path = "", --config-dir: path = "", --backup = false] {
    if ($source == "") {
        error make {msg: "Source directory must be specified with --source"}
    }

    if (not (($source | path exists))) {
        let msg = "Source directory not found: " + ($source | into string)
error make {msg: $msg}
    }

    print "⚙️  Deploying configuration files..."
    print ""

    let config_arg = if ($config_dir == "") { [] } else { ["--config-dir", ($config_dir | into string)] }

    let args = [
        "scripts/provisioning/deploy.nu"
        "--source"
        ($source | into string)
        ...$config_arg
        (if $backup { ["--backup"] } else { [] })
    ] | flatten

    try {
        nu ...$args
    } catch {
        error make {msg: "Failed to deploy configs"}
    }
}

def action-full-install [--bundle: path = "", --prefix: path = "", --config-dir: path = "", --verify = false] {
    if ($bundle == "") {
        error make {msg: "Bundle file must be specified with --bundle"}
    }

    if (not (($bundle | path exists))) {
        let msg = "Bundle file not found: " + ($bundle | into string)
error make {msg: $msg}
    }

    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print "🚀 syntaxis Full Installation"
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print ""

    # Step 1: Extract
    print "📦 Step 1: Extracting bundle..."
    let temp_dir = (
        "/tmp" | path join "syntaxis-install" (date now | format date "%s")
    )
    ^mkdir -p $temp_dir

    try {
        action-install-bundle --bundle $bundle --dest $temp_dir --prefix $prefix --force true
    } catch {
        ^rm -rf $temp_dir
        error make {msg: "Installation failed during extraction"}
    }

    # Find extracted bundle
    let bundle_dirs = (
        glob ($temp_dir | path join "*")
        | where {|d| (($d | path type) == "dir")}
    )
    if ($bundle_dirs | is-empty) {
        ^rm -rf $temp_dir
        error make {msg: "No bundle directory found"}
    }

    let bundle_root = $bundle_dirs.0

    # Step 2: Deploy configs
    print ""
    print "⚙️  Step 2: Deploying configuration files..."

    try {
        action-deploy-bundle --source $bundle_root --config-dir $config_dir --backup true
    } catch {
        ^rm -rf $temp_dir
        error make {msg: "Installation failed during config deployment"}
    }

    # Cleanup
    ^rm -rf $temp_dir

    print ""
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print "✅ Installation complete!"
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}

def action-status [] {
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print "📊 Installation Status"
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print ""

    # Check manifest
    let manifest_dir = ($env.HOME | path join ".syntaxis")
    let manifest_file = ($manifest_dir | path join "manifest.toml")

    if (not (($manifest_file | path exists))) {
        print "⚠️  No installation manifest found"
        print "   Run: provctl full-install --bundle <file>"
        return
    }

    try {
        let manifest = (open --raw $manifest_file | from toml)

        print "Installation Details:"
        print ("  Timestamp: " + ($manifest.installation.installed_at | into string))
        print ("  Prefix:    " + ($manifest.installation.prefix | into string))
        print ""

        print ("Installed Binaries: " + (($manifest.installation.binaries | length) | into string))
        $manifest.installation.binaries | each {|binary_name|
            print ("  ✓ " + ($binary_name | into string))
        }
    } catch {
        print "⚠️  Could not read installation manifest"
    }

    # Check deployment manifest
    let deploy_manifest = ($manifest_dir | path join "deployment.toml")
    if (($deploy_manifest | path exists)) {
        try {
            let manifest = (open --raw $deploy_manifest | from toml)
            print ""
            print ("Deployed Configs: " + (($manifest.deployment.configs | length) | into string))
            $manifest.deployment.configs | each {|config|
                print ("  ✓ " + ($config | into string))
            }
        } catch { }
    }

    print ""
}

def action-list-targets [] {
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print "🎯 Available Build Targets"
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print ""

    try {
        nu scripts/provisioning/pack.nu --list-targets
    } catch {
        error make {msg: "Failed to list targets"}
    }
}

def action-verify-bundle [--bundle: path = ""] {
    if ($bundle == "") {
        let msg = "Bundle file must be specified with --bundle"
error make {msg: $msg}
    }

    if (not (($bundle | path exists))) {
        let msg = "Bundle not found: " + ($bundle | into string)
error make {msg: $msg}
    }

    print "🔍 Verifying bundle..."
    print ""

    # Validate structure
    let ext = ($bundle | path parse | get extension)
    let valid_format = (($ext == "gz") or ($ext == "zip"))

    if $valid_format {
        print ("✅ Bundle format valid: " + ($ext | into string))
    } else {
        error make {msg: "Invalid bundle format (expected .tar.gz or .zip)"}
    }

    # Check size
    let size_mb = (((ls $bundle | get size.0) | into int) / (1024 * 1024) | math round --precision 2)
    print ("✅ Bundle size: " + ($size_mb | into string) + " MB")

    # Check checksums file
    let bundle_name = ($bundle | path parse | get stem)
    let checksums_file = (
        ($bundle | path dirname)
        | path join ($bundle_name + ".checksums.toml")
    )

    if (($checksums_file | path exists)) {
        print "✅ Checksums file found"
    } else {
        print "⚠️  Checksums file not found"
    }

    print ""
    print "✅ Bundle verification complete"
}

def action-clean [] {
    print "🧹 Cleaning staging directories..."

    let staging_dirs = [
        ".provisioning-staging"
        "/tmp/syntaxis-install"
    ]

    $staging_dirs | each {|dir|
        if (($dir | path exists)) {
            ^rm -rf $dir
            print ("  ✓ Removed: " + ($dir | into string))
        }
    }

    print "✅ Cleanup complete"
}

def main [action: string = "", ...args: string] {
    match $action {
        "build-bundle" => {
            action-build-bundle
        }

        "install-bundle" => {
            action-install-bundle
        }

        "deploy-bundle" => {
            action-deploy-bundle --source "."
        }

        "full-install" => {
            action-full-install
        }

        "status" => {
            action-status
        }

        "list-targets" => {
            action-list-targets
        }

        "verify-bundle" => {
            action-verify-bundle
        }

        "clean" => {
            action-clean
        }

        "help" | "--help" | "-h" => {
            show-help
        }

        "" => {
            show-help
        }

        _ => {
            print ("Unknown action: " + ($action | into string))
            print ""
            show-help
        }
    }
}

# Parse args and execute
let action = if (($in | length) > 0) { $in.0 } else { "" }
