#!/usr/bin/env nu
# Deploy - Deploy configuration files
#
# Usage:
#   nu scripts/provisioning/deploy.nu --source ./configs
#   nu scripts/provisioning/deploy.nu --source ./configs --config-dir ~/.config/syntaxis
#

use common/validate.nu *

def show-help [] {
    let help_text = "
syntaxis Deploy - Deploy configuration files

USAGE:
  nu scripts/provisioning/deploy.nu [OPTIONS]

OPTIONS:
  --source <DIR>        Source directory containing config files (required)
  --config-dir <PATH>   Target config directory
                        Default: ~/.config/syntaxis
  --backup              Backup existing configs before overwriting
  --force               Overwrite existing configs without prompting
  --help                Show this help message

EXAMPLES:
  # Deploy to default location
  nu scripts/provisioning/deploy.nu --source ./configs

  # Deploy to custom directory
  nu scripts/provisioning/deploy.nu --source ./configs --config-dir ~/my-config

  # Deploy with backup
  nu scripts/provisioning/deploy.nu --source ./configs --backup
"
    print $help_text
}

def find-config-files [source_dir: path] {
    if (not (($source_dir | path exists))) {
        let msg = "Source directory not found: " + ($source_dir | into string)
error make {msg: $msg}
    }

    let files = (glob ($source_dir | path join "**" "*"))
    let configs = (
        $files
        | where {|f| (($f | path type) == "file")}
        | each {|f| {
            path: $f
            name: ($f | path basename)
            relative: ($f | path relative-to $source_dir // ($f | path basename))
        }}
    )

    if (($configs | length) == 0) {
        let msg = "No config files found in: " + ($source_dir | into string)
error make {msg: $msg}
    }

    $configs
}

def ensure-config-directory [config_dir: path] {
    if (not (($config_dir | path exists))) {
        print ("📁 Creating directory: " + ($config_dir | into string))
        ^mkdir -p $config_dir
    }

    let perm_check = (validate-permissions $config_dir --write true)
    if (not ($perm_check.valid)) {
        let msg = "Cannot write to directory: " + ($config_dir | into string)
error make {msg: $msg}
    }
}

def backup-existing-config [config_dir: path, config_name: string] {
    let config_path = ($config_dir | path join $config_name)
    if (($config_path | path exists)) {
        let timestamp = (date now | format date "%Y%m%d-%H%M%S")
        let backup_path = ($config_dir | path join ($config_name + ".backup-" + $timestamp))
        ^mkdir -p ($backup_path | path dirname)
        ^cp $config_path $backup_path
        print ("  📦 Backed up to: " + ($backup_path | path basename))
    }
}

def deploy-config [source_path: path, config_dir: path, config_relative: string, backup: bool, force: bool] {
    let dest_path = ($config_dir | path join $config_relative)
    let dest_dir = ($dest_path | path dirname)

    # Ensure subdirectory exists
    if (not (($dest_dir | path exists))) {
        ^mkdir -p $dest_dir
    }

    if (($dest_path | path exists)) {
        if $backup {
            backup-existing-config $dest_dir ($dest_path | path basename)
        } else if (not $force) {
            print ("  ⚠️  " + $config_relative + " already exists (use --force to overwrite)")
            return false
        }
    }

    print ("  📋 Deploying: " + $config_relative)
    ^cp $source_path $dest_path
    print ("    ✓ Deployed to: " + ($dest_path | into string))
    true
}

def create-deployment-manifest [config_dir: path, deployed_configs: list] {
    let manifest_dir = ($env.HOME | path join ".syntaxis")
    ^mkdir -p $manifest_dir

    let manifest = {
        deployment: {
            deployed_at: (date now | format date "%Y-%m-%dT%H:%M:%SZ")
            config_dir: ($config_dir | into string)
            configs: $deployed_configs
        }
    }

    let manifest_file = ($manifest_dir | path join "deployment.toml")
    let content = $manifest | to toml
    $content | ^tee $manifest_file
    print ("✅ Deployment manifest saved: " + ($manifest_file | into string))
}

def show-deployment-summary [config_dir: path, deployed_configs: list] {
    print ""
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print "✅ Deployment Summary"
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print ("Deployed to: " + ($config_dir | into string))
    print ("Configs:     " + (($deployed_configs | length) | into string))
    $deployed_configs | each { |cfg|
        print ("  ✓ " + $cfg)
    }
    print ""
    print "Next steps:"
    print "  1. Review deployed configurations in: " + ($config_dir | into string)
    print "  2. Restart services as needed"
    print "  3. Check log files for any errors"
    print ""
}

# Main entry point
def main [--source: path = "", --config-dir: path = "", --backup = false, --force = false, --help = false] {
    if $help {
        show-help
        return
    }

    if ($source == "") {
        error make {msg: "Source directory must be specified with --source"}
    }

    # Determine config directory
    let target_config_dir = if ($config_dir == "") {
        $env.HOME | path join ".config" "syntaxis"
    } else {
        $config_dir
    }

    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print "📦 syntaxis Deploy"
    print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print ("Source:      " + ($source | into string))
    print ("Destination: " + ($target_config_dir | into string))
    print ("Backup:      " + ($backup | into string))
    print ("Force:       " + ($force | into string))
    print ""

    # Ensure destination directory is writable
    ensure-config-directory $target_config_dir

    # Find config files
    print "🔍 Finding configuration files..."
    let configs = (find-config-files $source)
    print ("  Found " + (($configs | length) | into string) + " config files")
    print ""

    # Deploy each config
    print "📥 Deploying configuration files..."
    let deployed_configs = (
        $configs
        | each { |cfg|
            let success = (deploy-config $cfg.path $target_config_dir $cfg.relative $backup $force)
            if $success {
                $cfg.relative
            } else {
                null
            }
        }
        | where { |item| (not ($item == null)) }
    )

    if (($deployed_configs | length) > 0) {
        create-deployment-manifest $target_config_dir $deployed_configs
        show-deployment-summary $target_config_dir $deployed_configs
    } else {
        print "❌ No configs were deployed"
    }
}

