# frozen_string_literal: true require 'optparse' require_relative '../core/colores' require_relative '../core/help_formatter' require_relative '../db/core/bitacora_db' module ADN class SubcomandoAmbitos def initialize(args, logger) @args = args @logger = logger end def ejecutar if @args.empty? || ['help', '-h', '--help'].include?(@args[0]) mostrar_ayuda return end subcomando = @args[0] sub_args = @args[1..-1] || [] case subcomando when 'listar' comando_listar(sub_args) when 'crear' comando_crear(sub_args) when 'info' comando_info(sub_args) when 'nodos' comando_nodos(sub_args) else puts "#{Color::RED}✗ Subcomando desconocido: '#{subcomando}'#{Color::RESET}" puts "\n" mostrar_ayuda exit 1 end rescue Interrupt puts "\n#{Color::YELLOW}⚠ Operación interrumpida por el usuario#{Color::RESET}" exit 130 rescue => e @logger.error("Error en operación de ámbitos: #{e.message}") puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}" exit 1 end private def comando_listar(args) opts = { activo: nil } parser = OptionParser.new do |opt| opt.on("--activo", "Mostrar solo ámbitos activos") { opts[:activo] = true } opt.on("--inactivo", "Mostrar solo ámbitos inactivos") { opts[:activo] = false } opt.on("-h", "--help", "Mostrar ayuda") do puts HelpFormatter.generar_help( titulo: "Listar Ámbitos", descripcion: "Muestra la lista de ámbitos (agrupadores de nodos).", uso: HelpFormatter.format_usage("adn ambitos listar", "[OPCIONES]"), opciones: [ { names: ["activo"], desc: "Mostrar solo ámbitos activos" }, { names: ["inactivo"], desc: "Mostrar solo ámbitos inactivos" }, { names: ["h", "help"], desc: "Mostrar esta ayuda" } ], ejemplos: [{ cmd: "./adn/tools/run ambitos listar", desc: "Listar todos los ámbitos" }] ) exit 0 end end parsear_argumentos!(parser, args) puts "#{Color::CYAN}📋 Listando ámbitos...#{Color::RESET}\n\n" BitacorasDB::BitacoraDB.with_connection do |db| ambitos = db.list_ambitos(activo: opts[:activo]) if ambitos.empty? puts "#{Color::YELLOW}⚠ No se encontraron ámbitos.#{Color::RESET}" return end puts "#{Color::BOLD}#{"ID".ljust(5)} #{"Nombre".ljust(20)} #{"Nodos".ljust(7)} #{"Activo".ljust(6)} #{"Padre".ljust(20)}#{Color::RESET}" puts "#{"─" * 5} #{"─" * 20} #{"─" * 7} #{"─" * 6} #{"─" * 20}" ambitos.each do |a| id = a['id'].to_s.ljust(5) nombre = a['nombre'].to_s.ljust(20) count = a['count_nodos'].to_s.ljust(7) activo = (a['activo'] ? '✅' : '❌').ljust(6) padre = (a['parent_nombre'] || '-').ljust(20) puts "#{id} #{nombre} #{count} #{activo} #{padre}" end puts "\nTotal: #{ambitos.length} ámbitos." end end def comando_crear(args) opts = { nombre: nil, descripcion: nil, activo: true } parser = OptionParser.new do |opt| opt.on("--nombre NOMBRE", "Nombre del ámbito") { |n| opts[:nombre] = n } opt.on("--descripcion DESC", "Descripción del ámbito") { |d| opts[:descripcion] = d } opt.on("-h", "--help", "Mostrar ayuda") do puts HelpFormatter.generar_help( titulo: "Crear Ámbito", descripcion: "Genera un nuevo ámbito para agrupar nodos de infraestructura.", uso: HelpFormatter.format_usage("adn ambitos crear", "--nombre NOMBRE [OPCIONES]"), opciones: [ { names: ["nombre NOMBRE"], desc: "Nombre único del ámbito (obligatorio)" }, { names: ["descripcion DESC"], desc: "Descripción del propósito del ámbito" }, { names: ["h", "help"], desc: "Mostrar esta ayuda" } ], ejemplos: [{ cmd: "./adn/tools/run ambitos crear --nombre dtic-Pruebas", desc: "Crear un ámbito de pruebas" }] ) exit 0 end end parsear_argumentos!(parser, args) unless opts[:nombre] puts "#{Color::RED}✗ Error: El parámetro --nombre es obligatorio.#{Color::RESET}" exit 1 end puts "#{Color::CYAN}📦 Creando ámbito '#{opts[:nombre]}'...#{Color::RESET}" BitacorasDB::BitacoraDB.with_connection do |db| begin ambito = db.create_ambito(nombre: opts[:nombre], descripcion: opts[:descripcion]) puts "#{Color::GREEN}✅ Ámbito creado exitosamente. ID: #{ambito['id']}#{Color::RESET}" rescue PG::UniqueViolation puts "#{Color::RED}✗ Error: Ya existe un ámbito con el nombre '#{opts[:nombre]}'.#{Color::RESET}" exit 1 end end end def comando_info(args) opts = {} parser = OptionParser.new do |opt| opt.on("-h", "--help", "Mostrar ayuda") do puts HelpFormatter.generar_help( titulo: "Info de Ámbito", descripcion: "Muestra información y estadísticas detalladas de un ámbito.", uso: HelpFormatter.format_usage("adn ambitos info", ""), opciones: [], ejemplos: [{ cmd: "./adn/tools/run ambitos info dtic-DASUTEN", desc: "Ver detalles de dtic-DASUTEN" }] ) exit 0 end end parsear_argumentos!(parser, args) objetivo = args.first if objetivo.nil? || objetivo.empty? puts "#{Color::RED}✗ Error: Debes especificar el nombre o ID del ámbito.#{Color::RESET}" exit 1 end BitacorasDB::BitacoraDB.with_connection do |db| ambito = db.get_ambito(objetivo) if ambito.nil? puts "#{Color::RED}✗ Error: Ámbito '#{objetivo}' no encontrado.#{Color::RESET}" exit 1 end puts "#{Color::CYAN}ℹ Info del Ámbito: #{ambito['nombre']}#{Color::RESET}\n\n" puts " #{Color::BOLD}ID:#{Color::RESET} #{ambito['id']}" puts " #{Color::BOLD}Nombre:#{Color::RESET} #{ambito['nombre']}" puts " #{Color::BOLD}Descripción:#{Color::RESET} #{ambito['descripcion'] || '(sin descripción)'}" puts " #{Color::BOLD}Padre:#{Color::RESET} #{ambito['parent_nombre'] || '(raíz)'}" puts " #{Color::BOLD}Activo:#{Color::RESET} #{ambito['activo'] ? 'Sí' : 'No'}" puts " #{Color::BOLD}Nodos:#{Color::RESET} #{ambito['count_nodos']}" puts "" end end def comando_nodos(args) opts = {} parser = OptionParser.new do |opt| opt.on("-h", "--help", "Mostrar ayuda") do puts HelpFormatter.generar_help( titulo: "Nodos de Ámbito", descripcion: "Lista todos los nodos pertenecientes a un ámbito.", uso: HelpFormatter.format_usage("adn ambitos nodos", ""), opciones: [], ejemplos: [{ cmd: "./adn/tools/run ambitos nodos dtic-DASUTEN", desc: "Ver componentes agrupados bajo dtic-DASUTEN" }] ) exit 0 end end parsear_argumentos!(parser, args) objetivo = args.first if objetivo.nil? || objetivo.empty? puts "#{Color::RED}✗ Error: Debes especificar el nombre o ID del ámbito.#{Color::RESET}" exit 1 end BitacorasDB::BitacoraDB.with_connection do |db| ambito = db.get_ambito(objetivo) if ambito.nil? puts "#{Color::RED}✗ Error: Ámbito '#{objetivo}' no encontrado.#{Color::RESET}" exit 1 end puts "#{Color::CYAN}🖥️ Nodos del ámbito '#{ambito['nombre']}'...#{Color::RESET}\n\n" nodos = db.get_nodos_by_ambito(ambito['id']) if nodos.empty? puts "#{Color::YELLOW}⚠ Este ámbito no tiene nodos asignados.#{Color::RESET}" return end nodos.each do |n| tipo = n['tipo'].to_s.ljust(10) ip = (n['ip'] || '-').ljust(15) estado = n['activo'] ? "#{Color::GREEN}ON#{Color::RESET}" : "#{Color::RED}OFF#{Color::RESET}" puts " #{Color::DIM}▸#{Color::RESET} #{Color::BOLD}#{n['nombre'].to_s.ljust(20)}#{Color::RESET} [#{tipo}] IP: #{ip} (#{estado})" end end end def mostrar_ayuda puts HelpFormatter.generar_help( titulo: "Gestión de Ámbitos (Modelo DB-First)", descripcion: "Los ámbitos agrupan lógicamente a los nodos correspondientes a áreas organizativas.", uso: HelpFormatter.format_usage("adn ambitos", " [OPCIONES]"), opciones: [ { names: ["h", "help"], desc: "Mostrar esta ayuda" } ], ejemplos: [ { cmd: "./adn/tools/run ambitos listar", desc: "Listar ámbitos y cantidad de nodos" }, { cmd: "./adn/tools/run ambitos info dtic-DIIAA", desc: "Ver detalle del ámbito DIIAA" }, { cmd: "./adn/tools/run ambitos nodos dtic-DASUTEN", desc: "Listar hipervisores e infraestructura de DASUTEN" } ] ) end def parsear_argumentos!(parser, args) begin parser.parse!(args) rescue OptionParser::InvalidOption => e puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}" puts "\nEjecuta con --help para ver las opciones disponibles." exit 1 end end end end