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

use std log

use lib_provisioning *
use env.nu *

# - > Help on Orchestrator
export def "main help" [
  --src: string = ""
  --notitles       # not titles
  --out: string    # Print Output format: json, yaml, text (default)
]: nothing -> nothing {
  print "
╭─────────────────────────────────────────────────────────────╮
│          Orchestrator Lifecycle Management                  │
╰─────────────────────────────────────────────────────────────╯

Available Commands:
  start [--background] [--provisioning-path <path>] [--port <port>]
    Start orchestrator (default: foreground, port 8080)

  stop
    Stop orchestrator

  status [--out json|yaml|text]
    Check if orchestrator is running

  health [--out json|yaml|text]
    Health check via HTTP endpoint

  migrate --to surrealdb|filesystem --yes [--check]
    Migrate storage backend

  logs [--follow] [--lines 50]
    Show orchestrator logs

Examples:
  provisioning orchestrator start --background
  provisioning orchestrator status
  provisioning orchestrator health --out json
  provisioning orchestrator migrate --to surrealdb --yes
  provisioning orchestrator logs --follow

About:
The orchestrator is a high-performance Rust coordination layer that provides:
- Task queue management with priority scheduling
- REST API for workflow submission and monitoring
- Deep call stack limitation resolution
- State persistence with multiple backend options
- Real-time workflow monitoring and health checks
"
}

# > Orchestrator Lifecycle Management
#
# The orchestrator is a high-performance Rust coordination layer that provides:
# - Task queue management with priority scheduling
# - REST API for workflow submission and monitoring
# - Deep call stack limitation resolution
# - State persistence with multiple backend options
# - Real-time workflow monitoring and health checks
#
# The orchestrator acts as the central coordination hub, receiving workflow
# requests and delegating execution to Nushell business logic scripts while
# maintaining state and providing monitoring capabilities.
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
  --background (-b)  # Run orchestrator in background
  --provisioning-path: string = ""  # Path to provisioning script
  --port: int = 8080  # HTTP server port
  --follow (-f)    # Follow logs in real-time
  --lines: int = 50  # Number of log lines to show
  --to: string     # Migration target: surrealdb or filesystem
  --check (-c)     # Only check mode, no actual changes
  --yes (-y)       # Confirm task
  --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 "orchestrator" $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 { "" }

  $env.PROVISIONING_MODULE = "orchestrator"

  match $task {
    "h" | "help" => {
      # Redirect to main categorized help system
      exec $"($env.PROVISIONING_NAME)" help orchestration --notitles
    },
    "start" => {
      print "🚀 Starting orchestrator..."
      if $background {
        orchestrator_start --background --provisioning-path $provisioning_path --port $port
      } else {
        orchestrator_start --provisioning-path $provisioning_path --port $port
      }
    },
    "stop" => {
      print "🛑 Stopping orchestrator..."
      orchestrator_stop
    },
    "status" => {
      orchestrator_status --out $out
    },
    "health" => {
      orchestrator_health --out $out
    },
    "migrate" => {
      if ($to | is-empty) {
        print "❌ Migration target required. Use --to surrealdb or --to filesystem"
        exit 1
      }
      if not $yes {
        print "⚠️  This will migrate storage backend. Use --yes to confirm."
        exit 1
      }
      print $"🔄 Migrating storage to ($to)..."
      if $check {
        orchestrator_migrate $to --check
      } else {
        orchestrator_migrate $to
      }
    },
    "logs" => {
      if $follow {
        orchestrator_logs --follow --lines $lines
      } else {
        orchestrator_logs --lines $lines
      }
    },
    _ => {
      print $"❌ Unknown task: ($task)"
      print "Use 'provisioning orchestrator help' for available commands"
      exit 1
    }
  }
}

# Start orchestrator
def orchestrator_start [
  --background
  --provisioning-path: string
  --port: int
]: nothing -> nothing {
  let provisioning_root = $env.PROVISIONING? | default "/usr/local/provisioning"
  let orchestrator_script = ($provisioning_root | path join "platform" "orchestrator" "scripts" "start-orchestrator.nu")

  if not ($orchestrator_script | path exists) {
    print $"❌ Orchestrator start script not found: ($orchestrator_script)"
    exit 1
  }

  mut flags = ["--port" ($port | into string)]

  if $background {
    $flags = ($flags | append ["--background"])
  }

  if ($provisioning_path | is-not-empty) {
    $flags = ($flags | append ["--provisioning-path" $provisioning_path])
  }

  ^nu $orchestrator_script ...$flags
}

# Stop orchestrator
def orchestrator_stop []: nothing -> nothing {
  let provisioning_root = $env.PROVISIONING? | default "/usr/local/provisioning"
  let orchestrator_script = ($provisioning_root | path join "platform" "orchestrator" "scripts" "start-orchestrator.nu")

  if not ($orchestrator_script | path exists) {
    print $"❌ Orchestrator start script not found: ($orchestrator_script)"
    exit 1
  }

  ^nu $orchestrator_script --stop
}

# Check orchestrator status
def orchestrator_status [--out: string]: nothing -> nothing {
  let provisioning_root = $env.PROVISIONING? | default "/usr/local/provisioning"
  let orchestrator_script = ($provisioning_root | path join "platform" "orchestrator" "scripts" "start-orchestrator.nu")

  if not ($orchestrator_script | path exists) {
    print $"❌ Orchestrator start script not found: ($orchestrator_script)"
    exit 1
  }

  ^nu $orchestrator_script --check

  if ($out | is-not-empty) {
    let health_result = (do { ^curl -s -f "http://localhost:8080/health" } | complete)
    if $health_result.exit_code == 0 {
      let health = ($health_result.stdout | from json)
      if $out == "json" {
        print ($health | to json)
      } else if $out == "yaml" {
        print ($health | to yaml)
      } else {
        print ($health | table)
      }
    } else {
      print "Could not retrieve detailed status"
    }
  }
}

# Check orchestrator health via HTTP endpoint
def orchestrator_health [--out: string]: nothing -> nothing {
  let health_result = (do { ^curl -s -f "http://localhost:8080/health" } | complete)

  if $health_result.exit_code != 0 {
    print "❌ Orchestrator is not running"
    print "   Start with: provisioning orchestrator start"
    exit 1
  }

  let health = ($health_result.stdout | from json)

  if ($health | get success) {
    print "✅ Orchestrator is healthy"
    print $"📊 Status: (($health | get data))"

    if ($out | is-not-empty) {
      if $out == "json" {
        print ($health | to json)
      } else if $out == "yaml" {
        print ($health | to yaml)
      } else {
        print ($health | table)
      }
    }
  } else {
    print "⚠️  Orchestrator health check failed"
    if ($out | is-not-empty) {
      if $out == "json" {
        print ($health | to json)
      } else if $out == "yaml" {
        print ($health | to yaml)
      }
    }
    exit 1
  }
}

# Migrate storage backend
def orchestrator_migrate [
  target: string
  --check
]: nothing -> nothing {
  let provisioning_root = $env.PROVISIONING? | default "/usr/local/provisioning"
  let migrate_script = ($provisioning_root | path join "platform" "orchestrator" "scripts" "migrate-storage.nu")

  if not ($migrate_script | path exists) {
    print $"❌ Migration script not found: ($migrate_script)"
    exit 1
  }

  match $target {
    "surrealdb" => {
      if $check {
        print "🔍 Checking migration to SurrealDB (dry-run)..."
        ^nu $migrate_script --from filesystem --to surrealdb-embedded --source-dir "./data" --target-dir "./data-surrealdb" --dry-run
      } else {
        print "🔄 Migrating to SurrealDB..."
        ^nu $migrate_script --from filesystem --to surrealdb-embedded --source-dir "./data" --target-dir "./data-surrealdb"
      }
    },
    "filesystem" => {
      if $check {
        print "🔍 Checking migration to filesystem (dry-run)..."
        ^nu $migrate_script --from surrealdb-embedded --to filesystem --source-dir "./data-surrealdb" --target-dir "./data" --dry-run
      } else {
        print "🔄 Migrating to filesystem..."
        ^nu $migrate_script --from surrealdb-embedded --to filesystem --source-dir "./data-surrealdb" --target-dir "./data"
      }
    },
    _ => {
      print $"❌ Unknown migration target: ($target)"
      print "   Valid targets: surrealdb, filesystem"
      exit 1
    }
  }
}

# Show orchestrator logs
def orchestrator_logs [
  --follow
  --lines: int
]: nothing -> nothing {
  let provisioning_root = $env.PROVISIONING? | default "/usr/local/provisioning"
  let log_file = ($provisioning_root | path join "platform" "orchestrator" "data" "orchestrator.log")

  if not ($log_file | path exists) {
    print $"⚠️  Log file not found: ($log_file)"
    print "   Orchestrator may not have been started yet."
    exit 1
  }

  if $follow {
    print $"📋 Following orchestrator logs (($log_file))..."
    print "   Press Ctrl+C to stop"
    ^tail -f $log_file
  } else {
    print $"📋 Last ($lines) lines from orchestrator logs:"
    ^tail -n ($lines | into string) $log_file
  }
}
