from src.TextManager.biblioteca import Biblioteca
from src.TextManager.biblioteca_mmr import BibliotecaRepo
from src.Llms.Embedders.Openai_embedder import OpenAIEmbedder
from src.ApiKeys.openai_apikey_mmr import OpenAICredencialRepo
from src.ConexionSql.Postgres_conexion import PostgresConexion
from src.TextManager.nota import Nota
from src.TextManager.notas_mmr import generar_tabla_nota_para_biblioteca, NotaRepo
from sqlalchemy import MetaData
from backend.schemas.text_manager_schema import NotaInput



def crear_biblioteca(nombre_biblioteca: str, conexion: PostgresConexion, descripcion: str = None):
    print("[INICIO] Creando biblioteca...")

    try:
        print("[Paso 1] Obteniendo credencial...")
        cred_repo = OpenAICredencialRepo(conexion)
        credencial = cred_repo.get_by_id("OPAK20250513-61b29978b7604031014")
        print("[OK] Credencial obtenida:", credencial.titulo if credencial else "❌ None")

        print("[Paso 2] Instanciando embedder...")
        embedder = OpenAIEmbedder(credencial, model="text-embedding-3-large")
        print("[OK] Embedder instanciado")

        print("[Paso 3] Instanciando biblioteca...")
        biblioteca = Biblioteca(
            nombre=nombre_biblioteca,
            embedder=embedder,
            descripcion=descripcion
        )
        print(f"[OK] Biblioteca instanciada con ID: {biblioteca.id}")

        print("[Paso 4] Guardando en base de datos...")
        repo = BibliotecaRepo(conexion)
        repo.add(biblioteca=biblioteca)
        print("[OK] Biblioteca guardada")

        print("[Paso 5] Generando modelo de notas...")
        biblioteca.generar_modelo_notas(conexion)
        print("[OK] Modelo de notas generado")

        print("[FIN] Biblioteca creada correctamente")
        return {
            "mensaje": f"Biblioteca '{nombre_biblioteca}' creada con éxito.",
            "id": biblioteca.id
        }

    except Exception as e:
        print("[ERROR] Ocurrió una excepción:", str(e))
        raise


def listar_bibliotecas(conexion: PostgresConexion) -> list[dict]:
    repo = BibliotecaRepo(conexion)
    bibliotecas: list[Biblioteca] = repo.get_all()
    return [
        {
            "id": b.id,
            "nombre": b.nombre,
            "descripcion": b.descripcion,
            "vector_dim": b.vector_dim
        }
        for b in bibliotecas
    ]

def agregar_nota_a_biblioteca(
    conexion: PostgresConexion,
    biblioteca_id: str,
    titulo: str,
    texto: str = "",
    tags: list[str] = None,
    conexiones: list[str] = None,
    resumen: str = ""
):

    # Obtener la biblioteca
    repo_biblioteca = BibliotecaRepo(conexion)
    biblioteca = repo_biblioteca.get_by_id(biblioteca_id)
    if biblioteca is None:
        raise ValueError(f"No se encontró la biblioteca con ID {biblioteca_id}")

    # Crear objeto Nota
    nota = Nota(
        titulo=titulo,
        texto=texto,
        tags=tags or [],
        conexiones=conexiones or [],
        resumen=resumen or "",
        # vector=biblioteca.embedder.embed_text(texto),
        # vector_resumen=biblioteca.embedder.embed_text(resumen) if resumen else None
    )
    # Mostrar atributos seguros
    print(
        f"[DEBUG] Nota creada: titulo='{nota.titulo}', "
        f"texto_len={len(nota.texto)}, "
        f"tags={len(nota.tags)}, "
        f"conexiones={len(nota.conexiones)}, "
        f"resumen_len={len(nota.resumen)}"
    )

    # Preparar tabla y modelo de nota
    metadata = MetaData()
    tabla, ModeloNota = generar_tabla_nota_para_biblioteca(
        biblioteca.nombre,
        biblioteca.vector_dim,
        metadata
    )
    metadata.create_all(conexion.get_engine())

    # Guardar la nota
    repo_nota = NotaRepo(conexion.get_session(), ModeloNota)
    nota_id = repo_nota.add(nota)

    resultado = {
        "mensaje": f"Nota '{titulo}' agregada con éxito a la biblioteca '{biblioteca.nombre}'.",
        "nota_id": nota_id
    }

    print(f"[SUCCESS] {resultado['mensaje']}")
    return resultado


def listar_notas_de_biblioteca(conexion: PostgresConexion, biblioteca_id: str) -> list[dict]:
    repo_biblioteca = BibliotecaRepo(conexion)
    biblioteca = repo_biblioteca.get_by_id(biblioteca_id)
    if not biblioteca:
        raise ValueError(f"No se encontró la biblioteca con ID: {biblioteca_id}")

    metadata = MetaData()
    tabla, ModeloNota = generar_tabla_nota_para_biblioteca(biblioteca.nombre, biblioteca.vector_dim, metadata)
    metadata.create_all(conexion.get_engine())

    repo_nota = NotaRepo(conexion.get_session(), ModeloNota)
    notas = repo_nota.get_all()
    return [
        {
            "id": n.id,
            "titulo": n.titulo,
            "tags": n.tags,
            "texto": n.texto,
            "resumen": n.resumen,
            "conexiones": n.conexiones
        }
        for n in notas
    ]


def eliminar_nota(conexion: PostgresConexion, biblioteca_id: str, nota_id: str) -> dict:
    repo_biblioteca = BibliotecaRepo(conexion)
    biblioteca = repo_biblioteca.get_by_id(biblioteca_id)
    if not biblioteca:
        raise ValueError(f"No se encontró la biblioteca con ID: {biblioteca_id}")

    metadata = MetaData()
    _, ModeloNota = generar_tabla_nota_para_biblioteca(biblioteca.nombre, biblioteca.vector_dim, metadata)
    metadata.create_all(conexion.get_engine())

    repo_nota = NotaRepo(conexion.get_session(), ModeloNota)
    fue_eliminada = repo_nota.delete_by_id(nota_id)

    if fue_eliminada:
        return {"mensaje": f"Nota '{nota_id}' eliminada correctamente."}
    else:
        raise ValueError(f"No se encontró la nota con ID: {nota_id}")


def actualizar_nota(conexion: PostgresConexion, biblioteca_id: str, nota_id: str, nota_input: NotaInput) -> dict:
    repo_biblioteca = BibliotecaRepo(conexion)
    biblioteca = repo_biblioteca.get_by_id(biblioteca_id)
    if not biblioteca:
        raise ValueError(f"No se encontró la biblioteca con ID: {biblioteca_id}")

    metadata = MetaData()
    _, ModeloNota = generar_tabla_nota_para_biblioteca(biblioteca.nombre, biblioteca.vector_dim, metadata)
    metadata.create_all(conexion.get_engine())

    repo_nota = NotaRepo(conexion.get_session(), ModeloNota)
    nota_actualizada = Nota(
        titulo=nota_input.titulo,
        texto=nota_input.texto,
        tags=nota_input.tags or [],
        conexiones=nota_input.conexiones or [],
        resumen=nota_input.resumen or ""
    )
    fue_actualizada = repo_nota.update(nota_id, nota_actualizada)

    if fue_actualizada:
        return {"mensaje": f"Nota '{nota_id}' actualizada correctamente."}
    else:
        raise ValueError(f"No se encontró la nota con ID: {nota_id}")
