#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Contextualizador Inteligente de Proyectos - Versión Completa
Auto: Asistente AI
Fecha: Julio 2025
"""

import requests
from bs4 import BeautifulSoup
from datetime import datetime, timedelta
import os
import json
import csv
import xml.etree.ElementTree as ET
from urllib.parse import urlparse
import hashlib
import time
import shutil
import logging
import re
import subprocess

class GestorArchivosOrganizado:
    def __init__(self, proyecto_dir="."):
        self.proyecto_dir = os.path.abspath(proyecto_dir)
        self.base_dir = os.path.join(proyecto_dir, "contexto_docs")
        self._crear_estructura_directorios()
        self._configurar_logging()
        self._limpiar_archivos_antiguos()
    
    def _crear_estructura_directorios(self):
        """Crea la estructura de directorios organizada"""
        directorios = [
            "cache/temp",
            "cache/semanal", 
            "output/latest",
            "logs",
            "config"
        ]
        
        for dir_path in directorios:
            full_path = os.path.join(self.base_dir, dir_path)
            if not os.path.exists(full_path):
                os.makedirs(full_path)
    
    def _configurar_logging(self):
        """Configura logging con rotación semanal"""
        log_dir = os.path.join(self.base_dir, "logs")
        log_file = os.path.join(log_dir, f"contexto_{datetime.now().strftime('%Y%m%d')}.log")
        
        logging.basicConfig(
            filename=log_file,
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s',
            encoding='utf-8'
        )
    
    def log(self, mensaje, nivel="info"):
        """Loggear mensajes"""
        if nivel == "error":
            logging.error(mensaje)
        elif nivel == "warning":
            logging.warning(mensaje)
        else:
            logging.info(mensaje)
        print(f"[{nivel.upper()}] {mensaje}")
    
    def _limpiar_archivos_antiguos(self):
        """Limpia archivos según política de retención"""
        ahora = datetime.now()
        
        # Limpiar caché de más de 7 días
        cache_temp = os.path.join(self.base_dir, "cache", "temp")
        if os.path.exists(cache_temp):
            for file in os.listdir(cache_temp):
                filepath = os.path.join(cache_temp, file)
                try:
                    file_time = datetime.fromtimestamp(os.path.getmtime(filepath))
                    if (ahora - file_time).days > 7:
                        os.remove(filepath)
                        self.log(f"Caché limpiado: {file}")
                except Exception as e:
                    self.log(f"Error limpiando {file}: {e}", "warning")
        
        # Limpiar outputs de más de 30 días
        output_dir = os.path.join(self.base_dir, "output")
        if os.path.exists(output_dir):
            for item in os.listdir(output_dir):
                if item == "latest":
                    continue
                item_path = os.path.join(output_dir, item)
                if os.path.isdir(item_path):
                    try:
                        # Extraer fecha del nombre de directorio
                        match = re.search(r'(\d{8})', item)
                        if match:
                            fecha_str = match.group(1)
                            fecha_dir = datetime.strptime(fecha_str, "%Y%m%d")
                            if (ahora - fecha_dir).days > 30:
                                shutil.rmtree(item_path)
                                self.log(f"Output antiguo eliminado: {item}")
                    except Exception as e:
                        self.log(f"Error procesando directorio {item}: {e}", "warning")
    
    def obtener_directorio_salida(self, prefijo="proyecto"):
        """Obtiene directorio de salida para la ejecución actual"""
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        dir_name = f"{prefijo}_docs_{timestamp}"
        output_dir = os.path.join(self.base_dir, "output", dir_name)
        
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        
        # Actualizar latest
        latest_dir = os.path.join(self.base_dir, "output", "latest")
        if os.path.exists(latest_dir):
            if os.name == 'nt':  # Windows
                shutil.rmtree(latest_dir)
            else:  # Unix/Linux/Mac
                try:
                    os.unlink(latest_dir)
                except:
                    shutil.rmtree(latest_dir)
        
        try:
            os.symlink(dir_name, latest_dir)
        except:
            # Si symlink falla, copiar
            latest_copy = os.path.join(self.base_dir, "output", "latest_copy")
            if os.path.exists(latest_copy):
                shutil.rmtree(latest_copy)
            shutil.copytree(output_dir, latest_copy)
        
        return output_dir
    
    def obtener_cache_path(self, url, tipo="temp"):
        """Obtiene ruta de caché con organización por tipo"""
        hash_url = hashlib.md5(url.encode()).hexdigest()
        cache_dir = os.path.join(self.base_dir, "cache", tipo)
        return os.path.join(cache_dir, f"{hash_url}.html")

class ContextoProyectoInteligente:
    def __init__(self, proyecto_dir=".", gestor_archivos=None):
        self.proyecto_dir = os.path.abspath(proyecto_dir)
        self.gestor = gestor_archivos or GestorArchivosOrganizado(proyecto_dir)
        self.fuentes = []
        self.secciones_totales = []
        self.metadata_global = {
            "fechas_descarga": [],
            "urls_procesadas": [],
            "urls_fallidas": [],
            "urls_desde_cache": []
        }
        self.contexto_proyecto = {}
        self.palabras_clave_incluir = []
        self.palabras_clave_excluir = []
        self._crear_directorio_cache()
    
    def _crear_directorio_cache(self):
        """Crea el directorio de caché si no existe"""
        cache_dir = os.path.join(self.gestor.base_dir, "cache")
        if not os.path.exists(cache_dir):
            os.makedirs(cache_dir)
    
    def _generar_hash_url(self, url):
        """Genera un hash único para la URL"""
        return hashlib.md5(url.encode()).hexdigest()
    
    def _guardar_en_cache(self, url, contenido, tipo="temp"):
        """Guarda contenido en caché"""
        cache_path = self.gestor.obtener_cache_path(url, tipo)
        try:
            with open(cache_path, 'w', encoding='utf-8') as f:
                f.write(contenido)
            return True
        except Exception as e:
            self.gestor.log(f"Error al guardar en caché: {e}", "error")
            return False
    
    def _leer_desde_cache(self, url, tipo="temp"):
        """Lee contenido desde caché si existe y no está vencido"""
        cache_path = self.gestor.obtener_cache_path(url, tipo)
        
        if os.path.exists(cache_path):
            file_time = os.path.getmtime(cache_path)
            current_time = time.time()
            
            # 7 días para temp, 30 días para semanal
            max_age = 7 * 86400 if tipo == "temp" else 30 * 86400
            
            if (current_time - file_time) < max_age:
                try:
                    with open(cache_path, 'r', encoding='utf-8') as f:
                        return f.read()
                except Exception as e:
                    self.gestor.log(f"Error al leer desde caché: {e}", "error")
        
        return None
    
    def escanear_entorno(self):
        """Escanea el entorno de desarrollo del usuario."""
        self.gestor.log("🔍 Escaneando entorno de desarrollo...")
        
        entorno = {
            "sistema_operativo": None,
            "versiones": {
                "php": None,
                "node": None,
                "npm": None,
                "composer": None,
                "laravel": None # Se intentará obtener de composer.json o artisan
            },
            "herramientas": {
                "servidor_local": None, # Inferido o preguntado
                "gestor_db": None       # Opcional, más complejo de detectar automáticamente
            },
            "variables_entorno": {
                "APP_ENV": None,
                "DB_CONNECTION": None
                # Agrega más si es relevante, pero cuidado con datos sensibles
            }
        }

        try:
            # 1. Sistema Operativo
            if os.name == 'nt':
                entorno["sistema_operativo"] = "Windows"
            elif hasattr(os, 'uname'):
                entorno["sistema_operativo"] = os.uname().sysname
            else:
                entorno["sistema_operativo"] = f"Desconocido ({os.name})"
        except Exception as e:
            entorno["sistema_operativo"] = f"Error al detectar: {e}"

        # 2. Versiones de herramientas
        herramientas = [
            ("php", ["php", "--version"]),
            ("node", ["node", "--version"]),
            ("npm", ["npm", "--version"]),
            ("composer", ["composer", "--version"])
        ]

        for nombre, comando in herramientas:
            try:
                # En Windows, puede ser necesario usar shell=True
                resultado = subprocess.run(comando, capture_output=True, text=True, timeout=10, shell=(os.name == 'nt'), cwd=self.proyecto_dir)
                if resultado.returncode == 0:
                    # Extraer la primera línea y limpiar
                    version_line = resultado.stdout.splitlines()[0] if resultado.stdout else "Versión encontrada"
                    entorno["versiones"][nombre] = version_line.strip()
                else:
                    entorno["versiones"][nombre] = f"Error al ejecutar: {resultado.stderr.strip()[:100]}..." # Limitar longitud del error
            except subprocess.TimeoutExpired:
                entorno["versiones"][nombre] = "Timeout al ejecutar comando"
            except FileNotFoundError:
                entorno["versiones"][nombre] = "Comando no encontrado"
            except Exception as e:
                entorno["versiones"][nombre] = f"Error: {e}"

        # 3. Detectar Laravel (desde composer.json ya cargado o artisan)
        try:
            # Opción 1: Desde composer.json (ya cargado en self.contexto_proyecto)
            composer_data = None
            composer_path = os.path.join(self.proyecto_dir, 'composer.json')
            if os.path.exists(composer_path):
                with open(composer_path, 'r') as f:
                    composer_data = json.load(f)
                
                if composer_data and 'require' in composer_data:
                    laravel_version = composer_data['require'].get('laravel/framework', 'No especificada')
                    entorno["versiones"]["laravel"] = laravel_version
            else:
                # Opción 2: Intentar con `php artisan --version` (puede ser lento)
                # Descomenta las siguientes líneas si deseas probar esto
                # resultado_artisan = subprocess.run(
                #     ["php", "artisan", "--version"], 
                #     cwd=self.proyecto_dir, 
                #     capture_output=True, 
                #     text=True, 
                #     timeout=15,
                #     shell=(os.name == 'nt')
                # )
                # if resultado_artisan.returncode == 0:
                #     entorno["versiones"]["laravel"] = resultado_artisan.stdout.strip()
                # else:
                #     entorno["versiones"]["laravel"] = f"Artisan no disponible o error: {resultado_artisan.stderr.strip()}"
                pass # Si no se encuentra composer.json ni se usa artisan, queda como None o del composer.json

        except Exception as e:
            entorno["versiones"]["laravel"] = f"Error al detectar Laravel: {e}"

        # 4. Detectar servidor local (Inferencia básica)
        # Esto es más una suposición. Podrías hacerlo interactivo.
        ruta_proyecto_lower = self.proyecto_dir.lower()
        if 'laragon' in ruta_proyecto_lower:
            entorno["herramientas"]["servidor_local"] = "Laragon (inferido de la ruta)"
        elif 'xampp' in ruta_proyecto_lower:
            entorno["herramientas"]["servidor_local"] = "XAMPP (inferido de la ruta)"
        elif 'wamp' in ruta_proyecto_lower:
            entorno["herramientas"]["servidor_local"] = "WAMP (inferido de la ruta)"
        else:
            entorno["herramientas"]["servidor_local"] = "Desconocido o Servidor Personalizado"

        # 5. Variables de entorno básicas (desde .env, con cuidado)
        env_path = os.path.join(self.proyecto_dir, '.env')
        if os.path.exists(env_path):
            try:
                with open(env_path, 'r') as f:
                    for line in f:
                        line = line.strip()
                        if line and not line.startswith('#'):
                            if '=' in line:
                                key, value = line.split('=', 1)
                                key = key.strip()
                                # Solo almacenar claves no sensibles
                                if key in ["APP_ENV", "DB_CONNECTION", "APP_DEBUG"]:
                                    entorno["variables_entorno"][key] = value.strip()
            except Exception as e:
                self.gestor.log(f"Advertencia al leer .env: {e}", "warning")

        self.gestor.log("✅ Escaneo de entorno completado.")
        # Almacenar en el contexto del proyecto
        self.contexto_proyecto["entorno"] = entorno
        return entorno

    def escanear_proyecto(self):
        """Escanea el proyecto para detectar tecnologías y generar contexto"""
        self.gestor.log(f"Escaneando proyecto: {self.proyecto_dir}")
        
        contexto = {
            "proyecto": {
                "ruta": self.proyecto_dir,
                "nombre": os.path.basename(self.proyecto_dir),
                "fecha_escaneo": datetime.now().isoformat()
            },
            "archivos": {
                "php": [],
                "js": [],
                "blade": [],
                "config": [],
                "composer": None,
                "package": None
            },
            "tecnologias_detectadas": [],
            "dependencias": {
                "php": [],
                "npm": []
            }
        }
        
        # Recorrer directorios
        for root, dirs, files in os.walk(self.proyecto_dir):
            # Excluir directorios de sistema
            dirs[:] = [d for d in dirs if d not in ['.git', 'node_modules', 'vendor', '.idea', '.vscode', '__pycache__']]
            
            for file in files:
                filepath = os.path.join(root, file)
                rel_path = os.path.relpath(filepath, self.proyecto_dir)
                
                # Clasificar archivos
                if file.endswith('.php'):
                    contexto["archivos"]["php"].append(rel_path)
                elif file.endswith('.js') and not file.endswith('.min.js'):
                    contexto["archivos"]["js"].append(rel_path)
                elif file.endswith('.blade.php'):
                    contexto["archivos"]["blade"].append(rel_path)
                elif file in ['composer.json', 'package.json', 'tailwind.config.js', 'webpack.mix.js', 'vite.config.js']:
                    contexto["archivos"]["config"].append(rel_path)
                
                # Archivos clave
                if file == 'composer.json':
                    contexto["archivos"]["composer"] = rel_path
                    if "Laravel/PHP" not in contexto["tecnologias_detectadas"]:
                        contexto["tecnologias_detectadas"].append("Laravel/PHP")
                elif file == 'package.json':
                    contexto["archivos"]["package"] = rel_path
                    if "Node.js" not in contexto["tecnologias_detectadas"]:
                        contexto["tecnologias_detectadas"].append("Node.js")
                elif 'tailwind' in file.lower() and "Tailwind CSS" not in contexto["tecnologias_detectadas"]:
                    contexto["tecnologias_detectadas"].append("Tailwind CSS")
                elif 'livewire' in file.lower() and "Livewire" not in contexto["tecnologias_detectadas"]:
                    contexto["tecnologias_detectadas"].append("Livewire")
                elif file in ['webpack.mix.js', 'vite.config.js'] and "Build Tools" not in contexto["tecnologias_detectadas"]:
                    contexto["tecnologias_detectadas"].append("Build Tools")
        
        # Leer composer.json para dependencias PHP
        if contexto["archivos"]["composer"]:
            try:
                with open(os.path.join(self.proyecto_dir, contexto["archivos"]["composer"]), 'r', encoding='utf-8') as f:
                    composer_data = json.load(f)
                    if 'require' in composer_data:
                        contexto["dependencias"]["php"] = list(composer_data['require'].keys())
                        # Detectar tecnologías específicas
                        for dep in composer_data['require'].keys():
                            if 'livewire' in dep and "Livewire" not in contexto["tecnologias_detectadas"]:
                                contexto["tecnologias_detectadas"].append("Livewire")
                            elif 'spatie' in dep and "Spatie Packages" not in contexto["tecnologias_detectadas"]:
                                contexto["tecnologias_detectadas"].append("Spatie Packages")
            except Exception as e:
                self.gestor.log(f"Error leyendo composer.json: {e}", "error")
        
        # Leer package.json para dependencias NPM
        if contexto["archivos"]["package"]:
            try:
                with open(os.path.join(self.proyecto_dir, contexto["archivos"]["package"]), 'r', encoding='utf-8') as f:
                    package_data = json.load(f)
                    if 'dependencies' in package_data:
                        contexto["dependencias"]["npm"] = list(package_data['dependencies'].keys())
                        # Detectar tecnologías específicas
                        for dep in package_data['dependencies'].keys():
                            if 'alpinejs' in dep and "Alpine.js" not in contexto["tecnologias_detectadas"]:
                                contexto["tecnologias_detectadas"].append("Alpine.js")
                            elif '@tailwindcss' in dep and "Tailwind CSS" not in contexto["tecnologias_detectadas"]:
                                contexto["tecnologias_detectadas"].append("Tailwind CSS")
            except Exception as e:
                self.gestor.log(f"Error leyendo package.json: {e}", "error")
        
        self.contexto_proyecto = contexto
        self.gestor.log(f"Escaneo completado. Tecnologías detectadas: {', '.join(contexto['tecnologias_detectadas'])}")
        return contexto
    
    def sugerir_urls_documentacion(self):
        """Sugiere URLs de documentación basadas en tecnologías detectadas"""
        tecnologias = self.contexto_proyecto.get("tecnologias_detectadas", [])
        urls_sugeridas = []
        
        # Mapeo de tecnologías a URLs de documentación
        mapeo_docs = {
            "Laravel/PHP": [
                ("https://laravel.com/docs/12.x", "Laravel 12 Documentation"),
                ("https://laravel.com/docs/12.x/container", "Laravel Service Container")
            ],
            "Livewire": [
                ("https://livewire.laravel.com/docs", "Livewire Documentation"),
                ("https://livewire.laravel.com/docs/wire-model", "Livewire Data Binding")
            ],
            "Tailwind CSS": [
                ("https://tailwindcss.com/docs", "Tailwind CSS Documentation"),
                ("https://tailwindcss.com/docs/utility-first", "Tailwind Utility Classes")
            ],
            "Alpine.js": [
                ("https://alpinejs.dev/start-here", "Alpine.js Documentation"),
                ("https://alpinejs.dev/directives", "Alpine.js Directives")
            ],
            "Node.js": [
                ("https://nodejs.org/api/", "Node.js API Documentation")
            ],
            "Spatie Packages": [
                ("https://spatie.be/docs", "Spatie Documentation")
            ],
            "Build Tools": [
                ("https://vitejs.dev/guide/", "Vite Documentation"),
                ("https://laravel.com/docs/12.x/vite", "Laravel Vite Integration")
            ]
        }
        
        # Agregar URLs basadas en tecnologías detectadas
        for tecnologia in tecnologias:
            if tecnologia in mapeo_docs:
                urls_sugeridas.extend(mapeo_docs[tecnologia])
        
        # Eliminar duplicados manteniendo orden
        urls_unicas = []
        urls_vistas = set()
        for url, nombre in urls_sugeridas:
            if url not in urls_vistas:
                urls_unicas.append((url, nombre))
                urls_vistas.add(url)
        
        return urls_unicas
    
    def configurar_filtros_inteligentes(self):
        """Configura filtros basados en tecnologías y dependencias del proyecto"""
        tecnologias = self.contexto_proyecto.get("tecnologias_detectadas", [])
        dependencias_php = self.contexto_proyecto.get("dependencias", {}).get("php", [])
        dependencias_npm = self.contexto_proyecto.get("dependencias", {}).get("npm", [])
        
        palabras_incluir = []
        palabras_excluir = ["installation", "upgrade", "migration", "changelog"]  # Palabras genéricas a excluir
        
        # Filtros por tecnología
        if "Laravel/PHP" in tecnologias:
            palabras_incluir.extend([
                "container", "service", "binding", "middleware", "controller", 
                "model", "eloquent", "query", "database", "auth", "security"
            ])
        
        if "Livewire" in tecnologias:
            palabras_incluir.extend([
                "livewire", "component", "wire", "alpine", "x-data", 
                "wire:model", "wire:click", "hydration"
            ])
        
        if "Tailwind CSS" in tecnologias:
            palabras_incluir.extend([
                "tailwind", "class", "utility", "responsive", "dark", 
                "flex", "grid", "spacing", "colors", "typography"
            ])
        
        if "Alpine.js" in tecnologias:
            palabras_incluir.extend([
                "alpine", "x-data", "x-bind", "x-on", "x-model", 
                "x-show", "x-if", "reactivity"
            ])
        
        # Filtros por dependencias específicas
        for dep in dependencias_php:
            if "spatie" in dep:
                palabras_incluir.append("spatie")
            elif "filament" in dep:
                palabras_incluir.extend(["filament", "admin", "panel"])
            elif "inertia" in dep:
                palabras_incluir.extend(["inertia", "vue", "react"])
        
        for dep in dependencias_npm:
            if "vue" in dep:
                palabras_incluir.extend(["vue", "component", "reactivity"])
            elif "react" in dep:
                palabras_incluir.extend(["react", "hook", "component"])
        
        self.palabras_clave_incluir = list(set(palabras_incluir))
        self.palabras_clave_excluir = list(set(palabras_excluir))
        
        self.gestor.log(f"Filtros inteligentes configurados")
        self.gestor.log(f"  Incluir: {', '.join(self.palabras_clave_incluir)}")
        self.gestor.log(f"  Excluir: {', '.join(self.palabras_clave_excluir)}")
    
    def _seccion_cumple_filtros(self, titulo, contenido):
        """Verifica si una sección cumple con los filtros configurados"""
        texto_completo = (titulo + " " + contenido).lower()
        
        # Si hay palabras clave de inclusión, al menos una debe estar presente
        if self.palabras_clave_incluir:
            cumple_inclusion = any(palabra in texto_completo for palabra in self.palabras_clave_incluir)
            if not cumple_inclusion:
                return False
        
        # Si hay palabras clave de exclusión, ninguna debe estar presente
        if self.palabras_clave_excluir:
            cumple_exclusion = not any(palabra in texto_completo for palabra in self.palabras_clave_excluir)
            if not cumple_exclusion:
                return False
        
        return True
    
    def limpiar_texto(self, texto):
        """Limpia texto de caracteres especiales y espacios extra"""
        return ' '.join(texto.split())
    
    def extraer_secciones_de_url(self, url, nombre_fuente=""):
        """Extrae secciones de una URL específica (con caché y filtros)"""
        try:
            self.gestor.log(f"Procesando: {url}")
            
            # Intentar leer desde caché primero
            contenido_html = self._leer_desde_cache(url, "semanal")
            
            if contenido_html:
                self.gestor.log(f"Usando caché para: {url}")
                self.metadata_global["urls_desde_cache"].append(url)
            else:
                self.gestor.log(f"Descargando: {url}")
                response = requests.get(url, timeout=30)
                response.raise_for_status()
                contenido_html = response.text
                
                # Guardar en caché
                self._guardar_en_cache(url, contenido_html, "semanal")
                self.metadata_global["fechas_descarga"].append(datetime.now().isoformat())
            
            # Parsear HTML
            soup = BeautifulSoup(contenido_html, 'html.parser')
            
            # Limpiar elementos no deseados
            for elemento in soup(["script", "style", "nav", "header", "footer", "aside", "noscript", "iframe"]):
                elemento.decompose()
            
            # Extraer título de la página
            titulo_pagina = soup.find('title')
            titulo_pagina = titulo_pagina.get_text() if titulo_pagina else nombre_fuente or url
            
            # Extraer secciones basadas en encabezados
            secciones = []
            encabezados = soup.find_all(['h1', 'h2', 'h3'])
            
            if not encabezados:
                # Si no hay encabezados, usar el contenido completo
                contenido = self.limpiar_texto(soup.get_text())
                if self._seccion_cumple_filtros(titulo_pagina + " - Contenido Principal", contenido):
                    secciones.append({
                        "titulo": f"{titulo_pagina} - Contenido Principal",
                        "contenido": contenido[:3000],
                        "fuente": nombre_fuente or url
                    })
            else:
                for i, encabezado in enumerate(encabezados):
                    titulo_seccion = self.limpiar_texto(encabezado.get_text())
                    if not titulo_seccion:
                        continue
                        
                    contenido = ""
                    siguiente = encabezado.find_next_sibling()
                    
                    # Recoger contenido hasta el siguiente encabezado
                    while siguiente and siguiente.name not in ['h1', 'h2', 'h3']:
                        if siguiente.name not in ['script', 'style']:
                            contenido += siguiente.get_text() + " "
                        siguiente = siguiente.find_next_sibling()
                    
                    contenido = self.limpiar_texto(contenido)
                    
                    if contenido and self._seccion_cumple_filtros(titulo_seccion, contenido):
                        secciones.append({
                            "titulo": f"{titulo_pagina} - {titulo_seccion}",
                            "contenido": contenido[:2000],  # Limitar tamaño
                            "fuente": nombre_fuente or url
                        })
            
            self.metadata_global["urls_procesadas"].append(url)
            self.gestor.log(f"Se encontraron {len(secciones)} secciones (filtradas)")
            return secciones
            
        except Exception as e:
            self.gestor.log(f"Error al procesar {url}: {e}", "error")
            self.metadata_global["urls_fallidas"].append({"url": url, "error": str(e)})
            return []
    
    def agregar_fuente(self, url, nombre_fuente=""):
        """Agrega una fuente de documentación"""
        secciones = self.extraer_secciones_de_url(url, nombre_fuente)
        if secciones:
            self.secciones_totales.extend(secciones)
            self.fuentes.append({
                "url": url,
                "nombre": nombre_fuente,
                "secciones_encontradas": len(secciones)
            })
        # Pequeña pausa para no sobrecargar servidores
        time.sleep(0.5)
    
    def generar_nombre_base(self, prefijo="proyecto"):
        """Genera nombre base con fecha y hora"""
        now = datetime.now()
        fecha_hora = now.strftime("%Y%m%d_%H%M%S")
        return f"{prefijo}_docs_{fecha_hora}"
    
    def guardar_contexto_proyecto(self, directorio_salida):
        """Guarda el contexto del proyecto en JSON"""
        contexto_file = os.path.join(directorio_salida, "contexto_proyecto.json")
        with open(contexto_file, 'w', encoding='utf-8') as f:
            json.dump(self.contexto_proyecto, f, ensure_ascii=False, indent=2)
        return contexto_file
    
    def guardar_txt_estructurado(self, nombre_base, directorio_salida):
        """Guarda en formato TXT estructurado"""
        nombre = os.path.join(directorio_salida, f"{nombre_base}_txt.txt")
        with open(nombre, 'w', encoding='utf-8') as f:
            f.write("CONTEXTUALIZACIÓN INTELIGENTE DE PROYECTO\n")
            f.write("="*60 + "\n")
            f.write(f"Proyecto: {self.contexto_proyecto['proyecto']['nombre']}\n")
            f.write(f"Fecha de generación: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
            f.write(f"Total de fuentes: {len(self.fuentes)}\n")
            f.write(f"Total de secciones: {len(self.secciones_totales)}\n")
            f.write(f"Fuentes desde caché: {len(self.metadata_global['urls_desde_cache'])}\n")
            
            # Mostrar tecnologías detectadas
            tecnologias = self.contexto_proyecto.get("tecnologias_detectadas", [])
            if tecnologias:
                f.write(f"Tecnologías detectadas: {', '.join(tecnologias)}\n")
            
            # Mostrar filtros aplicados
            if self.palabras_clave_incluir:
                f.write(f"Palabras clave de inclusión: {', '.join(self.palabras_clave_incluir)}\n")
            if self.palabras_clave_excluir:
                f.write(f"Palabras clave de exclusión: {', '.join(self.palabras_clave_excluir)}\n")
            
            f.write("="*60 + "\n\n")
            
            # Información del proyecto
            f.write("INFORMACIÓN DEL PROYECTO:\n")
            f.write("-" * 30 + "\n")
            f.write(f"Ruta: {self.contexto_proyecto['proyecto']['ruta']}\n")
            f.write(f"Archivos PHP encontrados: {len(self.contexto_proyecto['archivos']['php'])}\n")
            f.write(f"Archivos JS encontrados: {len(self.contexto_proyecto['archivos']['js'])}\n")
            f.write(f"Archivos Blade encontrados: {len(self.contexto_proyecto['archivos']['blade'])}\n\n")
            
            # Información del entorno (si está disponible)
            if "entorno" in self.contexto_proyecto:
                entorno = self.contexto_proyecto["entorno"]
                f.write("INFORMACIÓN DEL ENTORNO:\n")
                f.write("-" * 30 + "\n")
                f.write(f"Sistema Operativo: {entorno.get('sistema_operativo', 'No detectado')}\n")
                f.write(f"PHP: {entorno['versiones'].get('php', 'No detectado')}\n")
                f.write(f"Node: {entorno['versiones'].get('node', 'No detectado')}\n")
                f.write(f"Laravel: {entorno['versiones'].get('laravel', 'No detectado')}\n")
                f.write(f"Servidor Local: {entorno['herramientas'].get('servidor_local', 'Desconocido')}\n")
                f.write(f"APP_ENV: {entorno['variables_entorno'].get('APP_ENV', 'No especificado')}\n\n")
            
            # Estadísticas de caché
            if self.metadata_global['urls_desde_cache']:
                f.write("FUENTES DESDE CACHÉ:\n")
                for url in self.metadata_global['urls_desde_cache']:
                    f.write(f"- {url}\n")
                f.write("\n")
            
            # Listar fuentes procesadas
            f.write("FUENTES DE DOCUMENTACIÓN PROCESADAS:\n")
            for fuente in self.fuentes:
                f.write(f"- {fuente['nombre'] or fuente['url']} ({fuente['secciones_encontradas']} secciones)\n")
            f.write("\n" + "="*60 + "\n\n")
            
            # Secciones
            for i, seccion in enumerate(self.secciones_totales, 1):
                f.write(f"\n{'='*20} SECCIÓN {i} {'='*20}\n")
                f.write(f"TÍTULO: {seccion['titulo']}\n")
                f.write(f"FUENTE: {seccion['fuente']}\n")
                f.write("-" * 60 + "\n")
                f.write(f"{seccion['contenido']}\n\n")
        return nombre
    
    def guardar_markdown_estructurado(self, nombre_base, directorio_salida):
        """Guarda en formato Markdown estructurado"""
        nombre = os.path.join(directorio_salida, f"{nombre_base}_markdown.md")
        with open(nombre, 'w', encoding='utf-8') as f:
            f.write("# Contextualización Inteligente de Proyecto\n\n")
            f.write(f"**Proyecto:** {self.contexto_proyecto['proyecto']['nombre']}\n\n")
            f.write(f"**Fecha de generación:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
            f.write(f"**Total de fuentes:** {len(self.fuentes)}\n\n")
            f.write(f"**Total de secciones:** {len(self.secciones_totales)}\n\n")
            f.write(f"**Fuentes desde caché:** {len(self.metadata_global['urls_desde_cache'])}\n\n")
            
            # Mostrar tecnologías detectadas
            tecnologias = self.contexto_proyecto.get("tecnologias_detectadas", [])
            if tecnologias:
                f.write(f"**Tecnologías detectadas:** {', '.join(tecnologias)}\n\n")
            
            # Mostrar filtros aplicados
            if self.palabras_clave_incluir:
                f.write(f"**Palabras clave de inclusión:** {', '.join(self.palabras_clave_incluir)}\n\n")
            if self.palabras_clave_excluir:
                f.write(f"**Palabras clave de exclusión:** {', '.join(self.palabras_clave_excluir)}\n\n")
            
            f.write("---\n\n")
            
            # Información del proyecto
            f.write("## Información del Proyecto\n\n")
            f.write(f"- **Ruta:** {self.contexto_proyecto['proyecto']['ruta']}\n")
            f.write(f"- **Archivos PHP:** {len(self.contexto_proyecto['archivos']['php'])}\n")
            f.write(f"- **Archivos JS:** {len(self.contexto_proyecto['archivos']['js'])}\n")
            f.write(f"- **Archivos Blade:** {len(self.contexto_proyecto['archivos']['blade'])}\n\n")
            
            # Información del entorno (si está disponible)
            if "entorno" in self.contexto_proyecto:
                entorno = self.contexto_proyecto["entorno"]
                f.write("## Información del Entorno\n\n")
                f.write(f"- **Sistema Operativo:** {entorno.get('sistema_operativo', 'No detectado')}\n")
                f.write(f"- **PHP:** `{entorno['versiones'].get('php', 'No detectado')}`\n")
                f.write(f"- **Node:** `{entorno['versiones'].get('node', 'No detectado')}`\n")
                f.write(f"- **Laravel:** `{entorno['versiones'].get('laravel', 'No detectado')}`\n")
                f.write(f"- **Servidor Local:** {entorno['herramientas'].get('servidor_local', 'Desconocido')}\n")
                f.write(f"- **APP_ENV:** `{entorno['variables_entorno'].get('APP_ENV', 'No especificado')}`\n\n")
            
            # Estadísticas de caché
            if self.metadata_global['urls_desde_cache']:
                f.write("## Fuentes desde caché\n\n")
                for url in self.metadata_global['urls_desde_cache']:
                    f.write(f"- {url}\n")
                f.write("\n---\n\n")
            
            # Listar fuentes
            f.write("## Fuentes de Documentación Procesadas\n\n")
            for fuente in self.fuentes:
                f.write(f"- **{fuente['nombre'] or fuente['url']}** ({fuente['secciones_encontradas']} secciones)\n")
            f.write("\n---\n\n")
            
            # Secciones
            for i, seccion in enumerate(self.secciones_totales, 1):
                f.write(f"## {i}. {seccion['titulo']}\n\n")
                f.write(f"**Fuente:** {seccion['fuente']}\n\n")
                f.write(f"{seccion['contenido']}\n\n")
                f.write("---\n\n")
        return nombre
    
    def guardar_html_estructurado(self, nombre_base, directorio_salida):
        """Guarda en formato HTML estructurado"""
        nombre = os.path.join(directorio_salida, f"{nombre_base}_html.html")
        html_inicio = f"""
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Contextualización de Proyecto - {self.contexto_proyecto['proyecto']['nombre']}</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; }}
        .container {{ max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }}
        .header {{ background: #007acc; color: white; padding: 20px; border-radius: 5px; margin-bottom: 20px; }}
        .project-info, .env-info, .sources, .cache-info, .filters {{ background: #f8f9fa; padding: 15px; border-radius: 5px; margin: 20px 0; }}
        .section {{ margin: 30px 0; padding: 20px; border: 1px solid #e9ecef; border-radius: 5px; }}
        .section-title {{ color: #007acc; border-bottom: 2px solid #007acc; padding-bottom: 10px; }}
        .source-tag {{ background: #e9ecef; padding: 2px 8px; border-radius: 3px; font-size: 0.9em; }}
        .cache-tag {{ background: #d4edda; padding: 2px 8px; border-radius: 3px; font-size: 0.9em; color: #155724; }}
        .filter-tag {{ background: #fff3cd; padding: 2px 8px; border-radius: 3px; font-size: 0.9em; color: #856404; }}
        .tech-tag {{ background: #cce5ff; padding: 2px 8px; border-radius: 3px; font-size: 0.9em; color: #004085; }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>Contextualización Inteligente de Proyecto</h1>
            <h2>{self.contexto_proyecto['proyecto']['nombre']}</h2>
            <p><strong>Fecha de generación:</strong> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
            <p><strong>Total de fuentes:</strong> {len(self.fuentes)} | <strong>Total de secciones:</strong> {len(self.secciones_totales)}</p>
            <p><strong>Fuentes desde caché:</strong> {len(self.metadata_global['urls_desde_cache'])}</p>
        </div>
        
        """
        
        # Información del proyecto
        tecnologias = self.contexto_proyecto.get("tecnologias_detectadas", [])
        html_inicio += """
        <div class="project-info">
            <h3>Información del Proyecto</h3>
            <p><strong>Ruta:</strong> """ + self.contexto_proyecto['proyecto']['ruta'] + """</p>
            <p><strong>Archivos PHP:</strong> """ + str(len(self.contexto_proyecto['archivos']['php'])) + """</p>
            <p><strong>Archivos JS:</strong> """ + str(len(self.contexto_proyecto['archivos']['js'])) + """</p>
            <p><strong>Archivos Blade:</strong> """ + str(len(self.contexto_proyecto['archivos']['blade'])) + """</p>
"""
        
        if tecnologias:
            tech_tags = "".join([f'<span class="tech-tag">{tech}</span> ' for tech in tecnologias])
            html_inicio += f"<p><strong>Tecnologías detectadas:</strong> {tech_tags}</p>"
        
        html_inicio += """
        </div>
"""
        
        # Información del entorno (si está disponible)
        if "entorno" in self.contexto_proyecto:
            entorno = self.contexto_proyecto["entorno"]
            html_inicio += """
        <div class="env-info">
            <h3>Información del Entorno</h3>
            <p><strong>Sistema Operativo:</strong> """ + str(entorno.get('sistema_operativo', 'No detectado')) + """</p>
            <p><strong>PHP:</strong> <code>""" + str(entorno['versiones'].get('php', 'No detectado')) + """</code></p>
            <p><strong>Node:</strong> <code>""" + str(entorno['versiones'].get('node', 'No detectado')) + """</code></p>
            <p><strong>Laravel:</strong> <code>""" + str(entorno['versiones'].get('laravel', 'No detectado')) + """</code></p>
            <p><strong>Servidor Local:</strong> """ + str(entorno['herramientas'].get('servidor_local', 'Desconocido')) + """</p>
            <p><strong>APP_ENV:</strong> <code>""" + str(entorno['variables_entorno'].get('APP_ENV', 'No especificado')) + """</code></p>
        </div>
"""

        # Información de filtros
        if self.palabras_clave_incluir or self.palabras_clave_excluir:
            html_inicio += """
        <div class="filters">
            <h3>Filtros aplicados:</h3>
"""
            if self.palabras_clave_incluir:
                html_inicio += f"<p><strong>Incluir:</strong> {', '.join(self.palabras_clave_incluir)}</p>\n"
            if self.palabras_clave_excluir:
                html_inicio += f"<p><strong>Excluir:</strong> {', '.join(self.palabras_clave_excluir)}</p>\n"
            html_inicio += """
        </div>
"""
        
        # Información de caché
        if self.metadata_global['urls_desde_cache']:
            html_inicio += """
        <div class="cache-info">
            <h3>Fuentes desde caché:</h3>
            <ul>
"""
            for url in self.metadata_global['urls_desde_cache']:
                html_inicio += f"<li>{url}</li>\n"
            html_inicio += """
            </ul>
        </div>
"""
        
        # Listar fuentes
        html_inicio += """
        <div class="sources">
            <h3>Fuentes de Documentación Procesadas:</h3>
            <ul>
"""
        
        fuentes_html = ""
        for fuente in self.fuentes:
            fuentes_html += f"<li><strong>{fuente['nombre'] or fuente['url']}</strong> ({fuente['secciones_encontradas']} secciones)</li>\n"
        
        html_medio = """
            </ul>
        </div>
        
        <div class="sections">
"""
        
        # Secciones
        secciones_html = ""
        for i, seccion in enumerate(self.secciones_totales, 1):
            cache_tag = '<span class="cache-tag">Desde caché</span>' if seccion['fuente'] in self.metadata_global['urls_desde_cache'] else ''
            filter_tag = '<span class="filter-tag">Filtrado</span>' if (self.palabras_clave_incluir or self.palabras_clave_excluir) else ''
            secciones_html += f"""
            <div class="section">
                <h2 class="section-title">{i}. {seccion['titulo']}</h2>
                <p><span class="source-tag">Fuente: {seccion['fuente']}</span> {cache_tag} {filter_tag}</p>
                <div class="section-content">
                    <p>{seccion['contenido'].replace(chr(10), '<br>')}</p>
                </div>
            </div>
"""
        
        html_final = """
        </div>
    </div>
</body>
</html>
"""
        
        with open(nombre, 'w', encoding='utf-8') as f:
            f.write(html_inicio + fuentes_html + html_medio + secciones_html + html_final)
        return nombre
    
    def guardar_json_estructurado(self, nombre_base, directorio_salida):
        """Guarda en formato JSON estructurado"""
        nombre = os.path.join(directorio_salida, f"{nombre_base}_json.json")
        data = {
            "metadata": {
                "proyecto": self.contexto_proyecto['proyecto'],
                "fecha_generacion": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                "timestamp": datetime.now().isoformat(),
                "total_fuentes": len(self.fuentes),
                "total_secciones": len(self.secciones_totales),
                "fuentes_desde_cache": len(self.metadata_global['urls_desde_cache']),
                "tecnologias_detectadas": self.contexto_proyecto.get("tecnologias_detectadas", []),
                "filtros_aplicados": {
                    "incluir": self.palabras_clave_incluir,
                    "excluir": self.palabras_clave_excluir
                },
                "fuentes_procesadas": self.fuentes,
                "metadata_global": self.metadata_global
            },
            "contexto_proyecto": self.contexto_proyecto,
            "estadisticas": {
                "total_secciones": len(self.secciones_totales),
                "caracteres_totales": sum(len(s['contenido']) for s in self.secciones_totales),
                "palabras_totales": sum(len(s['contenido'].split()) for s in self.secciones_totales),
                "fuentes_por_tipo": {},
                "secciones_por_fuente": {}
            },
            "secciones": self.secciones_totales
        }
        
        # Calcular estadísticas por fuente
        for seccion in self.secciones_totales:
            fuente = seccion['fuente']
            if fuente not in data['estadisticas']['fuentes_por_tipo']:
                data['estadisticas']['fuentes_por_tipo'][fuente] = {
                    "secciones": 0,
                    "caracteres": 0,
                    "palabras": 0
                }
            data['estadisticas']['fuentes_por_tipo'][fuente]['secciones'] += 1
            data['estadisticas']['fuentes_por_tipo'][fuente]['caracteres'] += len(seccion['contenido'])
            data['estadisticas']['fuentes_por_tipo'][fuente]['palabras'] += len(seccion['contenido'].split())
            
            # Contar secciones por fuente
            if fuente not in data['estadisticas']['secciones_por_fuente']:
                data['estadisticas']['secciones_por_fuente'][fuente] = []
            data['estadisticas']['secciones_por_fuente'][fuente].append({
                "titulo": seccion['titulo'],
                "caracteres": len(seccion['contenido']),
                "palabras": len(seccion['contenido'].split())
            })
        
        with open(nombre, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        return nombre
    
    def guardar_csv_estructurado(self, nombre_base, directorio_salida):
        """Guarda en formato CSV"""
        nombre = os.path.join(directorio_salida, f"{nombre_base}_csv.csv")
        with open(nombre, 'w', newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            writer.writerow(['indice', 'titulo', 'fuente', 'desde_cache', 'filtro_aplicado', 'caracteres', 'palabras', 'contenido'])
            for i, seccion in enumerate(self.secciones_totales, 1):
                desde_cache = "Sí" if seccion['fuente'] in self.metadata_global['urls_desde_cache'] else "No"
                filtro_aplicado = "Sí" if (self.palabras_clave_incluir or self.palabras_clave_excluir) else "No"
                caracteres = len(seccion['contenido'])
                palabras = len(seccion['contenido'].split())
                writer.writerow([i, seccion['titulo'], seccion['fuente'], desde_cache, filtro_aplicado, caracteres, palabras, seccion['contenido'][:1000]])
        return nombre
    
    def guardar_xml_estructurado(self, nombre_base, directorio_salida):
        """Guarda en formato XML"""
        nombre = os.path.join(directorio_salida, f"{nombre_base}_xml.xml")
        root = ET.Element("contextualizacion_proyecto")
        
        # Metadata
        meta_elem = ET.SubElement(root, "metadata")
        proyecto_elem = ET.SubElement(meta_elem, "proyecto")
        nombre_elem = ET.SubElement(proyecto_elem, "nombre")
        nombre_elem.text = self.contexto_proyecto['proyecto']['nombre']
        fecha_elem = ET.SubElement(meta_elem, "fecha_generacion")
        fecha_elem.text = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        fuentes_elem = ET.SubElement(meta_elem, "total_fuentes")
        fuentes_elem.text = str(len(self.fuentes))
        secciones_elem = ET.SubElement(meta_elem, "total_secciones")
        secciones_elem.text = str(len(self.secciones_totales))
        cache_elem = ET.SubElement(meta_elem, "fuentes_desde_cache")
        cache_elem.text = str(len(self.metadata_global['urls_desde_cache']))
        
        # Tecnologías detectadas
        tecnologias = self.contexto_proyecto.get("tecnologias_detectadas", [])
        if tecnologias:
            tech_elem = ET.SubElement(meta_elem, "tecnologias_detectadas")
            tech_elem.text = ", ".join(tecnologias)
        
        # Filtros aplicados
        if self.palabras_clave_incluir or self.palabras_clave_excluir:
            filtros_elem = ET.SubElement(meta_elem, "filtros_aplicados")
            if self.palabras_clave_incluir:
                incluir_elem = ET.SubElement(filtros_elem, "incluir")
                incluir_elem.text = ", ".join(self.palabras_clave_incluir)
            if self.palabras_clave_excluir:
                excluir_elem = ET.SubElement(filtros_elem, "excluir")
                excluir_elem.text = ", ".join(self.palabras_clave_excluir)
        
        # Fuentes desde caché
        if self.metadata_global['urls_desde_cache']:
            cache_fuentes = ET.SubElement(root, "fuentes_desde_cache")
            for url in self.metadata_global['urls_desde_cache']:
                url_elem = ET.SubElement(cache_fuentes, "url")
                url_elem.text = url
        
        # Fuentes procesadas
        fuentes_cont_elem = ET.SubElement(root, "fuentes_documentacion")
        for fuente in self.fuentes:
            fuente_elem = ET.SubElement(fuentes_cont_elem, "fuente")
            nombre_elem = ET.SubElement(fuente_elem, "nombre")
            nombre_elem.text = fuente['nombre'] or fuente['url']
            secciones_count = ET.SubElement(fuente_elem, "secciones")
            secciones_count.text = str(fuente['secciones_encontradas'])
        
        # Secciones
        secciones_elem = ET.SubElement(root, "secciones")
        for i, seccion in enumerate(self.secciones_totales, 1):
            sec_elem = ET.SubElement(secciones_elem, "seccion")
            indice_elem = ET.SubElement(sec_elem, "indice")
            indice_elem.text = str(i)
            titulo_elem = ET.SubElement(sec_elem, "titulo")
            titulo_elem.text = seccion['titulo']
            fuente_elem = ET.SubElement(sec_elem, "fuente")
            fuente_elem.text = seccion['fuente']
            cache_elem = ET.SubElement(sec_elem, "desde_cache")
            cache_elem.text = "true" if seccion['fuente'] in self.metadata_global['urls_desde_cache'] else "false"
            filtro_elem = ET.SubElement(sec_elem, "filtro_aplicado")
            filtro_elem.text = "true" if (self.palabras_clave_incluir or self.palabras_clave_excluir) else "false"
            caracteres_elem = ET.SubElement(sec_elem, "caracteres")
            caracteres_elem.text = str(len(seccion['contenido']))
            palabras_elem = ET.SubElement(sec_elem, "palabras")
            palabras_elem.text = str(len(seccion['contenido'].split()))
            contenido_elem = ET.SubElement(sec_elem, "contenido")
            contenido_elem.text = seccion['contenido'][:1000]
        
        tree = ET.ElementTree(root)
        tree.write(nombre, encoding='utf-8', xml_declaration=True)
        return nombre
    
    def generar_todos_los_formatos(self, prefijo="proyecto"):
        """Genera todos los archivos en diferentes formatos"""
        if not self.secciones_totales:
            self.gestor.log("No hay secciones para guardar", "warning")
            return []
        
        # Obtener directorio de salida
        directorio_salida = self.gestor.obtener_directorio_salida(prefijo)
        self.gestor.log(f"Directorio de salida: {directorio_salida}")
        
        nombre_base = self.generar_nombre_base(prefijo)
        archivos_generados = []
        
        self.gestor.log("Generando archivos en diferentes formatos...")
        
        # Guardar contexto del proyecto
        contexto_file = self.guardar_contexto_proyecto(directorio_salida)
        archivos_generados.append(contexto_file)
        self.gestor.log(f"Guardado: {os.path.basename(contexto_file)}")
        
        # TXT estructurado
        archivo_txt = self.guardar_txt_estructurado(nombre_base, directorio_salida)
        archivos_generados.append(archivo_txt)
        self.gestor.log(f"Guardado: {os.path.basename(archivo_txt)}")
        
        # Markdown estructurado
        archivo_md = self.guardar_markdown_estructurado(nombre_base, directorio_salida)
        archivos_generados.append(archivo_md)
        self.gestor.log(f"Guardado: {os.path.basename(archivo_md)}")
        
        # HTML estructurado
        archivo_html = self.guardar_html_estructurado(nombre_base, directorio_salida)
        archivos_generados.append(archivo_html)
        self.gestor.log(f"Guardado: {os.path.basename(archivo_html)}")
        
        # JSON estructurado
        archivo_json = self.guardar_json_estructurado(nombre_base, directorio_salida)
        archivos_generados.append(archivo_json)
        self.gestor.log(f"Guardado: {os.path.basename(archivo_json)}")
        
        # CSV
        archivo_csv = self.guardar_csv_estructurado(nombre_base, directorio_salida)
        archivos_generados.append(archivo_csv)
        self.gestor.log(f"Guardado: {os.path.basename(archivo_csv)}")
        
        # XML
        archivo_xml = self.guardar_xml_estructurado(nombre_base, directorio_salida)
        archivos_generados.append(archivo_xml)
        self.gestor.log(f"Guardado: {os.path.basename(archivo_xml)}")
        
        return archivos_generados

def mostrar_menu_interactivo():
    """Muestra menú interactivo para configurar el proceso"""
    print("🤖 CONTEXTUALIZADOR INTELIGENTE DE PROYECTO")
    print("="*50)
    
    # Obtener directorio del proyecto
    proyecto_dir = input("Ruta del proyecto (Enter para usar actual): ").strip()
    if not proyecto_dir:
        proyecto_dir = "."
    
    # Crear instancia
    gestor = GestorArchivosOrganizado(proyecto_dir)
    contextualizador = ContextoProyectoInteligente(proyecto_dir, gestor)
    
    # 1. ESCANEAR ENTORNO (NUEVO)
    print("\n🌍 ESCANEANDO ENTORNO...")
    entorno = contextualizador.escanear_entorno()
    print(f"   Sistema: {entorno.get('sistema_operativo', 'Desconocido')}")
    print(f"   PHP: {entorno['versiones'].get('php', 'No detectado')}")
    print(f"   Node: {entorno['versiones'].get('node', 'No detectado')}")
    print(f"   Laravel: {entorno['versiones'].get('laravel', 'No detectado')}")
    print(f"   Servidor: {entorno['herramientas'].get('servidor_local', 'Desconocido')}")

    # 2. ESCANEAR PROYECTO (EXISTENTE)
    print("\n🔍 ESCANEANDO PROYECTO...")
    contexto = contextualizador.escanear_proyecto()
    
    # Mostrar tecnologías detectadas
    print(f"\n🎯 TECNOLOGÍAS DETECTADAS:")
    tecnologias = contexto["tecnologias_detectadas"]
    for i, tech in enumerate(tecnologias, 1):
        print(f"   {i}. {tech}")
    
    if not tecnologias:
        print("   ⚠️  No se detectaron tecnologías conocidas")
    
    # Sugerir URLs
    urls_sugeridas = contextualizador.sugerir_urls_documentacion()
    print(f"\n📚 URLs DE DOCUMENTACIÓN SUGERIDAS:")
    for i, (url, nombre) in enumerate(urls_sugeridas, 1):
        print(f"   {i}. {nombre}")
        print(f"      {url}")
    
    # Configurar filtros inteligentes
    print(f"\n🧠 CONFIGURANDO FILTROS INTELIGENTES...")
    contextualizador.configurar_filtros_inteligentes()
    
    # Preguntar si quiere personalizar
    personalizar = input("\n¿Quieres personalizar las URLs o filtros? (s/n): ").strip().lower()
    
    urls_a_usar = []
    if personalizar == 's':
        print("\n📝 URLs personalizadas (deja vacío para terminar):")
        while True:
            url = input("URL: ").strip()
            if not url:
                break
            nombre = input("Nombre (opcional): ").strip() or url
            urls_a_usar.append((url, nombre))
            print()
    else:
        urls_a_usar = urls_sugeridas
    
    # Procesar URLs
    print(f"\n📥 PROCESANDO DOCUMENTACIÓN...")
    for url, nombre in urls_a_usar:
        contextualizador.agregar_fuente(url, nombre)
    
    # Generar archivos
    if contextualizador.secciones_totales:
        prefijo = input(f"\n📄 Prefijo para archivos (Enter para '{contexto['proyecto']['nombre']}'): ").strip()
        if not prefijo:
            prefijo = contexto['proyecto']['nombre']
        
        print(f"\n💾 GENERANDO ARCHIVOS...")
        archivos = contextualizador.generar_todos_los_formatos(prefijo)
        
        if archivos:
            print(f"\n✅ ¡PROCESO COMPLETADO!")
            print(f"📂 Archivos generados en:")
            print(f"   {contextualizador.gestor.base_dir}/output/latest/")
            print(f"\n📄 Archivos creados:")
            for archivo in archivos:
                try:
                    tamano = os.path.getsize(archivo)
                    print(f"   📄 {os.path.basename(archivo)} ({tamano:,} bytes)")
                except:
                    print(f"   📄 {os.path.basename(archivo)}")
            
            print(f"\n💡 RECOMENDACIONES:")
            print(f"   • Usa el archivo JSON para mejor estructura")
            print(f"   • Los archivos se organizan por fecha")
            print(f"   • Sistema de limpieza automática activo")
            print(f"   • Caché semanal para optimizar descargas")
            
            # Mostrar estadísticas finales
            total_caracteres = sum(len(s['contenido']) for s in contextualizador.secciones_totales)
            total_palabras = sum(len(s['contenido'].split()) for s in contextualizador.secciones_totales)
            print(f"\n📊 ESTADÍSTICAS:")
            print(f"   • Secciones procesadas: {len(contextualizador.secciones_totales)}")
            print(f"   • Caracteres totales: {total_caracteres:,}")
            print(f"   • Palabras totales: {total_palabras:,}")
            print(f"   • Promedio por sección: {total_caracteres // len(contextualizador.secciones_totales):,} caracteres")
            
        else:
            print("\n❌ No se pudieron generar los archivos.")
    else:
        print("\n❌ No se encontraron secciones relevantes en la documentación.")

def main():
    """Función principal"""
    try:
        mostrar_menu_interactivo()
    except KeyboardInterrupt:
        print("\n\n⚠️  Proceso interrumpido por el usuario")
    except Exception as e:
        print(f"\n❌ Error inesperado: {e}")
        logging.error(f"Error inesperado: {e}", exc_info=True)

if __name__ == "__main__":
    main()
