"""
@RAG_CONTEXT
{
  "archivo": "src/rag_indexer/main.py",
  "lineas": 158,
  "tokens_estimados": 1510,
  "hash_contenido": "5dc407e1d7a3e6ec5324b3b28f92f203a8889de2593598f6e07ac3dc244b489a",
  "creacion": "2026-03-04",
  "modificacion": "2026-03-04",
  "tags": [
    "datetime",
    "argparse",
    "COMMENT_SYNTAX",
    ".config",
    "json",
    ".file_parser",
    ".hook_manager",
    "os",
    ".llm_client",
    "get_llm_descriptions",
    "install_git_hook",
    "pathspec"
  ],
  "descripcion_corta": "",
  "descripcion_larga": ""
}
"""
import os
import json
import datetime
import argparse
import pathspec

from .config import COMMENT_SYNTAX, DEFAULT_EXCLUDES, API_KEYS, ACTIVE_LLM
from .file_parser import (
    split_metadata_and_code,
    extract_dependencies,
    calculate_hash,
    inject_metadata,
)
from .llm_client import get_llm_descriptions
from .hook_manager import install_git_hook


def load_gitignore(root_dir):
    patterns = [
        'node_modules/', '.git/', 'venv/', '.env',
        '__pycache__/', '*.min.js', '*.min.css',
    ]
    gitignore_path = os.path.join(root_dir, '.gitignore')
    if os.path.exists(gitignore_path):
        with open(gitignore_path, 'r', encoding='utf-8') as f:
            patterns.extend(f.read().splitlines())
    return pathspec.PathSpec.from_lines(pathspec.patterns.GitWildMatchPattern, patterns)


def is_valid_file(filepath, spec, root_dir):
    rel_path = os.path.relpath(filepath, root_dir)
    if spec.match_file(rel_path):
        return False
    ext = os.path.splitext(filepath)[1].lower()
    if ext in DEFAULT_EXCLUDES or ext not in COMMENT_SYNTAX:
        return False
    return True


def process_single_file(filepath, root_dir, is_scaffold=False):
    if not is_scaffold and not API_KEYS.get(ACTIVE_LLM, ""):
        print(f"⚠️ No se detectó API Key para {ACTIVE_LLM.upper()}. Entrando en modo andamiaje automático...")
        is_scaffold = True

    ext = os.path.splitext(filepath)[1].lower()
    rel_path = os.path.relpath(filepath, root_dir).replace('\\', '/')

    with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
        original_content = f.read()

    old_metadata, clean_code = split_metadata_and_code(original_content, ext)
    code_hash = calculate_hash(clean_code)
    today = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d")

    metadata = {
        "archivo": rel_path,
        "lineas": len(clean_code.splitlines()),
        "tokens_estimados": len(clean_code) // 4,
        "hash_contenido": code_hash,
        "creacion": old_metadata.get("creacion", today) if old_metadata else today,
        "modificacion": today,
        "tags": extract_dependencies(clean_code, ext),
        "descripcion_corta": old_metadata.get("descripcion_corta", "") if old_metadata else "",
        "descripcion_larga": old_metadata.get("descripcion_larga", "") if old_metadata else "",
    }

    needs_update = not old_metadata or old_metadata.get("hash_contenido") != code_hash or not metadata["descripcion_corta"]

    if needs_update:
        if is_scaffold:
            print(f"  Preparando andamiaje para: {rel_path}")
            metadata["descripcion_corta"] = ""
            metadata["descripcion_larga"] = ""
        else:
            print(f"  Llamando a LLM para contexto de: {rel_path}")
            corta, larga = get_llm_descriptions(clean_code, rel_path)
            metadata["descripcion_corta"], metadata["descripcion_larga"] = corta, larga
    else:
        print(f"  Sin cambios (hash idéntico): {rel_path}")

    inject_metadata(filepath, original_content, clean_code, metadata, ext)
    return metadata


def run_indexer(is_scaffold=False):
    project_root = os.getcwd()
    modo = "Andamiaje (Scaffold)" if is_scaffold else "Completo (API LLM)"
    print(f"Iniciando motor de indexación RAG en: {project_root} | Modo: {modo}")

    spec = load_gitignore(project_root)
    master_tree = []
    total_tokens = 0
    total_files = 0

    for subdir, dirs, files in os.walk(project_root):
        dirs[:] = [
            d for d in dirs
            if not spec.match_file(
                os.path.relpath(os.path.join(subdir, d), project_root) + '/'
            )
        ]
        for file in files:
            filepath = os.path.join(subdir, file)
            if is_valid_file(filepath, spec, project_root):
                try:
                    meta = process_single_file(filepath, project_root, is_scaffold=is_scaffold)
                    master_tree.append(meta)
                    total_tokens += meta['tokens_estimados']
                    total_files += 1
                except Exception as e:
                    print(f"Error en {filepath}: {e}")

    instrucciones_agente = (
        "Hola Agente. Tu misión es iterar sobre el arreglo 'arbol' de este JSON. "
        "Busca los archivos donde 'descripcion_corta' o 'descripcion_larga' estén vacíos. "
        "Abre esos archivos en el disco, lee su código fuente, y completa sus bloques de comentarios "
        "en la cabecera con un resumen técnico. NO modifiques el código original ni el 'hash_contenido'. "
        "Cuando hayas terminado de procesar y guardar todos los archivos vacíos, "
        "ejecuta el comando 'rag-indexer run' en esta terminal para sellar el trabajo."
    )

    master_index = {
        "_INSTRUCCIONES_PARA_EL_AGENTE": instrucciones_agente,
        "proyecto": os.path.basename(project_root) or "Proyecto_RAG",
        "ultima_indexacion": datetime.datetime.now(datetime.timezone.utc).isoformat() + "Z",
        "estadisticas": {
            "total_archivos": total_files,
            "total_tokens_estimados": total_tokens
        },
        "arbol": master_tree
    }

    output_path = os.path.join(project_root, 'rag-indexer.json')
    with open(output_path, 'w', encoding='utf-8') as f:
        json.dump(master_index, f, indent=2, ensure_ascii=False)

    print(f"\nOperación completada. Archivos: {total_files} | Tokens: ~{total_tokens}")


def main():
    parser = argparse.ArgumentParser(
        description="RAG Context Indexer - DevTool para optimización de contexto en LLMs"
    )
    subparsers = parser.add_subparsers(dest="command", help="Comandos disponibles")
    subparsers.add_parser("init", help="Instala el Git Pre-commit Hook")
    subparsers.add_parser("prepare", help="Fase 1: Inyecta plantillas vacías (Scaffold) para agentes locales")
    subparsers.add_parser("run", help="Fase 2: Ejecuta escaneo y llama a la API (Flujo normal/Sellado)")

    args = parser.parse_args()

    if args.command == "init":
        install_git_hook()
    elif args.command == "prepare":
        run_indexer(is_scaffold=True)
    elif args.command == "run":
        run_indexer(is_scaffold=False)
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
