"""Pydantic response/request models for the notes + timeline + media domain.

Shapes mirror the dicts built in services/notes.py and services/timeline.py
(which in turn mirror v1's template context), so the generated TS client gets
precise types. Multipart routes (capture/comment create + comment edit) read
Form/File params directly; ``CommentCreate`` documents that contract for
JSON-side tooling.
"""
from __future__ import annotations

from datetime import date, datetime

from pydantic import BaseModel, Field


# --- targets ---

class TargetRef(BaseModel):
    """A bare (type, id) entity reference — request payloads."""

    type: str
    id: int


class TargetOut(BaseModel):
    """A labeled target chip."""

    type: str
    id: int
    is_primary: bool = False
    label: str = ""
    short_label: str = ""
    url: str = ""


# --- comments ---

class CommentCreate(BaseModel):
    """Documented contract of POST /api/notes/comments (multipart form).

    ``secondary_target`` entries are ``"<type>:<id>"`` strings;
    ``override_inference="1"`` makes that list final (auto-inference skipped
    even when it is empty). Files travel as ``audio`` / ``photos`` parts.
    """

    target_type: str
    target_id: int
    comment_date: date
    body: str = ""
    kind: str = ""
    transcript: str = ""
    captured_at: datetime | None = None
    secondary_target: list[str] = Field(default_factory=list)
    override_inference: str = ""


class CommentOut(BaseModel):
    id: int
    comment_date: date | None = None
    created_at: datetime
    captured_at: datetime | None = None
    body: str = ""
    kind: str = ""
    transcript: str = ""
    audio_path: str | None = None
    photos: list[str] = Field(default_factory=list)
    page_context: str = ""
    is_archived: bool = False
    primary: TargetOut | None = None
    other_targets: list[TargetOut] = Field(default_factory=list)
    # Whether the feed's scope entity is this comment's PRIMARY target
    # (v1's per-row ``is_primary`` flag on expanded threads).
    is_primary_for_scope: bool = True


class CommentTargetsOut(BaseModel):
    targets: list[TargetOut] = Field(default_factory=list)


# --- captures (raw field-note rows) ---

class CaptureOut(BaseModel):
    id: int
    created_at: datetime
    captured_at: datetime | None = None
    audio_path: str | None = None
    photo_paths: str = ""
    photos: list[str] = Field(default_factory=list)
    text: str = ""
    transcript: str = ""
    status: str
    processed_at: datetime | None = None
    processing_notes: str = ""
    body: str = ""
    kind: str = ""
    comment_date: date | None = None
    page_context: str = ""
    parent_id: int | None = None
    is_archived: bool = False


class CaptureListOut(BaseModel):
    notes: list[CaptureOut] = Field(default_factory=list)


class CaptureQueueOut(BaseModel):
    notes: list[CaptureOut] = Field(default_factory=list)
    status: str
    counts: dict[str, int] = Field(default_factory=dict)


class CaptureUpdate(BaseModel):
    """PATCH /api/notes/{id} — v1 api_note_update fields, all optional."""

    status: str | None = None
    transcript: str | None = None
    text: str | None = None
    processing_notes: str | None = None


class TranscriptOut(BaseModel):
    ok: bool = True
    id: int
    transcript: str


class OkOut(BaseModel):
    ok: bool = True


# --- inference ---

class InferredTargetsOut(BaseModel):
    targets: list[TargetOut] = Field(default_factory=list)


# --- timeline ---

class ActivityEntryOut(BaseModel):
    id: int
    created_at: datetime
    category: str
    entity_type: str
    entity_id: int | None = None
    summary: str
    field: str | None = None
    old_value: str | None = None
    new_value: str | None = None
    entity_url: str = ""


class TimelineScopeOut(BaseModel):
    type: str
    id: int
    label: str = ""


class TimelineOut(BaseModel):
    """GET /api/timeline — global feed, optionally scoped."""

    view: str
    scope: TimelineScopeOut | None = None
    comments: list[CommentOut] = Field(default_factory=list)
    log_entries: list[ActivityEntryOut] = Field(default_factory=list)
    include_children: bool = False
    include_related: bool = False
    supports_children: bool = False
    show_archived: bool = False


class EntityTimelineOut(BaseModel):
    """GET /api/timeline/{entity_type}/{entity_id}."""

    entity_type: str
    entity_id: int
    label: str = ""
    view: str
    comments: list[CommentOut] = Field(default_factory=list)
    log_entries: list[ActivityEntryOut] = Field(default_factory=list)
    show_archived: bool = False


# --- overview history ---

class OverviewVersionOut(BaseModel):
    id: int
    entity_type: str
    entity_id: int
    content: str
    created_at: datetime
    author: str = "user"
    change_note: str = ""


class OverviewHistoryOut(BaseModel):
    entity_type: str
    entity_id: int
    label: str = ""
    current: str = ""
    versions: list[OverviewVersionOut] = Field(default_factory=list)
