# src/agix/cli/qualia_shell.py
"""Shell interactivo para QualiaSpirit."""

if __package__ in {None, ""}:  # pragma: no cover - permite ejecución como script
    import sys
    from pathlib import Path

    _current_file = Path(__file__).resolve()
    for _parent in (_current_file.parent, *_current_file.parents):
        if (_parent / "pyproject.toml").exists() or (_parent / ".git").exists():
            _project_root = _parent
            break
    else:
        _project_root = _current_file.parents[2]
    _src_root = _project_root / "src"
    for _path in (_project_root, _src_root):
        _path_str = str(_path)
        if _path_str not in sys.path:
            sys.path.insert(0, _path_str)
    from agix._script_utils import bootstrap_script_environment

    bootstrap_script_environment("__main__", str(_current_file))

import argparse
import json
from pathlib import Path
from typing import Optional

from agix.qualia.spirit import QualiaSpirit
from agix.identity import PersonalityProfile
from agix.security.blocker import verificar
from agix.adapters import GPTQualiaAdapter

HELP_TEXT = (
    "Comandos disponibles:\n"
    "  exp <evento>;<carga>;<emocion> - Registrar una experiencia\n"
    "  clasifica <concepto>              - Categorizar un concepto\n"
    "  crea <c1,c2,...>                  - Fusionar conceptos\n"
    "  reflexiona                        - Mostrar reflexion actual\n"
    "  diario                            - Listar recuerdos\n"
    "  guardar <ruta>                   - Guardar estado\n"
    "  cargar <ruta>                    - Cargar estado\n"
    "  gpt <mensaje>                    - Consultar al modelo GPT\n"
    "  motor <texto>                   - Consultar al motor lógico\n"
    "  meta                             - Evaluar coherencia y ética\n"
    "  dialogo                           - Mostrar historial de diálogo\n"
    "  salir                             - Terminar la sesión"
)


def handle_command(spirit: QualiaSpirit, command: str) -> str:
    """Procesa un comando de la shell.

    Parameters
    ----------
    spirit: QualiaSpirit
        Instancia sobre la cual actuar.
    command: str
        Texto introducido por el usuario.

    Returns
    -------
    str
        Mensaje de respuesta. Si retorna "exit" se finaliza el bucle.
    """
    command = command.strip()
    if not command:
        return ""

    if not verificar(command):
        spirit.memoria.registrar("bloqueo", command, "", False)
        return "Comando bloqueado."

    if command in {"salir", "exit", "quit"}:
        return "exit"

    if command == "reflexiona":
        return spirit.reflexionar()

    if command == "diario":
        return str(spirit.diario())

    if command == "dialogo":
        return str(spirit.memoria.manager.dialogos)

    if command == "meta":
        report = spirit.metaevaluar()
        return str(report)

    if command.startswith("guardar "):
        ruta = command.split(" ", 1)[1].strip()
        if ruta:
            spirit.guardar_estado(ruta)
            return "Estado guardado."
        return "Debes indicar una ruta"

    if command.startswith("cargar "):
        ruta = command.split(" ", 1)[1].strip()
        if ruta:
            spirit.cargar_estado(ruta)
            return "Estado cargado."
        return "Debes indicar una ruta"

    if command.startswith("gpt "):
        mensaje = command.split(" ", 1)[1].strip()
        if mensaje:
            adapter = GPTQualiaAdapter(lambda m: m)
            return adapter.generate_reply(mensaje)
        return "Debes indicar un mensaje"

    if command.startswith("motor "):
        texto = command.split(" ", 1)[1].strip()
        if texto:
            try:
                return spirit.usar_motor(texto)
            except ValueError as exc:
                return str(exc)
        return "Debes indicar un texto"

    if command.startswith("clasifica "):
        concepto = command.split(" ", 1)[1].strip()
        if concepto:
            return spirit.clasificar_concepto(concepto)
        return "Debes indicar un concepto"

    if command.startswith("crea "):
        payload = command.split(" ", 1)[1].strip()
        if payload:
            bases = [c.strip() for c in payload.split(",") if c.strip()]
            try:
                return spirit.crear_concepto(bases)
            except ValueError as exc:
                return str(exc)
        return "Debes indicar al menos dos conceptos separados por coma"

    if command.startswith("exp "):
        payload = command[4:].strip()
        try:
            evento, carga, emocion = [p.strip() for p in payload.split(";")]
            spirit.experimentar(evento, float(carga), emocion)
            return "Evento registrado."
        except ValueError:
            return "Formato inválido. Usa: exp <evento>;<carga>;<emocion>"

    return HELP_TEXT


def run_shell(args: argparse.Namespace) -> None:
    """Inicia un loop interactivo con :class:`QualiaSpirit`."""
    profile = None
    if args.personality:
        data = None
        p = Path(args.personality)
        if p.is_file():
            data = json.loads(p.read_text())
        else:
            defaults_path = Path(__file__).resolve().parents[2] / "agix" / "identity" / "perfiles.json"
            if defaults_path.is_file():
                defaults = json.loads(defaults_path.read_text())
                data = defaults.get(args.personality)
        if data:
            profile = PersonalityProfile(**data)
    spirit = QualiaSpirit(
        nombre=args.name,
        edad_aparente=args.age,
        personality=profile,
    )

    if args.replay:
        spirit.cargar_estado(args.replay)
        spirit.reentrenar_desde_memoria()

    print("\n🌈 Bienvenido al Qualia Shell. Escribe 'ayuda' para ver comandos.\n")
    while True:
        try:
            user_input = input("qualia> ")
        except EOFError:
            print()
            break

        if user_input.strip() == "ayuda":
            print(HELP_TEXT)
            continue

        response = handle_command(spirit, user_input)
        if response == "exit":
            break
        if response:
            print(response)
        spirit.memoria.manager.registrar_dialogo(user_input, response or "")

    print("Hasta pronto. ✨")


def build_parser(parser: Optional[argparse.ArgumentParser] = None) -> argparse.ArgumentParser:
    """Construye el parser para el subcomando ``qualia``."""
    if parser is None:
        parser = argparse.ArgumentParser(description="Shell interactivo para QualiaSpirit")

    parser.add_argument("--name", type=str, default="Qualia", help="Nombre de la entidad")
    parser.add_argument("--age", type=int, default=7, help="Edad aparente")
    parser.add_argument(
        "--replay",
        type=str,
        default="",
        metavar="RUTA",
        help="Reentrena emociones desde el archivo indicado",
    )
    parser.add_argument(
        "--personality",
        type=str,
        default="",
        metavar="PERFIL",
        help="Nombre o ruta a un perfil de personalidad",
    )
    return parser


__all__ = ["run_shell", "build_parser", "handle_command"]
