"""Core domain models for Sulci."""

from datetime import UTC, datetime
from enum import StrEnum
from uuid import uuid4

from pydantic import BaseModel, Field


class AtomType(StrEnum):
    """Types of knowledge atoms."""

    FACT = "fact"
    DECISION = "decision"
    PREFERENCE = "preference"
    ENTITY = "entity"
    RELATIONSHIP = "relationship"
    CONTEXT = "context"
    INSTRUCTION = "instruction"


class ConflictStatus(StrEnum):
    """Status of a knowledge conflict."""

    OPEN = "open"
    RESOLVED = "resolved"
    DISMISSED = "dismissed"


class ConflictType(StrEnum):
    """How the conflict was detected."""

    CONTRADICTORY_VALUE = "contradictory_value"
    SEMANTIC_CONTRADICTION = "semantic_contradiction"


class VerificationStatus(StrEnum):
    """Verification state of a knowledge atom."""

    UNVERIFIED = "unverified"
    VERIFIED = "verified"
    EXPIRED = "expired"


class ProjectType(StrEnum):
    """Type of project — controls PII handling."""

    STANDARD = "standard"
    PRIVATE = "private"


class DataMode(StrEnum):
    """Data residency mode for a project."""

    LOCAL = "local"
    SYNC = "sync"


class ProjectStatus(StrEnum):
    """Lifecycle status of a project."""

    ACTIVE = "active"
    PROPOSED = "proposed"


class Project(BaseModel):
    """A first-class project entity."""

    id: str = Field(default_factory=lambda: uuid4().hex)
    name: str
    project_type: ProjectType = ProjectType.STANDARD
    data_mode: DataMode = DataMode.LOCAL
    description: str = ""
    status: ProjectStatus = ProjectStatus.ACTIVE
    created_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
    updated_at: datetime = Field(default_factory=lambda: datetime.now(UTC))


class KnowledgeAtom(BaseModel):
    """A single unit of knowledge extracted from interactions."""

    id: str = Field(default_factory=lambda: uuid4().hex)
    atom_type: AtomType
    content: str  # Human-readable description
    subject: str | None = None  # Entity/topic
    predicate: str | None = None  # Relationship/property
    object: str | None = None  # Value/target
    confidence: float = Field(default=0.8, ge=0.0, le=1.0)
    source_tool: str | None = None  # e.g. "chatgpt", "claude", "perplexity"
    tags: list[str] = Field(default_factory=list)
    created_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
    updated_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
    last_accessed_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
    access_count: int = 0
    is_active: bool = True
    verified_at: datetime | None = None
    verification_status: VerificationStatus = VerificationStatus.UNVERIFIED
    projects: list[str] = Field(default_factory=list)


class KnowledgeConflict(BaseModel):
    """A detected conflict between two knowledge atoms."""

    id: str = Field(default_factory=lambda: uuid4().hex)
    atom_a_id: str
    atom_b_id: str
    conflict_type: ConflictType
    description: str
    status: ConflictStatus = ConflictStatus.OPEN
    resolved_winner_id: str | None = None
    created_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
    resolved_at: datetime | None = None


class Interaction(BaseModel):
    """A captured conversation or API interaction."""

    id: str = Field(default_factory=lambda: uuid4().hex)
    source_tool: str  # e.g. "openai_proxy", "claude_mcp", "manual"
    messages: list[dict]  # Raw conversation messages
    extracted_atoms: list[str] = Field(default_factory=list)  # IDs of extracted atoms
    created_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
    metadata: dict = Field(default_factory=dict)


class ContextInjection(BaseModel):
    """Record of context injected into a downstream request."""

    id: str = Field(default_factory=lambda: uuid4().hex)
    target_tool: str  # e.g. "openai", "anthropic"
    query_text: str  # What triggered the context retrieval
    atoms_injected: list[str]  # IDs of atoms used
    injection_text: str  # The actual text injected
    created_at: datetime = Field(default_factory=lambda: datetime.now(UTC))


class ContextQueryResult(BaseModel):
    """Result from querying relevant context."""

    atom: KnowledgeAtom
    relevance_score: float
    vector_similarity: float
