#!/usr/bin/env nu
# Info: Script to run Provisioning
# Author: JesusPerezLorenzo
# Release: 1.0.4
# Date: 6-2-2024

#use std  # assert
use std log

# Detect project root and set up module paths early
# This ensures NU_LIB_DIRS is properly configured before loading modules
export-env {
    # Project root detection: look for kcl.mod or provisioning structure
    let potential_roots = [
        $env.PWD
        ($env.PWD | path dirname)
        ($env.PWD | path dirname | path dirname)
    ]

    let matching_roots = ($potential_roots
        | where ($it | path join "kcl.mod" | path exists)
            or ($it | path join "core" "nulib" | path exists))

    let project_root = if ($matching_roots | length) > 0 {
        $matching_roots | first
    } else {
        $env.PWD
    }

    # Update PWD in NU_LIB_DIRS to use detected project root
    if ($env.NU_LIB_DIRS? | default [] | any {|path| $path == $env.PWD}) {
        $env.NU_LIB_DIRS = ($env.NU_LIB_DIRS | each {|path|
            if $path == $env.PWD { $project_root } else { $path }
        })
    }

    # Add project-local env if it exists - will be loaded after main env.nu
}

use lib_provisioning *
use env.nu *

#Load all main defs
use main_provisioning *

#module srv { use instances.nu * }

use servers/ssh.nu *
use servers/utils.nu *
use taskservs/utils.nu find_taskserv

def run_module [
  args: string
  module: string
  option?: string
  --exec
] {
  let use_debug = if $env.PROVISIONING_DEBUG { "-x" } else { "" }
  # print $"($env.PROVISIONING_NAME) ($use_debug) -mod ($module) ($option | default "") ($args) --notitles "
  if $exec {
    exec $"($env.PROVISIONING_NAME)" $use_debug -mod $module ($option | default "") $args  --notitles
  } else {
    ^$"($env.PROVISIONING_NAME)" $use_debug -mod $module ($option | default "") $args --notitles
  }
}
#  -  > Help   on cprov
export def "main help" [
  --notitles       # not titles
  --out: string    # Print Output format: json, yaml, text (default)
] {
  if $notitles == null or not $notitles { show_titles }
  ^($env.PROVISIONING_NAME) "--help"
  if ($out | is-not-empty) { $env.PROVISIONING_NO_TERMINAL = false }
  print (provisioning_options)
  if not $env.PROVISIONING_DEBUG { end_run "" }
}

def main [
  ...args: string  # Other options, use help to get info
  --infra (-i): string     # Cloud directory
  --settings (-s): string # Settings path
  --serverpos (-p): int   # Server position in settings
  --outfile (-o): string  # Output file
  --template(-t): string  # Template path or name in PROVISION_KLOUDS_PATH
  --check (-c)     # Only check mode no servers will be created
  --yes (-y)       # confirm task
  --wait (-w)      # Wait servers to be created
  --keepstorage    # keep storage
  --select: string # Select with task as option
  --onsel: string  # On selection: e (edit) | v (view) | l (list) | t (tree)
  --infras: string # Infra list names separated by commas
  --new (-n): string    # New infrastructure name
  --debug (-x)     # Use Debug mode
  --xm             # Debug with PROVISIONING_METADATA
  --xc             # Debug for task and services locally PROVISIONING_DEBUG_CHECK
  --xr             # Debug for remote servers PROVISIONING_DEBUG_REMOTE
  --xld            # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
  --nc             # Not clean working settings
  --metadata       # Error with metadata (-xm)
  --notitles       # not tittles
  --environment: string    # Environment override (dev/test/prod)
  -v               # Show version
  --version (-V)   # Show version with title
  --info (-I)      # Show Info  with title
  --about (-a)     # Show About
  --helpinfo (-h)  # For more details use options "help" (no dashes)
  --out: string    # Print Output format: json, yaml, text (default)
  --view           # Print with highlight
  --inputfile: string  # Input format: json, yaml, text (default)
  --include_notuse # Include servers not use
]: nothing -> nothing {
  if ($out | is-not-empty) {
    $env.PROVISIONING_OUT = $out
    $env.PROVISIONING_NO_TERMINAL = true
  }
  provisioning_init $helpinfo "" $args
  if $version or $v { ^$env.PROVISIONING_NAME -v ; exit }
  if $info { ^$env.PROVISIONING_NAME -i ; exit }
  if $about {
    #use defs/about.nu [ about_info ]
    _print (get_about_info)
    exit
  }
  if $debug { $env.PROVISIONING_DEBUG = true }
  if $metadata { $env.PROVISIONING_METADATA = true }
  if ($environment | is-not-empty) { $env.PROVISIONING_ENV = $environment }
  let task = if ($args | length) > 0 { ($args| get 0) } else { if ($new | is-not-empty) { "new" } else { "" } }
  let ops = if ($args | length) > 0 {
    ($args| skip 1)
  } else {
    ( $"($env.PROVISIONING_ARGS? | default "") " | str replace $"($task) " ""
      | str trim | split row " ")
  }
  let str_ops = ($ops | str join " ")
  match $task {
    # "upcloud" => {
    #   #use upcloud/servers.nu upcloud
    #   if $infra == null {
    #     upcloud $args
    #   } else {
    #     upcloud --infra $infra $args
    #   }
    # },
    # "aws" => {
    #   #use aws/servers.nu aws
    #   if $infra == null {
    #     aws $args
    #   } else {
    #     aws --infra $infra $args
    #   }
    # },
    # "local" => {
    #   #use local/servers.nu local
    #   if $infra == null {
    #     local $args
    #   } else {
    #     local --infra $infra $args
    #   }
    # },
    "h" => {
      ^($env.PROVISIONING_NAME) help ($env.PROVISIONING_ARGS | str replace $task '') "--notitles"
    },
    "cache" => {
      let str_infra = if $infra != null  { $"--infra ($infra) "} else { "" }
      let str_outfile = if $outfile != null  { $"--outfile ($outfile) "} else { "" }
      let str_out = if $out != null  { $"--out ($out) "} else { "" }
      run_module $"($str_ops) ($str_infra) ($str_out) ($str_outfile)" "server" "cache"
    },
    "providers" => {
      #use defs/lists.nu *
      _print $"(_ansi green)PROVIDERS(_ansi reset) list: \n"
      _print (providers_list "selection" | to json) "json" "result" "table"
    },
    "ssh" => {
      #use servers/ssh.nu *
      #use utils/settings.nu *
      let curr_settings = (find_get_settings --infra $infra --settings $settings $include_notuse)
      rm -rf $curr_settings.wk_path
      server_ssh $curr_settings "" "pub" false
    }
    "sed" | "sops" => {
      if ($ops | length) == -2 {
        (throw-error $"🛑 No file found" $"for (_ansi yellow_bold)sops(_ansi reset) edit")
        exit -1
      }
      let pos = if $task == "sed" { 0 } else { 1 }
      let target_file = ($ops | get -o $pos | default "")
      let target_full_path = if ($target_file | path exists) == false {
        let infra_path = (get_infra $infra)
        if ($infra_path | path join $target_file | path exists)  {
          ($infra_path | path join $target_file)
        } else {
          (throw-error $"🛑 No file (_ansi green_italic)($target_file)(_ansi reset) found" $"for (_ansi yellow_bold)sops(_ansi reset) edit")
          exit -1
        }
      } else { $target_file }
      if $env.PROVISIONING_SOPS? == null  {
        let curr_settings = (find_get_settings --infra $infra --settings $settings $include_notuse)
        rm -rf $curr_settings.wk_path
        $env.CURRENT_INFRA_PATH = ($curr_settings.infra_path | path join $curr_settings.infra)
        use sops_env.nu
      }
      #use sops on_sops
      if $task == "sed" {
          on_sops "sed" $target_full_path
      } else {
          on_sops $task $target_full_path ($ops | skip 1)
      }
    },
    "e" | "env" => {
      # Check if this is the new environment management system
      let subcmd = ($ops | get -o 0 | default "")
      if $subcmd in ["list" "current" "switch" "validate" "compare" "show" "init" "detect" "set" "paths" "create" "delete" "export" "status"] {
        # Use new environment management system
        use lib_provisioning/cmd/environment.nu *
        match $subcmd {
          "list" => { env list }
          "current" => { env current }
          "switch" => {
            let target_env = ($ops | get -o 1 | default "")
            if ($target_env | is-empty) {
              print "Usage: env switch <environment>"
              exit 1
            }
            env switch $target_env
          }
          "validate" => {
            let target_env = ($ops | get -o 1 | default "")
            env validate $target_env
          }
          "compare" => {
            let env1 = ($ops | get -o 1 | default "")
            let env2 = ($ops | get -o 2 | default "")
            if ($env1 | is-empty) or ($env2 | is-empty) {
              print "Usage: env compare <env1> <env2>"
              exit 1
            }
            env compare $env1 $env2
          }
          "show" => {
            let target_env = ($ops | get -o 1 | default "")
            env show $target_env
          }
          "init" => {
            let target_env = ($ops | get -o 1 | default "")
            if ($target_env | is-empty) {
              print "Usage: env init <environment>"
              exit 1
            }
            env init $target_env
          }
          "detect" => { env detect }
          "set" => {
            let target_env = ($ops | get -o 1 | default "")
            if ($target_env | is-empty) {
              print "Usage: env set <environment>"
              exit 1
            }
            env set $target_env
          }
          "paths" => {
            let target_env = ($ops | get -o 1 | default "")
            env paths $target_env
          }
          "create" => {
            let target_env = ($ops | get -o 1 | default "")
            if ($target_env | is-empty) {
              print "Usage: env create <environment>"
              exit 1
            }
            env create $target_env
          }
          "delete" => {
            let target_env = ($ops | get -o 1 | default "")
            if ($target_env | is-empty) {
              print "Usage: env delete <environment>"
              exit 1
            }
            env delete $target_env
          }
          "export" => {
            let target_env = ($ops | get -o 1 | default "")
            env export $target_env
          }
          "status" => {
            let target_env = ($ops | get -o 1 | default "")
            env status $target_env
          }
          _ => {
            print "Environment Management Commands:"
            print "  env list              - List available environments"
            print "  env current           - Show current environment"
            print "  env switch <env>      - Switch to environment"
            print "  env validate [env]    - Validate environment"
            print "  env compare <e1> <e2> - Compare environments"
            print "  env show [env]        - Show environment config"
            print "  env init <env>        - Initialize environment"
            print "  env detect            - Detect current environment"
            print "  env set <env>         - Set environment variable"
            print "  env paths [env]       - Show environment paths"
            print "  env create <env>      - Create new environment"
            print "  env delete <env>      - Delete environment"
            print "  env export [env]      - Export environment config"
            print "  env status [env]      - Show environment status"
          }
        }
      } else {
        # Fall back to legacy environment display
        match $out {
          "json" => { _print (show_env | to json) "json" "result" "table" },
          "yaml" => { _print (show_env | to yaml) "yaml" "result" "table" },
          "toml" => { _print (show_env | to toml) "toml" "result" "table" },
          _     => { print (show_env | table -e) } ,
        }
      }
    },
    "allenv" => {
      let all_env = {
        env: (show_env),
        providers: (on_list "providers" "-" ""),
        taskservs: (on_list "taskservs" "-" ""),
        clusters: (on_list "clusters" "-" ""),
        infras: (on_list "infras" "-" ""),
        itemdefs: {
          providers: (find_provgendefs),
          taskserv: (
            open ($env.PROVISIONING_TASKSERVS_PATH | path join $env.PROVISIONING_GENERATE_DIRPATH | path join $env.PROVISIONING_GENERATE_DEFSFILE)
          )
        }
      }
      if ($view) {
        match $out {
          "json" => ($all_env | to json | highlight),
          "yaml" => ($all_env | to yaml | highlight),
          "toml" => ($all_env | to toml | highlight),
          _      => ($all_env | to json | highlight),
        }
      } else {
        match $out {
          "json" => { _print ($all_env | to json) "json" "result" "table" },
          "yaml" => { _print ($all_env | to yaml) "yaml" "result" "table" },
          "toml" => { _print ($all_env | to toml) "toml" "result" "table" },
          _      => { print ($all_env | to json) } ,
        }
      }
    },
    "show" => {
      match ($ops | get -o 0 | default "") {
        "h" |"help" => {
          print (provisioning_show_options)
          exit
        },
      }
      let curr_settings = (find_get_settings --infra $infra --settings $settings $include_notuse)
      if ($curr_settings | is-empty) {
        if ($out | is-empty) {
          _print $"🛑 Errors found in infra (_ansi yellow_bold)($infra)(_ansi reset) notuse ($include_notuse)"
          print ($curr_settings | describe)
          print $settings
        }
        exit
      }
      let show_info = (get_show_info $ops $curr_settings ($out | default ""))
      if ($view) {
        match $out {
          "json" => { print ($show_info | to json | highlight json) },
          "yaml" => { print ($show_info | to yaml | highlight yaml) },
          "toml" => { print ($show_info | to toml | highlight toml) },
          _      => { print ($show_info | to json | highlight) },
        }
      } else {
        match $out {
          "json" => { _print ($show_info | to json) "json" "result" "table" },
          "yaml" => { _print ($show_info | to yaml) "yaml" "result" "table" },
          "toml" => { _print ($show_info | to toml) "toml" "result" "table" },
          _      => { print ($show_info | to json) } ,
        }
      }
    },
    "c" | "create" => {
      let use_debug = if $debug or $env.PROVISIONING_DEBUG { "-x"} else { "" }
      let use_check = if $check { "--check "} else { "" }
      let str_infra = if $infra != null  { $"--infra ($infra) "} else { "" }
      let str_out = if $outfile != null  { $"--outfile ($outfile) "} else { "" }
      exec $"($env.PROVISIONING_NAME)" $use_debug "create" $str_ops  $use_check $str_infra $str_out --notitles
    },
    "d" | "delete" => {
      let use_debug = if $debug { "-x"} else { "" }
      let use_check = if $check { "--check "} else { "" }
      let use_yes = if $yes { "--yes "} else { "" }
      let use_keepstorage = if $keepstorage { "--keepstorage "} else { "" }
      let str_infra = if $infra != null  { $"--infra ($infra) "} else { "" }
      exec $"($env.PROVISIONING_NAME)" "delete" $str_ops $use_check $use_yes $use_keepstorage $str_infra --notitles
    },
    "u" | "update" => {
      let use_debug = if $debug { "-x"} else { "" }
      let use_check = if $check { "--check "} else { "" }
      let str_infra = if $infra != null  { $"--infra ($infra) "} else { "" }
      exec $"($env.PROVISIONING_NAME)" "update" $str_ops $use_check $str_infra --notitles
    },
    "cst" | "create-server-task" | "csts" | "create-servers-tasks" => {
      run_module $str_ops "server" "create"
      if $env.LAST_EXIT_CODE != 0 {
        _print $"🛑 Errors found in (_ansi yellow_bold)create-server(_ansi reset)"
        exit 1
      }
      run_module $"- ($str_ops)" "taskserv" "create"
    },
    "s" | "server" => {
      let use_check = if $check { "--check "} else { "" }
      let use_yes = if $yes { "--yes" } else { "" }
      let use_wait = if $wait { "--wait" } else { "" }
      let use_keepstorage = if $keepstorage { "--keepstorage "} else { "" }
      let str_infra = if $infra != null  { $"--infra ($infra) "} else { "" }
      let str_outfile = if $outfile != null  { $"--outfile ($outfile) "} else { "" }
      let str_out = if $out != null  { $"--out ($out) "} else { "" }
      let arg_include_notuse = if $include_notuse { $"--include_notuse "} else { "" }
      run_module $"($str_ops) ($str_infra) ($use_check) ($str_out) ($str_outfile) ($use_yes) ($use_wait) ($use_keepstorage) ($arg_include_notuse)" "server" --exec
    },
    "price" | "prices" | "cost" | "costs" => {
      let use_check = if $check { "--check "} else { "" }
      let str_infra = if $infra != null  { $"--infra ($infra) "} else { "" }
      let str_out = if $outfile != null  { $"--outfile ($outfile) "} else { "" }
      run_module $"($str_ops) ($str_infra) ($use_check) ($str_out)" "server" "price" --exec
    },
    "t" | "task" | "taskserv" => {
      let use_check = if $check { "--check "} else { "" }
      let str_infra = if $infra != null  { $"--infra ($infra) "} else { "" }
      run_module $"($str_ops) ($str_infra) ($use_check)" "taskserv" --exec
    },
    "cl" | "cluster" => {
      let use_check = if $check { "--check "} else { "" }
      let str_infra = if $infra != null  { $"--infra ($infra) "} else { "" }
      run_module $"($str_ops) ($str_infra) ($use_check)" "cluster" --exec
    },
    "g" | "gen" | "generate" => {
      match ($ops | get -o 0 | default "") {
        "h" |"help" => {
          print (provisioning_generate_options)
          exit
        },
      }
      let str_infra = if $infra != null  { $"--infra ($infra) "} else { "" }
      let use_debug = if $debug { "-x"} else { "" }
      let use_check = if $check { "--check "} else { "" }
      let str_out = if $outfile != null  { $"--outfile ($outfile) "} else { "" }
      let str_input = if $inputfile != null  { $"--inputfile ($inputfile) "} else { "" }
      let str_template = if ($template != null) { $"--template ($template)" } else { "" }
      let str_select = if ($select != null) { $"--select ($select)" } else { "" }
      if ($str_ops | is-empty) {
        exec $"($env.PROVISIONING_NAME)" $use_debug "generate" $str_ops  $use_check $str_infra $str_out --notitles
      } else {
        let target = ($ops | get -o 0)
        let gen_ops = ($ops | skip 1 | str join " ") + $" ($str_infra) ($str_template) ($str_out) ($use_check) ($use_debug) ($str_select) ($str_input)"
        match $target {
          "s" | "server" => { run_module $"- ($gen_ops)" "server" "generate" --exec },
          "t" | "task" | "taskserv" => { run_module $"- ($gen_ops)" "taskserv" "generate" --exec },
          "i" | "infra" | "infras" => { run_module $"- ($gen_ops)" "infra" "generate" --exec },
          "cl" | "cluster" => { run_module $"- ($gen_ops)" "cluster" "generate" --exec },
          "h" | "help" => {
            _print $"\n(provisioning_generate_options)"
            exit
          },
          "new" => {
            exec $"($env.PROVISIONING_NAME)" $use_debug "generate" "new" $gen_ops $str_template $use_check $str_infra $str_out --notitles
          },
          "_" =>  {
            invalid_task "" $target --end
            exit
          }
        }
      }
      print $"($str_ops) ($str_infra)"
      #generate
    },
    "ctx" | "context" => {
      ^$"($env.PROVISIONING_NAME)" "context" $str_ops --notitles
      run_module  $str_ops "" --exec
    },
    "setup" | "st" | "config" => {
      run_module $str_ops "setup" --exec
    },
    "init" => {
      # Initialize user configuration
      match ($ops | get -o 0 | default "") {
        "config" => {
          # Initialize user config with template selection
          use lib_provisioning/config/loader.nu init-user-config

          let template_type = ($ops | get -o 1 | default "user")
          let force_flag = ($ops | any {|op| $op == "--force" or $op == "-f"})

          print "🚀 Initializing user configuration"
          print "=================================="
          print ""

          init-user-config --template $template_type --force $force_flag
        }
        "help" | "h" => {
          print "📋 Init Command Help"
          print "===================="
          print ""
          print "Initialize user configuration from templates:"
          print ""
          print "Commands:"
          print "  init config [template] [--force]  Initialize user config"
          print ""
          print "Templates:"
          print "  user    General user configuration (default)"
          print "  dev     Development environment optimized"
          print "  prod    Production environment optimized"
          print "  test    Testing environment optimized"
          print ""
          print "Options:"
          print "  --force, -f    Overwrite existing configuration"
          print ""
          print "Examples:"
          print "  provisioning init config"
          print "  provisioning init config dev"
          print "  provisioning init config prod --force"
        }
        _ => {
          print "❌ Unknown init command. Use 'provisioning init help' for available options."
        }
      }
    },
    "template" => {
      # Template management commands
      match ($ops | get -o 0 | default "") {
        "list" => {
          print "📋 Available Configuration Templates"
          print "==================================="
          print ""

          let project_root = $env.PWD
          let templates = [
            { name: "user", file: "config.user.toml.example", description: "General user configuration with comprehensive documentation" }
            { name: "dev", file: "config.dev.toml.example", description: "Development environment with enhanced debugging" }
            { name: "prod", file: "config.prod.toml.example", description: "Production environment with security and performance focus" }
            { name: "test", file: "config.test.toml.example", description: "Testing environment with mock providers and CI/CD integration" }
          ]

          for template in $templates {
            let template_path = ($project_root | path join $template.file)
            let status = if ($template_path | path exists) { "✅" } else { "❌" }
            print $"($status) ($template.name) - ($template.description)"
            if ($template_path | path exists) {
              print $"   📁 ($template_path)"
            } else {
              print $"   ❌ Template file not found: ($template_path)"
            }
            print ""
          }

          print "💡 Usage: provisioning init config [template_name]"
        }
        "show" => {
          # Show template content
          let template_name = ($ops | get -o 1 | default "")
          if ($template_name | is-empty) {
            print "❌ Please specify a template name. Use 'provisioning template list' to see available templates."
            return
          }

          let template_file = match $template_name {
            "user" => "config.user.toml.example"
            "dev" => "config.dev.toml.example"
            "prod" => "config.prod.toml.example"
            "test" => "config.test.toml.example"
            _ => {
              print $"❌ Unknown template: ($template_name). Valid options: user, dev, prod, test"
              return
            }
          }

          let project_root = $env.PWD
          let template_path = ($project_root | path join $template_file)

          if not ($template_path | path exists) {
            print $"❌ Template file not found: ($template_path)"
            return
          }

          print $"📄 Template: ($template_name)"
          print $"📁 Path: ($template_path)"
          print "=" * 80
          print ""

          # Show template content using configured file viewer
          let file_viewer = ($env.PROVISIONING_FILE_VIEWER? | default "less")
          ^$file_viewer $template_path
        }
        "validate" => {
          # Validate all templates
          print "🔍 Validating Configuration Templates"
          print "====================================="
          print ""

          let project_root = $env.PWD
          let templates = ["config.user.toml.example", "config.dev.toml.example", "config.prod.toml.example", "config.test.toml.example"]
          mut all_valid = true

          for template in $templates {
            let template_path = ($project_root | path join $template)
            print $"🔍 Validating ($template)..."

            if not ($template_path | path exists) {
              print $"   ❌ File not found: ($template_path)"
              $all_valid = false
              continue
            }

            # Basic TOML syntax validation and section checking
            print "   ✅ TOML syntax assumed valid (template file)"
            let config_data = (open $template_path)

            # Check if config_data is a record (properly parsed TOML)
            if (($config_data | describe) == "record") {
              let required_sections = ["core", "paths", "debug", "output"]
              for section in $required_sections {
                if ($config_data | get -o $section | is-not-empty) {
                  print $"   ✅ Required section present: ($section)"
                } else {
                  print $"   ⚠️  Section missing or empty: ($section)"
                }
              }
            } else {
              print "   ⚠️  Template contains only comments/documentation (no active config sections)"
            }
            print ""
          }

          if $all_valid {
            print "✅ All templates validated successfully!"
          } else {
            print "❌ Some templates have validation issues"
          }
        }
        "help" | "h" => {
          print "📋 Template Command Help"
          print "========================"
          print ""
          print "Manage configuration templates:"
          print ""
          print "Commands:"
          print "  template list               List available templates"
          print "  template show <name>        Show template content"
          print "  template validate           Validate all templates"
          print ""
          print "Examples:"
          print "  provisioning template list"
          print "  provisioning template show dev"
          print "  provisioning template validate"
        }
        _ => {
          print "❌ Unknown template command. Use 'provisioning template help' for available options."
        }
      }
    },
    "i" | "infra" | "infras" => {
      if ($str_ops | str contains "help") or $str_ops == "h" {
        run_module "help"  "infra"
        exit -2
      }
      let infra_ops = if ($infra | is-not-empty) { $"-i ($infra)"
      } else if $infras != null {
          $"--infras ($infras)"
      } else {
        $"-i (get_infra | path basename)"
      }
      let use_yes = if $yes { "--yes"} else { "" }
      let use_check = if $check { "--check"} else { "" }
      let use_onsel = if $onsel != null { $"--onsel ($onsel)"} else { "" }
      run_module $"($str_ops) ($infra_ops) ($use_check) ($use_onsel) ($use_yes)" "infra"
    },
    "deploy-rm" | "deploy-del" | "dp-rm" | "d-r" | "destroy"   => {
      let curr_settings = (find_get_settings --infra $infra --settings $settings)
      deploy_remove $curr_settings ($str_ops |  split row "-" | get -o 0 | default "")
      rm -rf $curr_settings.wk_path
      if  $task == "destroy" {
        let with_yes = if $yes { "--yes" } else { "" }
        exec $"($env.PROVISIONING_NAME)" "delete" server --notitles $with_yes
      }
    },
    "deploy-sel" | "deploy-list" | "dp-sel" | "d-s" => {
      let curr_settings = (find_get_settings --infra $infra --settings $settings)
      deploy_list $curr_settings ($str_ops |  split row "-" | get -o 0 | default "")  ($onsel | default "")
      rm -rf $curr_settings.wk_path
    },
    "deploy-sel-tree" | "deploy-list-tree" | "dp-sel-t" | "d-st" => {
      let curr_settings = (find_get_settings --infra $infra --settings $settings)
      (deploy_list $curr_settings $str_ops "tree")
      rm -rf $curr_settings.wk_path
    },
    "nu" => {
      let run_ops = if ($str_ops | str trim | str starts-with "-") {
        ""
      } else {
        ($ops | get -o 0)
      }
      if ($infra | is-not-empty) and ($env.PROVISIONING_INFRA_PATH | path join $infra |path exists) {
        cd ($env.PROVISIONING_INFRA_PATH | path join $infra)
      }
      if ($env.PROVISIONING_OUT | is-empty)  {
        if ($run_ops | is-empty)  {
          print (
            $"\nTo exit (_ansi purple_bold)NuShell(_ansi reset) session, with (_ansi default_dimmed)lib_provisioning(_ansi reset) loaded, " +
            $"use (_ansi green_bold)exit(_ansi reset) or (_ansi green_bold)[CTRL-D](_ansi reset)"
          )
          ^nu -i  -e $"use lib_provisioning * ; use env.nu * ; show_titles;"
          #^nu -e $"use lib_provisioning * ; show_titles; $env.PROMPT_INDICATOR = {|| 'provisioning> ' } ; $env.PROMPT_COMMAND = {|| create_left_prompt } "
        } else {
          ^nu -c $"($run_ops)"
        }
      }
    },
    "list" | "l" | "ls" => {
      #use defs/lists.nu on_list
      let target_list = if ($args | length) > -1 { ($args| get -o 1 | default "") } else { "" }
      let list_ops = ($ops | str join " " | str replace $"($target_list) " "" | str trim)
      on_list $target_list ($onsel | default "") $list_ops
    },
    "qr" => {
      #use utils/qr.nu *
      make_qr
    },
    "nuinfo" => {
      print $"\n (_ansi yellow)Nu shell info(_ansi reset)"
      print (version)
    },
    "plugin" | "plugins" => {
      print $"\n (_ansi yellow)Nu shell Plugins(_ansi reset)"
      ^nu -c "plugin list"
    },
    "new" => {
      let str_new = ($new | default "")
      print $"\n (_ansi yellow)New Infra ($str_new)(_ansi reset)"
    },
    "ai" => {
      # AI command module
      let str_infra = if $infra != null { $"--infra ($infra) " } else { "" }
      let str_settings = if $settings != null { $"--settings ($settings) " } else { "" }
      let str_out = if $out != null { $"--out ($out) " } else { "" }
      run_module $"($str_ops) ($str_infra) ($str_settings) ($str_out)" "ai" --exec
    },
    "validate" | "val" => {
      # Infrastructure validation module
      let sub_command = ($ops | get -o 0 | default "")

      match $sub_command {
        "help" | "h" => {
          use main_provisioning/ops.nu *
          print (provisioning_validate_options)
        }
        "config" => {
          # Configuration validation
          print "🔍 Configuration Validation"
          print "=========================="
          print ""

          # Load configuration using the config loader
          use lib_provisioning/config/loader.nu *

          let config_result = (load-provisioning-config --debug $debug --validate false)

          # Run detailed validation
          let strict_mode = (($ops | get -o 1 | default "") == "strict")
          let validation_result = (validate-config $config_result --detailed true --strict $strict_mode)

          print $"📊 Validation Summary:"
          print $"   • Structure valid: ($validation_result.summary.structure_valid)"
          print $"   • Paths valid: ($validation_result.summary.paths_valid)"
          print $"   • Types valid: ($validation_result.summary.types_valid)"
          print $"   • Semantic rules valid: ($validation_result.summary.semantic_valid)"
          print $"   • File references valid: ($validation_result.summary.files_valid)"
          print ""

          if ($validation_result.errors | length) > 0 {
            print "❌ Errors found:"
            for error in $validation_result.errors {
              print $"   • [($error.severity | str upcase)] ($error.message)"
            }
            print ""
          }

          if ($validation_result.warnings | length) > 0 {
            print "⚠️  Warnings found:"
            for warning in $validation_result.warnings {
              print $"   • [($warning.severity | str upcase)] ($warning.message)"
            }
            print ""
          }

          if $validation_result.valid {
            print "✅ Configuration validation passed!"
            print ""
            print "   All configuration checks completed successfully."
            print "   Configuration is ready for use."
            exit 0
          } else {
            print "❌ Configuration validation failed!"
            print ""
            print "   Please fix the errors above before proceeding."
            exit 1
          }
        }
        "interpolation" | "interp" => {
          # Enhanced interpolation validation and testing
          use lib_provisioning/config/loader.nu *

          let interp_command = ($ops | get -o 1 | default "test")

          match $interp_command {
            "test" => {
              # Test interpolation with sample data
              let sample_type = ($ops | get -o 2 | default "basic")
              test-interpolation --sample $sample_type
            }
            "validate" => {
              # Validate interpolation patterns in current config
              print "🔍 Interpolation Pattern Validation"
              print "==================================="
              print ""

              let config_result = (load-provisioning-config --debug $debug --validate false)
              let validation_result = (validate-interpolation $config_result --detailed true)

              if $validation_result.valid {
                print "✅ Interpolation validation passed!"
                print $"   • ($validation_result.summary.interpolation_patterns_detected) patterns processed"
              } else {
                print "❌ Interpolation validation failed!"
                for error in $validation_result.errors {
                  print $"   • [ERROR] ($error.message)"
                }
              }

              if ($validation_result.warnings | length) > 0 {
                print ""
                print "⚠️  Warnings:"
                for warning in $validation_result.warnings {
                  print $"   • [WARNING] ($warning.message)"
                }
              }

              print ""
              print $"📊 Summary: ($validation_result.summary.total_errors) errors, ($validation_result.summary.total_warnings) warnings"
            }
            "testsuite" | "suite" => {
              # Run comprehensive interpolation test suite
              print "🧪 Running Comprehensive Interpolation Test Suite"
              print "================================================="
              print ""

              let output_file = ($ops | get -o 2 | default "interpolation_test_results.json")
              let suite_results = (create-interpolation-test-suite --output-file $output_file)

              print ""
              print "🎯 Test Suite Results:"
              print $"   Success rate: ($suite_results.success_rate)%"
              print $"   Total tests: ($suite_results.total)"
              print $"   Passed: ($suite_results.passed)"
              print $"   Failed: ($suite_results.failed)"

              if $suite_results.failed > 0 {
                exit 1
              }
            }
            "show" => {
              # Show interpolation patterns and results
              let mode = ($ops | get -o 2 | default "interpolated")

              print "📋 Configuration Interpolation View"
              print "===================================="
              print ""

              let config_result = (load-provisioning-config --debug $debug --validate false)

              match $mode {
                "raw" => {
                  print "🔍 Raw configuration (before interpolation):"
                  print ""
                  # Load config without interpolation
                  let raw_config = (load-provisioning-config --debug $debug --validate false)
                  print ($raw_config | to json)
                }
                "interpolated" => {
                  print "✨ Interpolated configuration:"
                  print ""
                  print ($config_result | to json)
                }
                "patterns" => {
                  print "🔍 Detected interpolation patterns:"
                  print ""
                  # Convert to JSON and find all patterns
                  let json_str = ($config_result | to json)
                  # Simple pattern detection
                  if ($json_str | str contains "{{") {
                    print "   Found interpolation patterns in configuration"
                    # This is a simplified implementation
                    let pattern_count = (count-interpolation-patterns $json_str)
                    print $"   Total patterns: ($pattern_count)"
                  } else {
                    print "   No interpolation patterns found"
                  }
                }
                _ => {
                  print "❌ Unknown show mode. Valid options: raw, interpolated, patterns"
                }
              }
            }
            "help" | "h" => {
              print "📋 Interpolation Command Help"
              print "=============================="
              print ""
              print "Enhanced interpolation features for advanced configuration templating:"
              print ""
              print "Commands:"
              print "  validate interpolation test [sample]     Test interpolation with sample data"
              print "  validate interpolation validate          Validate interpolation patterns"
              print "  validate interpolation show [mode]       Show interpolation results"
              print "  validate interpolation testsuite [file]  Run comprehensive test suite"
              print ""
              print "Sample Types:"
              print "  basic      Basic interpolation patterns ({{paths.base}}, {{env.HOME}})"
              print "  advanced   Advanced patterns (git info, providers, conditionals)"
              print "  all        All interpolation features"
              print ""
              print "Show Modes:"
              print "  raw            Show configuration before interpolation"
              print "  interpolated   Show configuration after interpolation (default)"
              print "  patterns       Show detected interpolation patterns"
              print ""
              print "Supported Interpolation Patterns:"
              print "  {{paths.base}}                   Base path interpolation"
              print "  {{env.HOME}}, {{env.USER}}       Environment variables"
              print "  {{now.date}}, {{now.timestamp}}  Date/time values"
              print "  {{git.branch}}, {{git.commit}}   Git repository information"
              print "  {{sops.key_file}}                SOPS configuration"
              print "  {{providers.aws.region}}         Cross-section references"
              print "  {{path.join(paths.base, \"dir\")}} Function calls"
              print "  {{env.HOME || \"/tmp\"}}          Conditional expressions"
              print ""
              print "Examples:"
              print "  provisioning validate interpolation test basic"
              print "  provisioning validate interpolation validate"
              print "  provisioning validate interpolation show raw"
              print "  provisioning validate interpolation testsuite"
            }
            _ => {
              print "❌ Unknown interpolation command. Use 'provisioning validate interpolation help' for options."
            }
          }
        }
        "test" => {
          # Run the test script directly
          nu test_validation.nu
        }
        "quick" => {
          let target_path = if $infra != null { $infra } else {
            let next_arg = ($ops | get -o 1 | default ".")
            if ($next_arg | path exists) { $next_arg } else { "." }
          }

          print "🚀 Quick Infrastructure Validation"
          print "=================================="
          print ""
          print $"📁 Target: ($target_path | path expand)"
          print ""
          print "🔄 Running quick validation (errors and critical issues only)..."
          print ""

          let result = (nu test_validation.nu | complete)

          if $result.exit_code == 0 {
            print "✅ Quick validation passed!"
            print ""
            print "   No critical errors or blocking issues found."
            print $"   Infrastructure ($target_path) is ready for deployment."
          } else {
            print "❌ Quick validation found issues"
            print ""
            print "   Please review and fix critical/error-level issues before deployment."
          }
          print ""
        }
        "rules" => {
          # Show rules list
          print "📋 Available Validation Rules"
          print "============================"
          print ""
          print "🔧 👁️ VAL001: 🚨 YAML Syntax Validation (critical)"
          print "   Category: syntax | Severity: critical | Auto-fix: false"
          print ""
          print "🔧 👁️ VAL002: 🚨 KCL Compilation Check (critical)"
          print "   Category: compilation | Severity: critical | Auto-fix: false"
          print ""
          print "🔧 ✅ VAL003: ❌ Unquoted Variable References (error)"
          print "   Category: syntax | Severity: error | Auto-fix: true"
          print ""
          print "🔧 👁️ VAL004: ❌ Required Fields Validation (error)"
          print "   Category: schema | Severity: error | Auto-fix: false"
          print ""
          print "🔧 ✅ VAL005: ⚠️ Resource Naming Conventions (warning)"
          print "   Category: best_practices | Severity: warning | Auto-fix: true"
          print ""
          print "🔧 👁️ VAL006: ❌ Basic Security Checks (error)"
          print "   Category: security | Severity: error | Auto-fix: false"
          print ""
          print "🔧 👁️ VAL007: ⚠️ Version Compatibility Check (warning)"
          print "   Category: compatibility | Severity: warning | Auto-fix: false"
          print ""
          print "🔧 👁️ VAL008: ❌ Network Configuration Validation (error)"
          print "   Category: networking | Severity: error | Auto-fix: false"
          print ""
          print "Legend:"
          print "✅ = Auto-fixable | 👁️ = Manual fix required"
          print "🚨 = Critical | ❌ = Error | ⚠️ = Warning | ℹ️ = Info"
        }
        _ => {
          # Execute actual validation
          let target_path = if $infra != null {
            $infra
          } else if ($sub_command | path exists) {
            $sub_command
          } else {
            # Use current directory if it contains infrastructure files
            # Check for common infrastructure indicators: settings.k, kcl.mod, or .k files
            let current_dir = "."
            let has_settings = ($current_dir | path join "settings.k" | path exists)
            let has_kcl_mod = ($current_dir | path join "kcl.mod" | path exists)
            let has_k_files = ((glob "*.k") | length) > 0

            if $has_settings or $has_kcl_mod or $has_k_files {
              $current_dir
            } else {
              # If no infrastructure files in current dir, show help
              use main_provisioning/ops.nu *
              print (provisioning_validate_options)
              return
            }
          }

          print "🔍 Infrastructure Validation & Review Tool"
          print "=========================================="
          print ""
          print $"📁 Validating: ($target_path | path expand)"
          print ""

          # Check if target path exists
          if not ($target_path | path exists) {
            print $"🛑 Infrastructure path not found: ($target_path)"
            print ""
            print "Use 'provisioning validate help' for usage information"
            exit 1
          }

          # Run the validation using our working test system
          print "🔄 Running infrastructure validation..."
          print ""

          # Run basic validation directly without external script dependency
          # Count and validate infrastructure files recursively
          let k_files = (glob "**/*.k")
          let yaml_files = (glob "**/*.yaml" | append (glob "**/*.yml"))
          let toml_files = (glob "**/*.toml")

          let total_files = ($k_files | length) + ($yaml_files | length) + ($toml_files | length)

          print $"📊 Found ($total_files) infrastructure files:"
          print $"   • KCL files: ($k_files | length)"
          print $"   • YAML files: ($yaml_files | length)"
          print $"   • TOML files: ($toml_files | length)"
          print ""

          # Simple validation checks
          mut issues = []

          # Check for settings.k file
          if ("settings.k" | path exists) {
            print "✅ settings.k file found"
          } else {
            print "⚠️  No settings.k file found"
            $issues = ($issues | append "Missing settings.k file")
          }

          # Basic KCL syntax check for each .k file
          for file in $k_files {
            print $"🔍 Checking KCL file: ($file)"

            # Check if file is SOPS encrypted
            let content = (open $file --raw)
            let is_sops_file = ($content | str contains "\"sops\":") or ($content | str contains "ENC[AES256_GCM")

            if $is_sops_file {
              # Handle SOPS encrypted file
              print $"   🔐 ($file) - SOPS encrypted file detected"

              # Set up SOPS environment using the config-driven approach
              $env.PROVISIONING_USE_SOPS = ($env.PROVISIONING_USE_SOPS? | default "age")
              $env.PROVISIONING_SOPS = ($env.PROVISIONING_SOPS? | default "")

              use lib_provisioning/sops/lib.nu get_def_age
              let kage_path = (get_def_age $env.PROVISIONING_KLOUD_PATH)
              if ($kage_path | is-not-empty) and ($kage_path | path exists) {
                $env.SOPS_AGE_KEY_FILE = $kage_path
              }

              # Check if SOPS can decrypt it
              let sops_check = (^sops -d $file | complete)
              if $sops_check.exit_code == 0 {
                # Try to validate the decrypted content
                let kcl_check = (^sops -d $file | ^kcl - | complete)
                if $kcl_check.exit_code == 0 {
                  print $"   ✅ ($file) - SOPS encrypted KCL syntax OK"
                } else {
                  print $"   ❌ ($file) - SOPS encrypted KCL syntax error"
                  $issues = ($issues | append $"KCL syntax error in SOPS file ($file)")
                }
              } else {
                print $"   ⚠️  ($file) - SOPS decryption failed - check keys/config"
                print $"       Skipping validation (SOPS error: ($sops_check.stderr | str trim))"
                # Don't add to issues - this might be expected if keys aren't available
              }
            } else {
              # Regular KCL file validation
              let check_result = (^kcl $file | complete)
              if $check_result.exit_code == 0 {
                print $"   ✅ ($file) - KCL syntax OK"
              } else {
                print $"   ❌ ($file) - KCL syntax error"
                $issues = ($issues | append $"KCL syntax error in ($file)")
              }
            }
          }

          # Basic YAML syntax check
          for file in $yaml_files {
            print $"🔍 Checking YAML file: ($file)"
            let yaml_result = (^yq eval . $file | complete)
            if $yaml_result.exit_code == 0 {
              print $"   ✅ ($file) - YAML syntax OK"
            } else {
              print $"   ❌ ($file) - YAML syntax error"
              $issues = ($issues | append $"YAML syntax error in ($file)")
            }
          }

          let result = {
            exit_code: (if ($issues | length) > 0 { 1 } else { 0 })
            issues: $issues
          }

          print ""

          if $result.exit_code == 0 {
            print "✅ Validation completed successfully!"
            print ""
            print "📊 Summary:"
            print "   • No critical issues found"
            print "   • All infrastructure files are valid"
            print "   • Infrastructure is ready for deployment"
            print ""
            print $"📁 Files processed in: ($target_path | path expand)"
            print ""
            print "💡 For detailed validation options, use:"
            print "   provisioning validate help"
          } else {
            print "❌ Validation found issues"
            print ""
            print "🔍 Issues found:"
            for issue in $result.issues {
              print $"   • ($issue)"
            }
            print ""
            print "💡 Please fix these issues before deployment"
            print "   Use 'provisioning validate help' for more options"
          }
        }
      }
    },
    _ => {
      invalid_task "" $task --end
      exit
    },
  }
  if not $env.PROVISIONING_DEBUG { end_run "" }
  #print $"($env.PWD)\n($env.FILE_PWD)\n($env.PROCESS_PATH)\n"
}
export def get_show_info [
  ops: list
  curr_settings: record
  out: string
]: nothing -> record  {
  match ($ops | get -o 0 | default "") {
    "set" |"setting" | "settings" => $curr_settings,
    "def" | "defs" |"defsetting" | "defsettings" => {
      let src = ($curr_settings | get -o src | default "");
      let src_path = ($curr_settings | get -o src_path | default "");
      let def_settings = if ($src_path | path join $src | path exists) {
        open -r ($src_path | path join $src)
      } else { "" }
      let main_path = ($env.PROVISIONING | path join "kcl" | path join "settings.k")
      let src_main_settings = if ($main_path | path exists) {
        open -r $main_path
      } else { "" }
      {
        def: $src,
        def_path: $src_path,
        infra: ($curr_settings | get -o infra | default ""),
        infra_path: ($curr_settings | get -o infra_path | default ""),
        def_settings: $def_settings,
        main_path: $main_path,
        main_settings: $src_main_settings,
      }
    },
    "server" |"servers" | "s" => {
      let servers = ($curr_settings | get -o data | get -o servers |  default {})
      let item = ($ops | get -o 1 | default "")
      if ($item | is-empty) {
        $servers
      } else {
        let server = (find_server $item $servers ($out | default ""))
        let def_target = ($ops | get -o 2 | default "")
        match $def_target {
          "t" | "task" | "taskserv" => {
            let task = ($ops | get -o 3 | default "")
            (find_taskserv $curr_settings $server $task ($out | default ""))
          },
          _ => $server,
        }
      }
    },
    "serverdefs" |"serversdefs" | "sd" => {
      (find_serversdefs $curr_settings)
    },
    "provgendefs" |"provgendef" | "pgd" => {
      (find_provgendefs)
    },
    "taskservs" |"taskservs" | "ts" => {
      #(list_taskservs $curr_settings)
      let list_taskservs = (taskservs_list)
      if ($list_taskservs | length) == 0 {
          _print $"🛑 no items found for (_ansi cyan)taskservs list(_ansi reset)"
          return
      }
      $list_taskservs
    },
    "taskservsgendefs" |"taskservsgendef" | "tsd" => {
      let defs_path = ($env.PROVISIONING_TASKSERVS_PATH | path join $env.PROVISIONING_GENERATE_DIRPATH | path join $env.PROVISIONING_GENERATE_DEFSFILE)
      if ($defs_path | path exists) {
        open $defs_path
      }
    },
    "cost" | "costs" | "c" | "price" | "prices" | "p" => {
      (servers_walk_by_costs $curr_settings "" false false "stdout")
    },
    "alldata" => ($curr_settings | get -o data | default {}
       | merge { costs: (servers_walk_by_costs $curr_settings "" false false "stdout") }
    ),
    "data" | _ => {
      if ($out | is-not-empty) {
        ($curr_settings | get -o data | default {})
      } else {
          print ($" (_ansi cyan_bold)($curr_settings | get -o data | get -o main_name | default '')"
            + $"(_ansi reset): (_ansi yellow_bold)($curr_settings | get -o data | get -o main_title | default '') (_ansi reset)"
          )
          print ($curr_settings | get -o data | default {} | merge { servers: ''})
          ($curr_settings | get -o data | default {} | get -o servers | each {|item|
              print $"\n server:  (_ansi cyan_bold)($item.hostname | default '') (_ansi reset)"
              print $item
          })
          ""
      }
    },
  }
}
