from __future__ import annotations

from datetime import datetime
from typing import Optional, List

from analogai.foundation.modules.fact.basefact import BaseFact
from analogai.foundation.modules.fact.enums.fact_reference_type import FactReferenceType
from analogai.foundation.modules.fact.notion_fact import NotionFact
from analogai.foundation.modules.fact.direct_statement_fact import DirectStatementFact
from analogai.foundation.modules.fact.hypothetical_statement_fact import (
    HypotheticalStatementFact,
)


def build_fact(
    *,
    id: str,
    turn_id: Optional[str] = None,
    statement_id: Optional[str] = None,
    notion_id: Optional[str] = None,
    reference_type: Optional[str] = None,
    user_id: Optional[str] = None,
    agent_id: Optional[str] = None,
    text: str = "",
    embedding: Optional[List[float]] = None,
    source_id: Optional[str] = None,
    prev_id: Optional[str] = None,
    next_id: Optional[str] = None,
    created_at: Optional[datetime] = None,
) -> BaseFact:
    if not source_id or not str(source_id).strip():
        raise ValueError("Fact requires source_id")
    ref = str(reference_type).upper() if reference_type else None
    if ref == FactReferenceType.STATEMENT.value:
        if not statement_id:
            raise ValueError("DirectStatementFact requires statement_id")
        fact = DirectStatementFact(
            id=id,
            turn_id=turn_id,
            statement_id=statement_id,
            user_id=user_id,
            agent_id=agent_id,
            embedding=embedding,
            source_id=source_id,
            prev_id=prev_id,
            next_id=next_id,
            created_at=created_at,
        )
        if text:
            setattr(fact, "text", text)
        return fact
    if ref == FactReferenceType.HYPOTHETICAL_STATEMENT.value:
        if not statement_id:
            raise ValueError("HypotheticalStatementFact requires statement_id")
        fact = HypotheticalStatementFact(
            id=id,
            turn_id=turn_id,
            statement_id=statement_id,
            user_id=user_id,
            agent_id=agent_id,
            embedding=embedding,
            source_id=source_id,
            prev_id=prev_id,
            next_id=next_id,
            created_at=created_at,
        )
        if text:
            setattr(fact, "text", text)
        return fact
    if ref == FactReferenceType.NOTION.value:
        if not notion_id:
            raise ValueError("NotionFact requires notion_id")
        fact = NotionFact(
            id=id,
            turn_id=turn_id,
            notion_id=notion_id,
            user_id=user_id,
            agent_id=agent_id,
            embedding=embedding,
            source_id=source_id,
            prev_id=prev_id,
            next_id=next_id,
            created_at=created_at,
        )
        if text:
            setattr(fact, "text", text)
        return fact
    if statement_id:
        fact = DirectStatementFact(
            id=id,
            turn_id=turn_id,
            statement_id=statement_id,
            user_id=user_id,
            agent_id=agent_id,
            embedding=embedding,
            source_id=source_id,
            prev_id=prev_id,
            next_id=next_id,
            created_at=created_at,
        )
        if text:
            setattr(fact, "text", text)
        return fact
    if notion_id:
        fact = NotionFact(
            id=id,
            turn_id=turn_id,
            notion_id=notion_id,
            user_id=user_id,
            agent_id=agent_id,
            embedding=embedding,
            source_id=source_id,
            prev_id=prev_id,
            next_id=next_id,
            created_at=created_at,
        )
        if text:
            setattr(fact, "text", text)
        return fact
    fact = BaseFact(
        id=id,
        turn_id=turn_id,
        user_id=user_id,
        agent_id=agent_id,
        embedding=embedding,
        source_id=source_id,
        prev_id=prev_id,
        next_id=next_id,
        created_at=created_at,
    )
    if text:
        setattr(fact, "text", text)
    return fact


__all__ = ["build_fact"]
