# frozen_string_literal: true require 'optparse' require_relative '../../core/colores' require_relative '../../core/help_formatter' module ADN module SubcomandoDBAmbito # Comando: ambito:listar [OPCIONES] - Listar ámbitos def comando_ambito_listar(args) opts = { activo: nil } parser = OptionParser.new do |opt| opt.banner = "Uso: adn db ambito:listar [OPCIONES]" 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 opt exit end end begin parser.parse!(args) rescue OptionParser::InvalidOption => e puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}" exit 1 end 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 # Comando: ambito:crear [OPCIONES] - Crear nuevo ámbito def comando_ambito_crear(args) opts = { nombre: nil, descripcion: nil, parent_id: nil } parser = OptionParser.new do |opt| opt.banner = "Uso: adn db ambito:crear --nombre NOMBRE [OPCIONES]" opt.on("--nombre NOMBRE", "Nombre único del ámbito (obligatorio)") { |n| opts[:nombre] = n } opt.on("--descripcion DESC", "Descripción del ámbito") { |d| opts[:descripcion] = d } opt.on("--parent-id ID", Integer, "ID del ámbito padre") { |p| opts[:parent_id] = p } opt.on("-h", "--help", "Mostrar ayuda") do puts opt exit end end begin parser.parse!(args) rescue OptionParser::InvalidOption => e puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}" exit 1 end 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], parent_id: opts[:parent_id] ) 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 # Comando: ambito:info [NOMBRE_O_ID] - Info detallada def comando_ambito_info(args) objetivo = args.first if objetivo.nil? || objetivo.start_with?('-') puts "#{Color::YELLOW}Uso: adn db ambito:info #{Color::RESET}" return 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 # Comando: ambito:nodos [NOMBRE_O_ID] - Listar nodos de un ámbito def comando_ambito_nodos(args) objetivo = args.first if objetivo.nil? || objetivo.start_with?('-') puts "#{Color::YELLOW}Uso: adn db ambito:nodos #{Color::RESET}" return 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 end end