#!/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
  -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 }
  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" => {
      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
    },
    "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)
        }
        "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
          })
          ""
      }
    },
  }
}
