import os
from dotenv import load_dotenv
from sqlalchemy import Column, String
from src.ConexionSql.Base_conexion import ConexionBase
from src.base import Base
from src.Security.GenerarIDs import GeneradorIDUnico
from src.Llms.Embedders.Openai_embedder import OpenAIEmbedder
from src.ApiKeys.openai_apikey import OpenAICredencial

# ----------------------
# Cargar configuración desde .env si se requiere
# ----------------------
from entrypoint import ENV_PATH
load_dotenv(ENV_PATH)

# ----------------------
# MODELO (SQLAlchemy)
# ----------------------

class OpenAIEmbedderModel(Base):
    __tablename__ = "openai_embedders"

    id = Column(String, primary_key=True)
    api_key_id = Column(String, nullable=False)  # ID de la credencial asociada (clave foránea lógica)
    model = Column(String, nullable=False)

# ----------------------
# MAPPER
# ----------------------

class OpenAIEmbedderMapper:
    @staticmethod
    def to_dict(obj: OpenAIEmbedder) -> dict:
        return {
            "id": obj.id,
            "api_key_id": obj.client.credencial.id,
            "model": obj.model
        }

    @staticmethod
    def from_dict(data: dict, credencial: OpenAICredencial) -> OpenAIEmbedder:
        return OpenAIEmbedder(
            id=data["id"],
            credencial=credencial,
            model=data["model"]
        )

    @staticmethod
    def from_model(model: OpenAIEmbedderModel, credencial: OpenAICredencial) -> OpenAIEmbedder:
        return OpenAIEmbedder(
            id=model.id,
            credencial=credencial,
            model=model.model
        )

# ----------------------
# REPO
# ----------------------

class OpenAIEmbedderRepo:
    def __init__(self, conexion: ConexionBase):
        self.session = conexion.get_session()

    def add(self, embedder: OpenAIEmbedder) -> str:
        data = OpenAIEmbedderMapper.to_dict(embedder)
        model = OpenAIEmbedderModel(**data)
        self.session.add(model)
        self.session.commit()
        return model.id

    def get_by_id(self, id_: str, credencial: OpenAICredencial) -> OpenAIEmbedder | None:
        model = self.session.get(OpenAIEmbedderModel, id_)
        return OpenAIEmbedderMapper.from_model(model, credencial) if model else None

    def get_all(self, credencial_loader: callable) -> list[OpenAIEmbedder]:
        """
        :param credencial_loader: función que recibe un api_key_id y devuelve una instancia de OpenAICredencial
        """
        models = self.session.query(OpenAIEmbedderModel).all()
        return [
            OpenAIEmbedderMapper.from_model(m, credencial_loader(m.api_key_id))
            for m in models
        ]
