#!/usr/bin/env nu
# Info: Script to run Provisioning Layer System Management
# Author: JesusPerezLorenzo
# Release: 1.0.0
# Date: 29-09-2025

use std log

use lib_provisioning *
use env.nu *

# - > Help on Layer
export def "main help" [
  --src: string = ""
  --notitles       # not titles
  --out: string    # Print Output format: json, yaml, text (default)
]: nothing -> nothing {
  if $notitles == null or not $notitles { show_titles }
  ^$"($env.PROVISIONING_NAME)" -mod layer --help
  if ($out | is-not-empty) { $env.PROVISIONING_NO_TERMINAL = false }
  print (provisioning_options $src)
  if not $env.PROVISIONING_DEBUG { end_run "" }
}

# > Layer System Management
def main [
  ...args: string  # Other options, use help to get info
  -v               # Show version
  -i               # Show Info
  --version (-V)   # Show version with title
  --info (-I)      # Show Info with title
  --about (-a)     # Show About
  --workspace: string = ""  # Workspace/infrastructure name for layer resolution
  --module: string = ""     # Module name to show layer information
  --provider: string = ""   # Provider name for layer testing
  --debug (-x)     # Use Debug mode
  --xm             # Debug with PROVISIONING_METADATA
  --xld            # Log level with DEBUG PROVISIONING_LOG_LEVEL=debug
  --metadata       # Error with metadata (-xm)
  --notitles       # Do not show banner titles
  --helpinfo (-h)  # For more details use options "help" (no dashes)
  --out: string    # Print Output format: json, yaml, text (default)
]: nothing -> nothing {
  if ($out | is-not-empty) {
    $env.PROVISIONING_OUT = $out
    $env.PROVISIONING_NO_TERMINAL = true
  }
  provisioning_init $helpinfo "layer" $args
  if $version or $v { ^$env.PROVISIONING_NAME -v ; exit }
  if $info or $i { ^$env.PROVISIONING_NAME -i ; exit }
  if $about {
    _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 { "" }
  let ops = if ($args | length) > 1 { ($args | skip 1 | str join " ") } else { "" }

  let workspace_name = if ($ops | is-not-empty) and not ($ops | str starts-with "-") {
    ($ops | split row " " | get 0)
  } else {
    $workspace
  }

  let module_name = if ($ops | split row " " | length) > 1 {
    ($ops | split row " " | get 1)
  } else {
    $module
  }

  $env.PROVISIONING_MODULE = "layer"

  match $task {
    "h" | "help" => {
      # Redirect to main categorized help system
      exec $"($env.PROVISIONING_NAME)" help development --notitles
    },
    "show" => {
      if ($workspace_name | is-empty) {
        layer_show_all --out $out
      } else {
        layer_show $workspace_name --module $module_name --out $out
      }
    },
    "test" => {
      if ($module_name | is-empty) or ($workspace_name | is-empty) {
        print "❌ Module name and workspace required"
        print "Usage: provisioning layer test <module> <workspace> [provider]"
        exit 1
      }
      let provider_arg = if ($ops | split row " " | length) > 2 {
        ($ops | split row " " | get 2)
      } else {
        $provider
      }
      layer_test $module_name $workspace_name $provider_arg
    },
    "explain" => {
      layer_explain --out $out
    },
    "stats" => {
      layer_stats
    },
    "validate" => {
      layer_validate
    },
    _ => {
      print $"❌ Unknown task: ($task)"
      print "Use 'provisioning layer help' for available commands"
      print ""
      print "Available commands:"
      print "  show [workspace] [--module <name>] - Show layer information"
      print "  test <module> <workspace> [provider] - Test layer resolution"
      print "  explain - Explain the layer concept"
      print "  stats - Show layer statistics"
      print "  validate - Validate layer configuration"
      exit 1
    }
  }
}

# Show layer information
def layer_show [
  workspace: string
  --module: string
  --out: string
]: nothing -> nothing {
  let provisioning_root = $env.PROVISIONING? | default $env.PWD

  if ($module | is-not-empty) {
    print $"🔍 Layer Information for Module: ($module)"
    print $"   Workspace: ($workspace)"
    print ""

    # Show layer resolution chain
    print "📋 Layer Resolution Chain (Highest to Lowest Priority):"
    print ""

    # Layer 3: Infrastructure
    print "  3️⃣  Infrastructure Layer (Priority 300)"
    print $"     Path: workspace/infra/($workspace)/"
    let workspace_root = $env.PWD
    let infra_taskserv = ($workspace_root | path join "workspace" "infra" $workspace "taskservs" $"($module).k")
    let infra_override = ($workspace_root | path join "workspace" "infra" $workspace "overrides" $"($module).k")

    if ($infra_override | path exists) {
      print $"     ✅ Override: ($infra_override)"
    } else if ($infra_taskserv | path exists) {
      print $"     ✅ Taskserv: ($infra_taskserv)"
    } else {
      print "     ❌ No infrastructure-specific configuration"
    }
    print ""

    # Layer 2: Workspace
    print "  2️⃣  Workspace Layer (Priority 200)"
    print "     Path: provisioning/workspace/templates/"
    let workspace_template = ($provisioning_root | path join "workspace" "templates" "taskservs" $module)

    if ($workspace_template | path exists) {
      print $"     ✅ Template: ($workspace_template)"
    } else {
      print "     ❌ No shared template"
    }
    print ""

    # Layer 1: Core
    print "  1️⃣  Core Layer (Priority 100)"
    print "     Path: provisioning/extensions/"

    # Check if module exists in core by checking directory structure
    let core_taskserv_path = ($provisioning_root | path join "extensions" "taskservs")
    let core_provider_path = ($provisioning_root | path join "extensions" "providers" $module)

    let core_exists = ($core_provider_path | path exists) or (
      ($core_taskserv_path | path exists) and
      (ls $core_taskserv_path | where type == dir | get name | any {|p| ($p | path basename) == $module or ($p | str contains $module)})
    )

    if $core_exists {
      print "     ✅ Base system extension found"
    } else {
      print "     ❌ No core extension"
    }
    print ""
  } else {
    print $"🏗️  Layer System Overview for: ($workspace)"
    print ""
    print "📋 Layer Resolution Order:"
    print "   (Higher priority overrides lower priority)"
    print ""
    print "  3️⃣  Infrastructure Layer (Priority 300)"
    print $"     Path: workspace/infra/($workspace)/"
    print "     Description: Infrastructure-specific configurations and overrides"
    print "     Purpose: Customize settings for this specific environment"
    print ""
    print "  2️⃣  Workspace Layer (Priority 200)"
    print "     Path: provisioning/workspace/templates/"
    print "     Description: Shared templates and reusable configurations"
    print "     Purpose: Share common patterns across infrastructures"
    print ""
    print "  1️⃣  Core Layer (Priority 100)"
    print "     Path: provisioning/extensions/"
    print "     Description: Base provisioning system extensions"
    print "     Purpose: Provide default functionality and base components"
    print ""
  }
}

# Show all layer information
def layer_show_all [--out: string]: nothing -> nothing {
  print "🏗️  Layer System Architecture"
  print ""
  print "The provisioning system uses a layered architecture for configuration inheritance:"
  print ""
  print "📋 Layer Resolution Order (Highest to Lowest Priority):"
  print ""
  print "  3️⃣  Infrastructure Layer (Priority 300)"
  print "     • Path: workspace/infra/{name}/"
  print "     • Purpose: Infrastructure-specific configurations and overrides"
  print "     • Use case: Customize settings for specific environments"
  print ""
  print "  2️⃣  Workspace Layer (Priority 200)"
  print "     • Path: provisioning/workspace/templates/"
  print "     • Purpose: Shared templates and reusable configurations"
  print "     • Use case: Share common patterns across infrastructures"
  print ""
  print "  1️⃣  Core Layer (Priority 100)"
  print "     • Path: provisioning/extensions/"
  print "     • Purpose: Base provisioning system extensions"
  print "     • Use case: Provide default functionality and base components"
  print ""
  print "💡 Usage:"
  print "   provisioning layer show <workspace> [--module <name>]"
  print "   provisioning layer test <module> <workspace> [provider]"
  print "   provisioning layer explain"
  print ""
}

# Test layer resolution
def layer_test [
  module_name: string,
  workspace: string,
  provider: string = ""
]: nothing -> nothing {
  let provisioning_root = $env.PROVISIONING? | default $env.PWD
  let layer_utils = ($provisioning_root | path join "workspace" "tools" "layer-utils.nu")

  if not ($layer_utils | path exists) {
    print $"❌ Layer utilities not found: ($layer_utils)"
    exit 1
  }

  # Call the test function from layer-utils.nu
  nu -c $"use ($layer_utils) *; test_layer_resolution '($module_name)' '($workspace)' '($provider)'"
}

# Explain layer concept
def layer_explain [--out: string]: nothing -> nothing {
  if ($out | is-not-empty) {
    let layers = [
      {
        priority: 300
        name: "Infrastructure"
        path: "workspace/infra/{name}/"
        description: "Infrastructure-specific configurations and overrides"
      }
      {
        priority: 200
        name: "Workspace"
        path: "provisioning/workspace/templates/"
        description: "Shared templates and reusable configurations"
      }
      {
        priority: 100
        name: "Core"
        path: "provisioning/extensions/"
        description: "Base provisioning system extensions"
      }
    ]

    if $out == "json" {
      print ($layers | to json)
    } else if $out == "yaml" {
      print ($layers | to yaml)
    } else {
      print ($layers | table)
    }
    return
  }

  print "🎓 Understanding the Layer System"
  print "================================="
  print ""
  print "The provisioning system uses a three-layer architecture for configuration"
  print "inheritance and override management. Each layer has a specific priority:"
  print ""
  print "🏗️  LAYER ARCHITECTURE"
  print ""
  print "┌─────────────────────────────────────────────────────────────┐"
  print "│  Layer 3: Infrastructure (Priority 300)                     │"
  print "│  ──────────────────────────────────────────                 │"
  print "│  Path: workspace/infra/{name}/                              │"
  print "│  Purpose: Environment-specific customizations               │"
  print "│  Example: workspace/infra/production/taskservs/             │"
  print "│           kubernetes.k (production-specific K8s config)     │"
  print "└─────────────────────────────────────────────────────────────┘"
  print "                          ↓ overrides ↓"
  print "┌─────────────────────────────────────────────────────────────┐"
  print "│  Layer 2: Workspace (Priority 200)                          │"
  print "│  ─────────────────────────────────                          │"
  print "│  Path: provisioning/workspace/templates/                    │"
  print "│  Purpose: Shared templates across infrastructures           │"
  print "│  Example: workspace/templates/taskservs/kubernetes/         │"
  print "│           default.k (common K8s configuration)              │"
  print "└─────────────────────────────────────────────────────────────┘"
  print "                          ↓ overrides ↓"
  print "┌─────────────────────────────────────────────────────────────┐"
  print "│  Layer 1: Core (Priority 100)                               │"
  print "│  ────────────────────────────                               │"
  print "│  Path: provisioning/extensions/                             │"
  print "│  Purpose: Base system functionality                         │"
  print "│  Example: extensions/taskservs/kubernetes/                  │"
  print "│           (base kubernetes installation logic)              │"
  print "└─────────────────────────────────────────────────────────────┘"
  print ""
  print "📖 HOW IT WORKS"
  print ""
  print "1. Resolution Order:"
  print "   When you request a module (e.g., 'kubernetes'), the system searches"
  print "   from highest to lowest priority:"
  print "   Infrastructure (300) → Workspace (200) → Core (100)"
  print ""
  print "2. Override Mechanism:"
  print "   • Infrastructure overrides Workspace and Core"
  print "   • Workspace overrides Core"
  print "   • Core provides base defaults"
  print ""
  print "3. Configuration Inheritance:"
  print "   Each layer can inherit from lower layers and override specific"
  print "   settings. This allows you to:"
  print "   • Keep common configs in Workspace"
  print "   • Customize per-environment in Infrastructure"
  print "   • Maintain base functionality in Core"
  print ""
  print "💡 PRACTICAL EXAMPLE"
  print ""
  print "Scenario: Deploying Kubernetes"
  print ""
  print "• Core Layer (100):"
  print "  Provides base kubernetes installation scripts"
  print "  Default version: 1.28.0"
  print "  Default CNI: none"
  print ""
  print "• Workspace Layer (200):"
  print "  Template with your organization's standards"
  print "  Version: 1.29.0"
  print "  CNI: Cilium"
  print "  Monitoring: Enabled"
  print ""
  print "• Infrastructure Layer (300):"
  print "  Production-specific overrides"
  print "  Version: 1.29.0 (inherited from workspace)"
  print "  CNI: Cilium (inherited from workspace)"
  print "  Monitoring: Enabled (inherited from workspace)"
  print "  High Availability: True (production-specific)"
  print "  Backup: Enabled (production-specific)"
  print ""
  print "Result: Production gets all workspace defaults plus specific overrides"
  print ""
  print "🔧 COMMANDS"
  print ""
  print "• Show layers for a workspace:"
  print "  provisioning layer show <workspace>"
  print ""
  print "• Show layers for specific module:"
  print "  provisioning layer show <workspace> --module <name>"
  print ""
  print "• Test layer resolution:"
  print "  provisioning layer test <module> <workspace> [provider]"
  print ""
  print "• Show layer statistics:"
  print "  provisioning layer stats"
  print ""
  print "• Validate layer configuration:"
  print "  provisioning layer validate"
  print ""
}

# Show layer statistics
def layer_stats []: nothing -> nothing {
  let provisioning_root = $env.PROVISIONING? | default $env.PWD
  let layer_utils = ($provisioning_root | path join "workspace" "tools" "layer-utils.nu")

  if not ($layer_utils | path exists) {
    print $"❌ Layer utilities not found: ($layer_utils)"
    exit 1
  }

  # Call the stats function from layer-utils.nu
  nu -c $"use ($layer_utils) *; show_layer_stats"
}

# Validate layer configuration
def layer_validate []: nothing -> nothing {
  let provisioning_root = $env.PROVISIONING? | default $env.PWD
  let layer_utils = ($provisioning_root | path join "workspace" "tools" "layer-utils.nu")

  if not ($layer_utils | path exists) {
    print $"❌ Layer utilities not found: ($layer_utils)"
    exit 1
  }

  # Call the validate function from layer-utils.nu
  nu -c $"use ($layer_utils) *; validate_layer_config"
}
