from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime
from typing import Callable, List, Optional, Protocol


class FactResolver(Protocol):
    def resolve(self, fact_id: str) -> Optional["BaseFact"]:
        raise NotImplementedError


@dataclass
class BaseFact:
    id: str
    source_id: str
    turn_id: Optional[str] = None
    user_id: Optional[str] = None
    agent_id: Optional[str] = None
    embedding: Optional[List[float]] = None
    prev_id: Optional[str] = None
    next_id: Optional[str] = None
    created_at: Optional[datetime] = None
    _resolver: Optional[FactResolver] = field(default=None, repr=False, compare=False)
    _deleter: Optional[Callable[[str], None]] = field(default=None, repr=False, compare=False)
    _statement_service: Optional[object] = field(default=None, repr=False, compare=False)
    _notion_service: Optional[object] = field(default=None, repr=False, compare=False)

    def __post_init__(self) -> None:
        if not self.id:
            raise ValueError("BaseFact requires id")
        if not self.source_id or not str(self.source_id).strip():
            raise ValueError("BaseFact requires source_id")

    def prev(self) -> Optional["BaseFact"]:
        if self._resolver is None or not self.prev_id:
            return None
        return self._resolver.resolve(self.prev_id)

    def next(self) -> Optional["BaseFact"]:
        if self._resolver is None or not self.next_id:
            return None
        return self._resolver.resolve(self.next_id)

    def delete(self) -> None:
        self._delete_fact()

    def _delete_fact(self) -> None:
        if not self.id:
            raise ValueError("BaseFact requires id")
        if self._deleter is None:
            raise NotImplementedError("BaseFact delete requires deleter")
        self._deleter(self.id)


__all__ = ["BaseFact", "FactResolver"]
