from dataclasses import dataclass
from datetime import UTC, datetime
from enum import StrEnum
from typing import Any, Literal


class ItemKind(StrEnum):
    EMAIL = "email"
    CALENDAR_EVENT = "calendar_event"


class UrgencyLabel(StrEnum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"


MemoryCandidateStatus = Literal["pending", "approved", "rejected"]
MemoryReviewAction = Literal["approved", "rejected"]
RetrievalStage = Literal["retrieved", "prompt_included"]
type EmbeddingVector = list[float]


@dataclass(frozen=True)
class Item:
    provider: str
    external_id: str
    kind: ItemKind
    received_at: datetime
    subject: str
    sender: str
    metadata: dict[str, Any]


@dataclass(frozen=True)
class UrgencyDecision:
    score: float
    label: UrgencyLabel
    reasons: list[str]
    used_llm: bool


@dataclass(frozen=True)
class LLMUsage:
    provider: str
    model: str | None
    total_cost_usd: float | None
    input_tokens: int | None
    output_tokens: int | None
    raw: dict[str, Any]


@dataclass(frozen=True)
class LLMResult:
    decision: UrgencyDecision
    usage: LLMUsage
    raw_response: dict[str, Any]


@dataclass(frozen=True)
class TodoItem:
    title: str
    priority: UrgencyLabel
    due_at: datetime | None
    source_provider: str
    source_external_id: str


@dataclass(frozen=True)
class MemoryRuleCandidate:
    rule_key: str
    description: str
    evidence_count: int
    confidence: float
    status: MemoryCandidateStatus = "pending"
    rejected_reason: str | None = None


@dataclass(frozen=True)
class MemoryRule:
    id: int
    rule_key: str
    description: str
    active: bool
    created_at: datetime


@dataclass(frozen=True)
class MemoryReviewRecord:
    rule_key: str
    action: MemoryReviewAction
    reason: str | None
    reviewed_at: datetime


@dataclass(frozen=True)
class Alert:
    title: str
    body: str
    severity: UrgencyLabel


@dataclass(frozen=True)
class RunResult:
    started_at: datetime
    finished_at: datetime
    processed: int
    alerted: int
    errors: list[str]


@dataclass(frozen=True)
class RenderedItemText:
    provider: str
    external_id: str
    kind: ItemKind
    embedding_text: str
    summary_text: str
    source_version: str = "v1"


@dataclass(frozen=True)
class EmbeddingRecord:
    provider: str
    external_id: str
    embedding_provider: str
    embedding_model: str
    vector: EmbeddingVector
    dimension: int
    created_at: datetime


@dataclass(frozen=True)
class RetrievedMatch:
    provider: str
    external_id: str
    kind: ItemKind
    summary_text: str
    received_at: datetime
    similarity: float
    urgency_label: UrgencyLabel | None


@dataclass(frozen=True)
class RetrievalQuery:
    item: Item
    top_k: int
    min_similarity: float


@dataclass(frozen=True)
class RetrievalDecisionTrace:
    run_id: int
    source_provider: str
    source_external_id: str
    matched_provider: str
    matched_external_id: str
    similarity: float
    stage: RetrievalStage
    included_in_prompt: bool
    created_at: datetime


@dataclass(frozen=True)
class BackfillResult:
    processed: int
    skipped: int
    failed: int


@dataclass(frozen=True)
class StoredEmbeddingDocument:
    provider: str
    external_id: str
    kind: ItemKind
    summary_text: str
    received_at: datetime
    urgency_label: UrgencyLabel | None
    embedding_provider: str
    embedding_model: str
    vector: EmbeddingVector


@dataclass(frozen=True)
class VectorDocumentKey:
    provider: str
    external_id: str
    embedding_provider: str
    embedding_model: str


@dataclass(frozen=True)
class VectorSearchResult:
    provider: str
    external_id: str
    kind: ItemKind
    summary_text: str
    received_at: datetime
    urgency_label: UrgencyLabel | None
    similarity: float


@dataclass(frozen=True)
class VectorQuery:
    vector: EmbeddingVector
    top_k: int
    min_similarity: float
    include_item_kinds: set[str] | None
    prioritize_labels: set[UrgencyLabel] | None
    exclude_keys: set[tuple[str, str]]


@dataclass(frozen=True)
class VectorDocument:
    key: VectorDocumentKey
    kind: ItemKind
    received_at: datetime
    urgency_label: UrgencyLabel | None
    summary_text: str
    source_version: str
    vector: EmbeddingVector
    metadata: dict[str, str | int | float | bool]


def utc_now() -> datetime:
    return datetime.now(tz=UTC)
