"""PostgreSQL implementation of the formal acquisition repository."""
from __future__ import annotations

from typing import Any
from uuid import UUID

import psycopg2.extras

from acquisition.domain import (
    AcquisitionJob,
    AcquisitionRun,
    CandidateItem,
    ItemClassification,
    MediaAsset,
    Query,
    QueryBatch,
)


Json = psycopg2.extras.Json
psycopg2.extras.register_uuid()


class PostgresAcquisitionRepository:
    """Repository backed by the formal cloud PostgreSQL schema.

    The repository does not commit by itself; callers own transaction scope via
    core.db_session.transaction or an equivalent connection boundary.
    """

    def __init__(self, conn: Any):
        self.conn = conn

    def _one(self, sql: str, params: tuple[Any, ...]) -> dict[str, Any]:
        with self.conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
            cur.execute(sql, params)
            row = cur.fetchone()
            if row is None:
                raise RuntimeError("expected one row, got none")
            return dict(row)

    def _all(self, sql: str, params: tuple[Any, ...]) -> list[dict[str, Any]]:
        with self.conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
            cur.execute(sql, params)
            return [dict(row) for row in cur.fetchall()]

    def create_query_batch(
        self,
        *,
        name: str,
        source_type: str = "manual",
        generation_method: str | None = None,
        target_platforms: list[str] | None = None,
        status: str = "draft",
        metadata: dict[str, Any] | None = None,
    ) -> QueryBatch:
        row = self._one(
            """
            INSERT INTO query_batches(
                name, source_type, generation_method, target_platforms,
                status, metadata
            )
            VALUES (%s, %s, %s, %s, %s, %s)
            RETURNING *
            """,
            (
                name,
                source_type,
                generation_method,
                target_platforms or [],
                status,
                Json(metadata or {}),
            ),
        )
        return QueryBatch.model_validate(row)

    def add_query(
        self,
        *,
        batch_id: UUID | None,
        query_text: str,
        axes: dict[str, Any] | None = None,
        keep: bool | None = None,
        filter_reason: str | None = None,
        status: str = "draft",
        sort_order: int = 0,
        metadata: dict[str, Any] | None = None,
    ) -> Query:
        row = self._one(
            """
            INSERT INTO queries(
                batch_id, query_text, axes, keep, filter_reason,
                status, sort_order, metadata
            )
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
            RETURNING *
            """,
            (
                batch_id,
                query_text,
                Json(axes or {}),
                keep,
                filter_reason,
                status,
                sort_order,
                Json(metadata or {}),
            ),
        )
        return Query.model_validate(row)

    def list_queries_for_batch(
        self,
        batch_id: UUID,
        *,
        keep: bool | None = None,
    ) -> list[Query]:
        if keep is None:
            rows = self._all(
                """
                SELECT * FROM queries
                WHERE batch_id = %s
                ORDER BY sort_order, created_at
                """,
                (batch_id,),
            )
        else:
            rows = self._all(
                """
                SELECT * FROM queries
                WHERE batch_id = %s AND keep IS NOT DISTINCT FROM %s
                ORDER BY sort_order, created_at
                """,
                (batch_id, keep),
            )
        return [Query.model_validate(row) for row in rows]

    def get_query_batch(self, batch_id: UUID) -> QueryBatch:
        row = self._one("SELECT * FROM query_batches WHERE id = %s", (batch_id,))
        return QueryBatch.model_validate(row)

    def create_acquisition_run(
        self,
        *,
        batch_id: UUID | None = None,
        run_key: str | None = None,
        status: str = "pending",
        note: str | None = None,
        metadata: dict[str, Any] | None = None,
    ) -> AcquisitionRun:
        row = self._one(
            """
            INSERT INTO acquisition_runs(batch_id, run_key, status, note, metadata, started_at)
            VALUES (%s, %s, %s, %s, %s, CASE WHEN %s = 'running' THEN now() ELSE NULL END)
            ON CONFLICT (run_key) DO UPDATE SET
                status = EXCLUDED.status,
                note = EXCLUDED.note,
                metadata = EXCLUDED.metadata,
                started_at = COALESCE(acquisition_runs.started_at, EXCLUDED.started_at)
            RETURNING *
            """,
            (batch_id, run_key, status, note, Json(metadata or {}), status),
        )
        return AcquisitionRun.model_validate(row)

    def ensure_acquisition_job(
        self,
        *,
        run_id: UUID,
        query_id: UUID | None,
        platform: str,
        search_limit: int | None = None,
        display_limit: int | None = None,
        status: str = "pending",
        metadata: dict[str, Any] | None = None,
    ) -> AcquisitionJob:
        row = self._one(
            """
            INSERT INTO acquisition_jobs(
                run_id, query_id, platform, search_limit,
                display_limit, status, metadata
            )
            VALUES (%s, %s, %s, %s, %s, %s, %s)
            ON CONFLICT (run_id, query_id, platform) DO UPDATE SET
                search_limit = EXCLUDED.search_limit,
                display_limit = EXCLUDED.display_limit,
                metadata = acquisition_jobs.metadata || EXCLUDED.metadata
            RETURNING *
            """,
            (
                run_id,
                query_id,
                platform,
                search_limit,
                display_limit,
                status,
                Json(metadata or {}),
            ),
        )
        return AcquisitionJob.model_validate(row)

    def update_acquisition_job(
        self,
        job_id: UUID,
        *,
        status: str,
        attempt_count: int | None = None,
        error_message: str | None = None,
        metadata: dict[str, Any] | None = None,
    ) -> AcquisitionJob:
        row = self._one(
            """
            UPDATE acquisition_jobs SET
                status = %s,
                attempt_count = COALESCE(%s, attempt_count),
                error_message = %s,
                metadata = CASE WHEN %s THEN %s ELSE metadata END
            WHERE id = %s
            RETURNING *
            """,
            (
                status,
                attempt_count,
                error_message,
                metadata is not None,
                Json(metadata or {}),
                job_id,
            ),
        )
        return AcquisitionJob.model_validate(row)

    def update_acquisition_run(
        self,
        run_id: UUID,
        *,
        status: str,
        error_message: str | None = None,
        metadata: dict[str, Any] | None = None,
    ) -> AcquisitionRun:
        row = self._one(
            """
            UPDATE acquisition_runs SET
                status = %s,
                error_message = %s,
                metadata = CASE WHEN %s THEN metadata || %s ELSE metadata END,
                finished_at = CASE WHEN %s IN ('done', 'partial', 'failed') THEN now() ELSE finished_at END
            WHERE id = %s
            RETURNING *
            """,
            (
                status,
                error_message,
                metadata is not None,
                Json(metadata or {}),
                status,
                run_id,
            ),
        )
        return AcquisitionRun.model_validate(row)

    def upsert_candidate_item(
        self,
        *,
        platform: str,
        job_id: UUID | None = None,
        query_id: UUID | None = None,
        platform_item_id: str | None = None,
        unique_key: str | None = None,
        canonical_url: str | None = None,
        content_type: str | None = None,
        content_mode: str | None = None,
        title: str | None = None,
        author_name: str | None = None,
        body_text: str | None = None,
        raw_summary: str | None = None,
        status: str = "candidate",
        source_payload: dict[str, Any] | None = None,
        metadata: dict[str, Any] | None = None,
        error_message: str | None = None,
    ) -> CandidateItem:
        existing_id = None
        if unique_key:
            row = self._one_or_none(
                """
                SELECT id FROM candidate_items
                WHERE unique_key = %s
                ORDER BY created_at DESC
                LIMIT 1
                """,
                (unique_key,),
            )
            existing_id = row["id"] if row else None

        if platform_item_id:
            if existing_id is None:
                row = self._one_or_none(
                    """
                    SELECT id FROM candidate_items
                    WHERE platform = %s AND platform_item_id = %s
                    ORDER BY created_at DESC
                    LIMIT 1
                    """,
                    (platform, platform_item_id),
                )
                existing_id = row["id"] if row else None

        if existing_id:
            row = self._one(
                """
                UPDATE candidate_items SET
                    job_id = %s,
                    query_id = %s,
                    unique_key = COALESCE(%s, unique_key),
                    canonical_url = %s,
                    content_type = %s,
                    content_mode = %s,
                    title = %s,
                    author_name = %s,
                    body_text = %s,
                    raw_summary = %s,
                    status = %s,
                    metadata = %s,
                    error_message = %s
                WHERE id = %s
                RETURNING *
                """,
                (
                    job_id,
                    query_id,
                    unique_key,
                    canonical_url,
                    content_type,
                    content_mode,
                    title,
                    author_name,
                    body_text,
                    raw_summary,
                    status,
                    Json(metadata or {}),
                    error_message,
                    existing_id,
                ),
            )
        else:
            row = self._one(
                """
                INSERT INTO candidate_items(
                    job_id, query_id, platform, platform_item_id, unique_key, canonical_url,
                    content_type, content_mode, title, author_name, body_text, raw_summary, status,
                    source_payload, metadata, error_message
                )
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                RETURNING *
                """,
                (
                    job_id,
                    query_id,
                    platform,
                    platform_item_id,
                    unique_key,
                    canonical_url,
                    content_type,
                    content_mode,
                    title,
                    author_name,
                    body_text,
                    raw_summary,
                    status,
                    Json(source_payload or {}),
                    Json(metadata or {}),
                    error_message,
                ),
            )
        return CandidateItem.model_validate(row)

    def _one_or_none(self, sql: str, params: tuple[Any, ...]) -> dict[str, Any] | None:
        with self.conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
            cur.execute(sql, params)
            row = cur.fetchone()
            return dict(row) if row else None

    def get_candidate_item_by_unique_key(self, unique_key: str) -> CandidateItem | None:
        row = self._one_or_none(
            """
            SELECT * FROM candidate_items
            WHERE unique_key = %s
            ORDER BY created_at DESC
            LIMIT 1
            """,
            (unique_key,),
        )
        return CandidateItem.model_validate(row) if row else None

    def attach_existing_candidate_item(
        self,
        item_id: UUID,
        *,
        job_id: UUID,
        query_id: UUID,
        metadata: dict[str, Any] | None = None,
    ) -> CandidateItem:
        row = self._one(
            """
            UPDATE candidate_items SET
                job_id = %s,
                query_id = %s,
                metadata = metadata || %s
            WHERE id = %s
            RETURNING *
            """,
            (
                job_id,
                query_id,
                Json(metadata or {}),
                item_id,
            ),
        )
        return CandidateItem.model_validate(row)

    def add_media_asset(
        self,
        *,
        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: dict[str, Any] | None = None,
        metadata: dict[str, Any] | None = None,
    ) -> MediaAsset:
        row = self._one(
            """
            INSERT INTO media_assets(
                item_id, media_type, source_url, oss_url, cdn_url,
                position, status, source_payload, metadata
            )
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
            RETURNING *
            """,
            (
                item_id,
                media_type,
                source_url,
                oss_url,
                cdn_url,
                position,
                status,
                Json(source_payload or {}),
                Json(metadata or {}),
            ),
        )
        return MediaAsset.model_validate(row)

    def add_item_classification(
        self,
        *,
        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: dict[str, Any] | None = None,
        status: str = "pending",
        error_message: str | None = None,
    ) -> ItemClassification:
        row = self._one(
            """
            INSERT INTO item_classifications(
                item_id, is_creation_knowledge, label, confidence, reason,
                model_name, prompt_version, result_payload, status, error_message
            )
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            RETURNING *
            """,
            (
                item_id,
                is_creation_knowledge,
                label,
                confidence,
                reason,
                model_name,
                prompt_version,
                Json(result_payload or {}),
                status,
                error_message,
            ),
        )
        return ItemClassification.model_validate(row)

    def get_run_summary(self, run_id: UUID) -> dict[str, Any]:
        summary = self._one(
            """
            SELECT
                ar.id,
                ar.run_key,
                ar.batch_id,
                ar.status,
                ar.started_at,
                ar.finished_at,
                COUNT(DISTINCT q.id)::int AS query_count,
                COUNT(DISTINCT aj.id)::int AS job_count,
                COUNT(DISTINCT ci.id)::int AS candidate_count,
                COUNT(DISTINCT ic.id) FILTER (
                    WHERE ic.is_creation_knowledge IS TRUE
                )::int AS creation_hit_count,
                COUNT(DISTINCT ci.id) FILTER (
                    WHERE ic.is_creation_knowledge IS TRUE
                      AND dr.status = 'decoded'
                      AND kp.id IS NOT NULL
                )::int AS decoded_count,
                COUNT(DISTINCT pd.id) FILTER (
                    WHERE ic.is_creation_knowledge IS TRUE
                      AND dr.status = 'decoded'
                      AND kp.id IS NOT NULL
                )::int AS payload_count
            FROM acquisition_runs ar
            LEFT JOIN acquisition_jobs aj ON aj.run_id = ar.id
            LEFT JOIN queries q ON q.id = aj.query_id
            LEFT JOIN candidate_items ci ON ci.job_id = aj.id
            LEFT JOIN item_classifications ic ON ic.item_id = ci.id
            LEFT JOIN decode_results dr ON dr.item_id = ci.id
            LEFT JOIN knowledge_particles kp ON kp.item_id = ci.id
            LEFT JOIN payload_drafts pd ON pd.item_id = ci.id
            WHERE ar.id = %s
            GROUP BY ar.id
            """,
            (run_id,),
        )
        summary["queries"] = self._all(
            """
            SELECT
                q.id AS query_id,
                q.query_text,
                COUNT(DISTINCT aj.id)::int AS job_count,
                COUNT(DISTINCT ci.id)::int AS candidate_count,
                COUNT(DISTINCT ic.id) FILTER (
                    WHERE ic.is_creation_knowledge IS TRUE
                )::int AS creation_hit_count,
                COUNT(DISTINCT ci.id) FILTER (
                    WHERE ic.is_creation_knowledge IS TRUE
                      AND dr.status = 'decoded'
                      AND kp.id IS NOT NULL
                )::int AS decoded_count,
                COUNT(DISTINCT pd.id) FILTER (
                    WHERE ic.is_creation_knowledge IS TRUE
                      AND dr.status = 'decoded'
                      AND kp.id IS NOT NULL
                )::int AS payload_count,
                jsonb_object_agg(
                    aj.platform,
                    jsonb_build_object(
                        'status', aj.status,
                        'attempt_count', aj.attempt_count,
                        'display_limit', aj.display_limit,
                        'search_limit', aj.search_limit,
                        'error_message', aj.error_message
                    )
                ) FILTER (WHERE aj.id IS NOT NULL) AS platforms
            FROM queries q
            JOIN acquisition_jobs aj ON aj.query_id = q.id
            LEFT JOIN candidate_items ci ON ci.job_id = aj.id
            LEFT JOIN item_classifications ic ON ic.item_id = ci.id
            LEFT JOIN decode_results dr ON dr.item_id = ci.id
            LEFT JOIN knowledge_particles kp ON kp.item_id = ci.id
            LEFT JOIN payload_drafts pd ON pd.item_id = ci.id
            WHERE aj.run_id = %s
            GROUP BY q.id, q.query_text, q.sort_order
            ORDER BY q.sort_order, q.query_text
            """,
            (run_id,),
        )
        return summary

    def get_query_detail(self, *, run_id: UUID, query_id: UUID) -> dict[str, Any]:
        query = self._one("SELECT * FROM queries WHERE id = %s", (query_id,))
        jobs = self._all(
            """
            SELECT * FROM acquisition_jobs
            WHERE run_id = %s AND query_id = %s
            ORDER BY platform
            """,
            (run_id, query_id),
        )
        items = self._all(
            """
            SELECT ci.* FROM candidate_items ci
            JOIN acquisition_jobs aj ON aj.id = ci.job_id
            WHERE aj.run_id = %s AND ci.query_id = %s
            ORDER BY ci.platform, ci.created_at
            """,
            (run_id, query_id),
        )
        item_ids = [row["id"] for row in items]
        media: list[dict[str, Any]] = []
        classifications: list[dict[str, Any]] = []
        decode_summaries: list[dict[str, Any]] = []
        if item_ids:
            media = self._all(
                """
                SELECT * FROM media_assets
                WHERE item_id = ANY(%s)
                ORDER BY item_id, position
                """,
                (item_ids,),
            )
            classifications = self._all(
                """
                SELECT * FROM item_classifications
                WHERE item_id = ANY(%s)
                ORDER BY created_at DESC
                """,
                (item_ids,),
            )
            decode_summaries = self._all(
                """
                SELECT DISTINCT ON (dr.item_id)
                    dr.item_id,
                    dr.status AS decode_status,
                    COUNT(DISTINCT kp.id)::int AS particle_count,
                    COUNT(DISTINCT pd.id)::int AS payload_count
                FROM decode_results dr
                LEFT JOIN knowledge_particles kp ON kp.item_id = dr.item_id
                LEFT JOIN payload_drafts pd ON pd.item_id = dr.item_id
                WHERE dr.item_id = ANY(%s)
                GROUP BY dr.item_id, dr.status, dr.created_at
                ORDER BY dr.item_id, dr.created_at DESC
                """,
                (item_ids,),
            )
        return {
            "query": query,
            "jobs": jobs,
            "items": items,
            "media_assets": media,
            "classifications": classifications,
            "decode_summaries": decode_summaries,
        }

    def get_query_detail_for_batch(self, *, batch_id: UUID, query_id: UUID) -> dict[str, Any]:
        query = self._one(
            "SELECT * FROM queries WHERE id = %s AND batch_id = %s",
            (query_id, batch_id),
        )
        jobs = self._all(
            """
            SELECT aj.* FROM acquisition_jobs aj
            JOIN acquisition_runs ar ON ar.id = aj.run_id
            WHERE ar.batch_id = %s AND aj.query_id = %s
            ORDER BY aj.created_at, aj.platform
            """,
            (batch_id, query_id),
        )
        items = self._all(
            """
            SELECT ci.* FROM candidate_items ci
            JOIN acquisition_jobs aj ON aj.id = ci.job_id
            JOIN acquisition_runs ar ON ar.id = aj.run_id
            WHERE ar.batch_id = %s AND ci.query_id = %s
            ORDER BY ci.platform, ci.created_at
            """,
            (batch_id, query_id),
        )
        item_ids = [row["id"] for row in items]
        media: list[dict[str, Any]] = []
        classifications: list[dict[str, Any]] = []
        decode_summaries: list[dict[str, Any]] = []
        if item_ids:
            media = self._all(
                """
                SELECT * FROM media_assets
                WHERE item_id = ANY(%s)
                ORDER BY item_id, position
                """,
                (item_ids,),
            )
            classifications = self._all(
                """
                SELECT * FROM item_classifications
                WHERE item_id = ANY(%s)
                ORDER BY created_at DESC
                """,
                (item_ids,),
            )
            decode_summaries = self._all(
                """
                SELECT DISTINCT ON (dr.item_id)
                    dr.item_id,
                    dr.status AS decode_status,
                    COUNT(DISTINCT kp.id)::int AS particle_count,
                    COUNT(DISTINCT pd.id)::int AS payload_count
                FROM decode_results dr
                LEFT JOIN knowledge_particles kp ON kp.item_id = dr.item_id
                LEFT JOIN payload_drafts pd ON pd.item_id = dr.item_id
                WHERE dr.item_id = ANY(%s)
                GROUP BY dr.item_id, dr.status, dr.created_at
                ORDER BY dr.item_id, dr.created_at DESC
                """,
                (item_ids,),
            )
        return {
            "query": query,
            "jobs": jobs,
            "items": items,
            "media_assets": media,
            "classifications": classifications,
            "decode_summaries": decode_summaries,
        }

    def get_latest_query_result_list(self, query_id: UUID) -> dict[str, Any]:
        query = self._one("SELECT * FROM queries WHERE id = %s", (query_id,))
        run = self._one_or_none(
            """
            SELECT ar.* FROM acquisition_runs ar
            JOIN acquisition_jobs aj ON aj.run_id = ar.id
            WHERE aj.query_id = %s
            ORDER BY aj.created_at DESC, ar.created_at DESC
            LIMIT 1
            """,
            (query_id,),
        )
        if run is None:
            return {
                "query": query,
                "run": None,
                "jobs": [],
                "items": [],
                "media_assets": [],
                "classifications": [],
                "decode_summaries": [],
            }
        jobs = self._all(
            """
            SELECT
                aj.id,
                aj.run_id,
                aj.query_id,
                aj.platform,
                aj.status,
                aj.attempt_count,
                aj.display_limit,
                aj.search_limit,
                aj.error_message,
                aj.started_at,
                aj.finished_at,
                aj.created_at,
                aj.updated_at
            FROM acquisition_jobs aj
            WHERE aj.query_id = %s
            ORDER BY aj.created_at, aj.platform
            """,
            (query_id,),
        )
        items = self._all(
            """
            SELECT
                ci.id,
                ci.query_id,
                ci.job_id,
                ci.platform,
                ci.title,
                LEFT(ci.raw_summary, 700) AS raw_summary,
                ci.status,
                ci.content_mode,
                jsonb_strip_nulls(jsonb_build_object(
                    'page_index', ci.metadata -> 'page_index',
                    'page_rank', ci.metadata -> 'page_rank',
                    'source_cursor', ci.metadata -> 'source_cursor',
                    'content_mode', ci.metadata -> 'content_mode',
                    'search_provider', ci.metadata -> 'search_provider',
                    'detail_provider', ci.metadata -> 'detail_provider',
                    'acquisition_match_status', ci.metadata -> 'acquisition_match_status',
                    'matched_unique_key', ci.metadata -> 'matched_unique_key',
                    'skip_reason', ci.metadata -> 'skip_reason',
                    'unsupported_raw_type', ci.metadata -> 'unsupported_raw_type',
                    'video_url_missing', ci.metadata -> 'video_url_missing'
                )) AS metadata,
                ci.created_at,
                ci.updated_at
            FROM candidate_items ci
            JOIN acquisition_jobs aj ON aj.id = ci.job_id
            WHERE aj.query_id = %s
            ORDER BY ci.platform, ci.created_at
            """,
            (query_id,),
        )
        item_ids = [row["id"] for row in items]
        media: list[dict[str, Any]] = []
        classifications: list[dict[str, Any]] = []
        decode_summaries: list[dict[str, Any]] = []
        if item_ids:
            media = self._all(
                """
                SELECT DISTINCT ON (item_id)
                    id, item_id, media_type, source_url, oss_url, cdn_url, position, status
                FROM media_assets
                WHERE item_id = ANY(%s)
                ORDER BY
                    item_id,
                    CASE WHEN media_type IN ('cover', 'image', 'frame') THEN 0 ELSE 1 END,
                    position,
                    created_at
                """,
                (item_ids,),
            )
            classifications = self._all(
                """
                SELECT DISTINCT ON (item_id)
                    id, item_id, is_creation_knowledge, label, confidence, status, error_message
                FROM item_classifications
                WHERE item_id = ANY(%s)
                ORDER BY item_id, created_at DESC
                """,
                (item_ids,),
            )
            decode_summaries = self._all(
                """
                SELECT DISTINCT ON (dr.item_id)
                    dr.item_id,
                    dr.status AS decode_status,
                    COUNT(DISTINCT kp.id)::int AS particle_count,
                    COUNT(DISTINCT pd.id)::int AS payload_count
                FROM decode_results dr
                LEFT JOIN knowledge_particles kp ON kp.item_id = dr.item_id
                LEFT JOIN payload_drafts pd ON pd.item_id = dr.item_id
                WHERE dr.item_id = ANY(%s)
                GROUP BY dr.item_id, dr.status, dr.created_at
                ORDER BY dr.item_id, dr.created_at DESC
                """,
                (item_ids,),
            )
        return {
            "query": query,
            "run": run,
            "jobs": jobs,
            "items": items,
            "media_assets": media,
            "classifications": classifications,
            "decode_summaries": decode_summaries,
        }

    def get_latest_singleton_overview(self) -> dict[str, Any]:
        batch = self._one_or_none(
            """
            SELECT qb.* FROM query_batches qb
            JOIN acquisition_runs ar ON ar.batch_id = qb.id
            GROUP BY qb.id
            ORDER BY MAX(ar.created_at) DESC
            LIMIT 1
            """,
            (),
        )
        if batch is None:
            return {"batch": None, "run": None, "queries": [], "decoded_items": []}

        run = self._one_or_none(
            """
            SELECT * FROM acquisition_runs
            WHERE batch_id = %s
            ORDER BY created_at DESC
            LIMIT 1
            """,
            (batch["id"],),
        )
        if run is None:
            queries = self._all(
                """
                SELECT
                    q.id AS query_id,
                    q.query_text,
                    q.metadata->>'family_key' AS family_key,
                    q.sort_order,
                    0::int AS candidate_count,
                    0::int AS creation_hit_count,
                    0::int AS decoded_count,
                    0::int AS payload_count
                FROM queries q
                WHERE q.batch_id = %s
                ORDER BY q.sort_order, q.created_at
                """,
                (batch["id"],),
            )
            return {"batch": batch, "run": None, "queries": queries, "decoded_items": []}

        latest_queries_cte = """
            WITH query_activity AS (
                SELECT
                    q.id AS query_id,
                    q.query_text,
                    q.created_at AS query_created_at,
                    MAX(ar.created_at) AS activity_at
                FROM queries q
                LEFT JOIN acquisition_jobs aj ON aj.query_id = q.id
                LEFT JOIN acquisition_runs ar ON ar.id = aj.run_id
                GROUP BY q.id, q.query_text, q.created_at
            ),
            query_stats AS (
                SELECT
                    qa.query_id,
                    qa.query_text,
                    qa.query_created_at,
                    qa.activity_at,
                    COUNT(DISTINCT pd.id) FILTER (
                        WHERE ic.is_creation_knowledge IS TRUE
                          AND dr.status = 'decoded'
                          AND kp.id IS NOT NULL
                    )::int AS payload_count
                FROM query_activity qa
                LEFT JOIN acquisition_jobs aj ON aj.query_id = qa.query_id
                LEFT JOIN candidate_items ci ON ci.job_id = aj.id
                LEFT JOIN item_classifications ic ON ic.item_id = ci.id
                LEFT JOIN decode_results dr ON dr.item_id = ci.id
                LEFT JOIN knowledge_particles kp ON kp.item_id = ci.id
                LEFT JOIN payload_drafts pd ON pd.item_id = ci.id
                GROUP BY qa.query_id, qa.query_text, qa.query_created_at, qa.activity_at
            ),
            latest_queries AS (
                SELECT DISTINCT ON (query_text)
                    query_id
                FROM query_stats
                ORDER BY query_text, (payload_count > 0) DESC, activity_at DESC NULLS LAST, query_created_at DESC
            )
        """
        queries = self._all(
            latest_queries_cte
            + """
            SELECT
                q.id AS query_id,
                q.query_text,
                q.metadata->>'family_key' AS family_key,
                q.sort_order,
                COUNT(DISTINCT ci.id)::int AS candidate_count,
                COUNT(DISTINCT ic.id) FILTER (
                    WHERE ic.is_creation_knowledge IS TRUE
                )::int AS creation_hit_count,
                COUNT(DISTINCT ci.id) FILTER (
                    WHERE ic.is_creation_knowledge IS TRUE
                      AND dr.status = 'decoded'
                      AND kp.id IS NOT NULL
                )::int AS decoded_count,
                COUNT(DISTINCT pd.id) FILTER (
                    WHERE ic.is_creation_knowledge IS TRUE
                      AND dr.status = 'decoded'
                      AND kp.id IS NOT NULL
                )::int AS payload_count
            FROM latest_queries lq
            JOIN queries q ON q.id = lq.query_id
            LEFT JOIN acquisition_jobs aj ON aj.query_id = q.id
            LEFT JOIN candidate_items ci ON ci.job_id = aj.id
            LEFT JOIN item_classifications ic ON ic.item_id = ci.id
            LEFT JOIN decode_results dr ON dr.item_id = ci.id
            LEFT JOIN knowledge_particles kp ON kp.item_id = ci.id
            LEFT JOIN payload_drafts pd ON pd.item_id = ci.id
            GROUP BY q.id, q.query_text, q.metadata, q.sort_order
            ORDER BY q.sort_order, q.created_at
            """,
            (),
        )
        decoded_items = self._all(
            latest_queries_cte
            + """
            SELECT
                ci.id AS item_id,
                ci.query_id,
                ci.title,
                ci.platform,
                dr.status AS decode_status,
                COUNT(DISTINCT kp.id)::int AS particle_count,
                COUNT(DISTINCT pd.id)::int AS payload_count
            FROM candidate_items ci
            JOIN latest_queries lq ON lq.query_id = ci.query_id
            JOIN acquisition_jobs aj ON aj.id = ci.job_id
            JOIN decode_results dr ON dr.item_id = ci.id
            LEFT JOIN knowledge_particles kp ON kp.item_id = ci.id
            LEFT JOIN payload_drafts pd ON pd.item_id = ci.id
            GROUP BY ci.id, ci.query_id, ci.title, ci.platform, dr.status, dr.created_at
            ORDER BY dr.created_at DESC
            """,
            (),
        )
        return {
            "batch": batch,
            "run": run,
            "queries": queries,
            "decoded_items": decoded_items,
        }

    def list_creation_candidate_items(
        self,
        *,
        run_id: UUID | None = None,
        limit: int = 100,
    ) -> list[CandidateItem]:
        if run_id is None:
            rows = self._all(
                """
                SELECT ci.* FROM candidate_items ci
                JOIN item_classifications ic ON ic.item_id = ci.id
                WHERE ic.is_creation_knowledge IS TRUE
                  AND NOT EXISTS (
                      SELECT 1 FROM decode_results dr
                      WHERE dr.item_id = ci.id
                        AND dr.status IN ('decoded', 'rejected', 'skipped')
                  )
                ORDER BY ci.created_at
                LIMIT %s
                """,
                (limit,),
            )
        else:
            rows = self._all(
                """
                SELECT ci.* FROM candidate_items ci
                JOIN acquisition_jobs aj ON aj.id = ci.job_id
                JOIN item_classifications ic ON ic.item_id = ci.id
                WHERE aj.run_id = %s AND ic.is_creation_knowledge IS TRUE
                  AND NOT EXISTS (
                      SELECT 1 FROM decode_results dr
                      WHERE dr.item_id = ci.id
                        AND dr.status IN ('decoded', 'rejected', 'skipped')
                  )
                ORDER BY ci.created_at
                LIMIT %s
                """,
                (run_id, limit),
            )
        return [CandidateItem.model_validate(row) for row in rows]

    def get_candidate_item(self, item_id: UUID) -> CandidateItem:
        row = self._one("SELECT * FROM candidate_items WHERE id = %s", (item_id,))
        return CandidateItem.model_validate(row)

    def list_media_assets_for_item(self, item_id: UUID) -> list[MediaAsset]:
        rows = self._all(
            """
            SELECT * FROM media_assets
            WHERE item_id = %s
            ORDER BY position
            """,
            (item_id,),
        )
        return [MediaAsset.model_validate(row) for row in rows]
