from datetime import datetime
from enum import Enum
from typing import TypeVar, Optional

from langfuse.langchain import CallbackHandler
from openkosmos_core.common.model import BaseConfig
from pydantic import BaseModel


class AIBaseConfig(BaseConfig):
    pass


AI_CONFIG_T = TypeVar("AI_CONFIG_T", bound=AIBaseConfig)


class RunConfigConfigurable(BaseModel):
    thread_id: Optional[str] = datetime.now().strftime("%Y%m%d-%H%M%S")


class RunConfigMetadata(BaseModel):
    langfuse_session_id: Optional[str] = None
    langfuse_user_id: Optional[str] = "dev"
    langfuse_tags: Optional[list[str]] = None


class RunConfig(BaseModel):
    run_name: str
    configurable: RunConfigConfigurable = RunConfigConfigurable()
    recursion_limit: int = 13
    metadata: Optional[RunConfigMetadata] = None

    def to_config(self, callbacks: list = None):
        return {
            "run_name": self.run_name,
            "configurable": self.configurable.model_dump(exclude_none=True),
            "recursion_limit": self.recursion_limit,
            "metadata": None if self.metadata is None else self.metadata.model_dump(exclude_none=True),
            "callbacks": [CallbackHandler()] if callbacks is None else callbacks
        }


class SearchResult(BaseModel):
    id: str
    content: Optional[str] = None
    similarity_score: float = 0
    relevance_score: Optional[float] = 0
    metadata: Optional[dict] = None


class RelevanceDocument(BaseModel):
    text: str


class RelevanceResult(BaseModel):
    index: int
    relevance_score: float
    document: Optional[RelevanceDocument] = None


class RerankResult(BaseModel):
    results: list[RelevanceResult]
    metadata: Optional[dict] = None


class EmbeddingData(BaseModel):
    index: int
    object: str = "embedding"
    embedding: list[float]


class EmbeddingResult(BaseModel):
    object: str = "list"
    data: list[EmbeddingData]
    model: str


class LogMode(str, Enum):
    DEFAULT = "default"
    ALL = "all"
    NONE = "none"
