#!/usr/bin/env ruby
# frozen_string_literal: true
ENV['TZ'] = 'America/Argentina/Buenos_Aires'

# tools/adn.rb — Interfaz de línea de comandos unificada para el sistema ADN
# ============================================================================
# 🤖 DIRECTIVA IA: Esta herramienta es el punto de entrada principal para la
# automatización del ADN. Su objetivo es reducir progresivamente la dependencia
# de la IA mediante scripts Ruby autónomos.
# ============================================================================
# Uso: ./adn/tools/run <subcomando> [opciones] [argumentos]
#
# Subcomandos disponibles:
#   validador [--watch] [--fix]      Validar cumplimiento del ADN en bitácoras
#   contexto <nodo> [--cmd]          Obtener contexto topológico de un nodo
#   nodos <acción> [opciones]        Gestión de nodos (agrupar, listar, buscar)
#   jornada <acción> [modo] [hora]   Gestión de jornada (iniciar, cerrar, estado)
#   salud [--dashboard] [--json]     Ver salud general del sistema ADN
#   generar bitacora [fecha]         Generar nueva bitácora (fecha: YYYY-MM-DD)
#   generar nodo <nombre>            Generar ficha de nodo
#   generar proyecto <código>        Generar manifiesto de proyecto
#   tailscale <acción> [opciones]    Gestión de identidades Tailscale
#   conocimiento asimilar <archivo>  Asimilar documentación al ADN
#   evolucion <propuesta.md>         Gestionar propuesta de evolución del ADN
#   msp <subcomando>                  Gestión de MSPs (auditar, registrar, listar)
#   proy <subcomando>                 Generación y gestión de proyectos
#   candados <acción> [opciones]      Gestión de secretos y autorización SSH
#   ayuda [subcomando]               Mostrar ayuda detallada
#
# Documentación completa: docs/ambito/dtic-ADN/A01_dtic-ADN.md

require 'optparse'
require 'json'
require 'fileutils'
require 'date'
require 'time'

require_relative 'core/constants'

module ADN
  # Aseguramos que los directorios existan
  FileUtils.mkdir_p(LOGS_DIR) unless Dir.exist?(LOGS_DIR)
  FileUtils.mkdir_p(BITACORAS_DIR) unless Dir.exist?(BITACORAS_DIR)
end

require_relative 'core/logger'
require_relative 'cli/triggers/eventos'
require_relative 'cli/triggers/motor'
require_relative 'cli/db'
require_relative 'cli/plan'
# require_relative 'cli/backup' # Archivado → _hist/ (A03.P001)
require_relative 'cli/triggers'
require_relative 'cli/conocimiento'
require_relative 'cli/jornada'
require_relative 'cli/proceso'
require_relative 'cli/estados'
require_relative 'cli/tailscale'
require_relative 'cli/ssh'
require_relative 'cli/candados'
require_relative 'cli/network'
require_relative 'core/conciliador'

require_relative 'core/colores'

# ─── Logger estructurado ─────────────────────────────────────────────────
# El logger está implementado en adn/logger.rb
ADNLogger = ADN::Logger

require_relative 'cli/validador'
require_relative 'cli/contexto'
require_relative 'cli/generar'
require_relative 'cli/salud'
require_relative 'cli/ayuda'
require_relative 'cli/nodos'
require_relative 'cli/ambitos'
require_relative 'cli/msp'
require_relative 'cli/wzombi'
require_relative 'cli/dasuten'
require_relative 'cli/digis'
require_relative 'cli/dns'
require_relative 'bkps/bkps'
require_relative 'cli/dron'
require_relative 'proy/proy'

# ─── CLI Principal ──────────────────────────────────────────────────────
class ADNCLI
  def initialize
    @logger = ADNLogger.new
  end

  def ejecutar
    if ARGV.empty?
      ADN::SubcomandoAyuda.new([], @logger).ejecutar
      exit 0
    end

    subcomando = ARGV[0]
    
    # Saneamiento preventivo de pendientes (con cooldown de 5 minutos para performance)
    ejecutar_saneamiento_preventivo(subcomando)

    args = ARGV[1..-1] || []

    case subcomando
    when 'validador'
      SubcomandoValidador.new(args, @logger).ejecutar
    when 'contexto'
      SubcomandoContexto.new(args, @logger).ejecutar
    when 'salud'
      ADN::SubcomandoSalud.new(args, @logger).ejecutar
    when 'generar'
      SubcomandoGenerar.new(args, @logger).ejecutar
    when 'nodos'
      ADN::SubcomandoNodos.new(args, @logger).ejecutar
    when 'ambitos'
      ADN::SubcomandoAmbitos.new(args, @logger).ejecutar
    when 'conocimiento'
      ADN::SubcomandoConocimiento.new(args, @logger).ejecutar
    when 'db'
      ADN::SubcomandoDB.new(args, @logger).ejecutar
    when 'backup', 'backups'
      ADN::SubcomandoBkps.new(args, @logger).ejecutar  # Redirigido desde legacy backup → bkps
    when 'triggers'
      ADN::SubcomandoTriggers.new(args, @logger).ejecutar
    when 'jornada'
      ADN::SubcomandoJornada.new(args, @logger).ejecutar
    when 'proceso'
      ADN::SubcomandoProceso.new(args, @logger).ejecutar
    when 'estados'
      ADN::SubcomandoEstados.new(args, @logger).ejecutar
    when 'network'
      ADN::SubcomandoNetwork.new(args, @logger).ejecutar
    when 'tailscale', 'ts'
      ADN::SubcomandoTailscale.new(args, @logger).ejecutar
    when 'inicio'
      # Compatibilidad: redirigir a jornada iniciar
      ADN::SubcomandoJornada.new(['iniciar'] + args, @logger).ejecutar
    when 'cierre'
      # Compatibilidad: redirigir a jornada cerrar
      ADN::SubcomandoJornada.new(['cerrar'] + args, @logger).ejecutar
    when 'ayuda', 'help', '-h', '--help'
      ADN::SubcomandoAyuda.new(args, @logger).ejecutar
    when 'evolucion'
      @logger.info("Subcomando 'evolucion' será implementado en Fase 2")
      puts "#{Color::YELLOW}⚠ El subcomando 'evolucion' será implementado en Fase 2#{Color::RESET}"
      puts "  Ver plan: docs/plan/260307-1400_Plan_Mejoras_ADN.md"
    when 'plan'
      ADN::SubcomandoPlan.new(args, @logger).ejecutar
    when 'msp'
      SubcomandoMsp.new(args, @logger).ejecutar
    when 'proy'
      ADN::SubcomandoProy.new(args, @logger).ejecutar
    when 'ssh'
      ADN::SubcomandoSSH.new(args, @logger).ejecutar
    when 'network'
      ADN::SubcomandoNetwork.new(args, @logger).ejecutar
    when 'candados', 'secrets'
      ADN::SubcomandoCandados.new(args, @logger).ejecutar
    when 'wzombi', 'w-zombi'
      ADN::SubcomandoWZombi.new(args, @logger).ejecutar
    when 'dasuten'
      ADN::SubcomandoDasuten.new(args, @logger).ejecutar
    when 'bkps'
      ADN::SubcomandoBkps.new(args, @logger).ejecutar
    when 'dron', 'copiloto', 'novato'
      ADN::SubcomandoDron.new(args, @logger).ejecutar
    when 'digis'
      ADN::SubcomandoDigis.new(args, @logger).ejecutar
    when 'dns'
      ADN::SubcomandoDNS.new(args, @logger).ejecutar
    else
      @logger.error("Subcomando desconocido: #{subcomando}")
      puts "#{Color::RED}✗ Subcomando desconocido: '#{subcomando}'#{Color::RESET}"
      puts ""
      ADN::SubcomandoAyuda.new([], @logger).ejecutar
      exit 1
    end
  rescue Interrupt
    puts "\n#{Color::YELLOW}⚠ Interrumpido por el usuario#{Color::RESET}"
    @logger.info("Ejecución interrumpida por usuario")
    exit 130
  rescue OptionParser::InvalidOption => e
    @logger.error("Opción inválida: #{e.message}")
    puts "#{Color::RED}✗ Error: opción inválida #{e.message}#{Color::RESET}"
    puts "Usa './adn/tools/run ayuda' para ver las opciones disponibles"
    exit 1
  rescue ADN::Error => e
    @logger.error("Error de aplicación: #{e.message}")
    puts "#{Color::RED}✗ #{e.message}#{Color::RESET}"
    exit 1
  rescue => e
    @logger.error("Error inesperado: #{e.message}", { backtrace: e.backtrace })
    puts "#{Color::RED}✗ Error inesperado: #{e.message}#{Color::RESET}"
    puts "#{Color::DIM}#{e.backtrace.first(3).join("\n")}#{Color::RESET}" if ENV['ADN_DEBUG']
    puts "\n#{Color::YELLOW}💡 Ejecuta con ADN_DEBUG=1 para ver el trace completo#{Color::RESET}"
    exit 1
  end
  private

  def ejecutar_saneamiento_preventivo(subcomando)
    # No sanear si es ayuda o db (para evitar bucles o lentitud en info rápida)
    return if ['ayuda', 'help', 'db', 'salud', '-h', '--help'].include?(subcomando)
    
    archivo_cooldown = "/tmp/adn_sanity_cooldown"
    cooldown_segundo = 300 # 5 minutos
    
    if File.exist?(archivo_cooldown)
      last_run = File.mtime(archivo_cooldown)
      return if (Time.now - last_run) < cooldown_segundo
    end

    # Ejecutar conciliación
    begin
      # Tocamos el archivo primero para evitar que otras instancias concurrentes lo lancen
      FileUtils.touch(archivo_cooldown)
      ADN::Conciliador.new(@logger).ejecutar(silencioso: true)
    rescue => e
      @logger.advertencia("No se pudo completar el saneamiento preventivo: #{e.message}")
    end
  end
end

# ─── Punto de entrada ───────────────────────────────────────────────────
if __FILE__ == $0
  ADNCLI.new.ejecutar
end
