"""Formal acquisition domain objects.

These models describe the cloud pipeline state used by the formal PostgreSQL
repository layer.
"""
from __future__ import annotations

from datetime import datetime
from typing import Any, Literal
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field


JsonDict = dict[str, Any]
Platform = Literal["xiaohongshu", "weixin", "douyin"]
ContentMode = Literal["image_post", "video_post", "article", "unsupported"]
AcquisitionStatus = Literal[
    "draft",
    "pending",
    "running",
    "candidate",
    "classified",
    "done",
    "failed",
    "testing",
]


class DomainModel(BaseModel):
    model_config = ConfigDict(extra="forbid")


class QueryBatch(DomainModel):
    id: UUID | None = None
    name: str
    source_type: str = "manual"
    generation_method: str | None = None
    target_platforms: list[str] = Field(default_factory=list)
    status: str = "draft"
    metadata: JsonDict = Field(default_factory=dict)
    error_message: str | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None


class Query(DomainModel):
    id: UUID | None = None
    batch_id: UUID | None = None
    query_text: str
    axes: JsonDict = Field(default_factory=dict)
    keep: bool | None = None
    filter_reason: str | None = None
    status: str = "draft"
    sort_order: int = 0
    metadata: JsonDict = Field(default_factory=dict)
    error_message: str | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None


class AcquisitionRun(DomainModel):
    id: UUID | None = None
    batch_id: UUID | None = None
    run_key: str | None = None
    status: str = "pending"
    note: str | None = None
    metadata: JsonDict = Field(default_factory=dict)
    error_message: str | None = None
    started_at: datetime | None = None
    finished_at: datetime | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None


class AcquisitionJob(DomainModel):
    id: UUID | None = None
    run_id: UUID
    query_id: UUID | None = None
    platform: str
    status: str = "pending"
    search_limit: int | None = None
    display_limit: int | None = None
    attempt_count: int = 0
    metadata: JsonDict = Field(default_factory=dict)
    error_message: str | None = None
    started_at: datetime | None = None
    finished_at: datetime | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None


class CandidateItem(DomainModel):
    id: UUID | None = None
    job_id: UUID | None = None
    query_id: UUID | None = None
    platform: str
    platform_item_id: str | None = None
    unique_key: str | None = None
    canonical_url: str | None = None
    content_type: str | None = None
    content_mode: ContentMode | None = None
    title: str | None = None
    author_name: str | None = None
    published_at: datetime | None = None
    body_text: str | None = None
    raw_summary: str | None = None
    status: str = "candidate"
    source_payload: JsonDict = Field(default_factory=dict)
    metadata: JsonDict = Field(default_factory=dict)
    error_message: str | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None


class MediaAsset(DomainModel):
    id: UUID | None = None
    item_id: UUID
    media_type: str
    source_url: str | None = None
    oss_url: str | None = None
    cdn_url: str | None = None
    position: int = 0
    status: str = "pending"
    source_payload: JsonDict = Field(default_factory=dict)
    metadata: JsonDict = Field(default_factory=dict)
    error_message: str | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None


class ItemClassification(DomainModel):
    id: UUID | None = None
    item_id: UUID
    is_creation_knowledge: bool | None = None
    label: str | None = None
    confidence: float | None = None
    reason: str | None = None
    model_name: str | None = None
    prompt_version: str | None = None
    result_payload: JsonDict = Field(default_factory=dict)
    status: str = "pending"
    error_message: str | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None
