"""Completely isolated persistence models for ``find_agent_v2``."""

from __future__ import annotations

from datetime import datetime
from decimal import Decimal

from sqlalchemy import BigInteger, Index, Integer, Numeric, String, Text, UniqueConstraint, func
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.orm import Mapped, mapped_column

from supply_infra.db.base import Base

_LONG_TEXT = Text().with_variant(LONGTEXT(), "mysql")


class FindAgentV2Run(Base):
    __tablename__ = "find_agent_v2_run"
    __table_args__ = (
        UniqueConstraint("run_id", name="uk_find_agent_v2_run_id"),
        Index("idx_find_agent_v2_run_status", "status"),
        Index("idx_find_agent_v2_run_demand", "demand_grade_id"),
    )

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    run_id: Mapped[str] = mapped_column(String(64), nullable=False)
    demand_grade_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    demand_word: Mapped[str] = mapped_column(String(256), nullable=False)
    input_json: Mapped[str] = mapped_column(_LONG_TEXT, nullable=False)
    rule_config_json: Mapped[str] = mapped_column(Text, nullable=False)
    status: Mapped[str] = mapped_column(String(24), nullable=False, default="running")
    outcome_status: Mapped[str | None] = mapped_column(String(24), nullable=True)
    current_round: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    search_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    candidate_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    valid_primary_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    input_tokens: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
    output_tokens: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
    total_tokens: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
    cost_usd: Mapped[Decimal] = mapped_column(Numeric(18, 8), nullable=False, default=0)
    intent_summary: Mapped[str | None] = mapped_column(Text, nullable=True)
    stop_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
    obagent_run_uid: Mapped[str | None] = mapped_column(String(64), nullable=True)
    create_time: Mapped[datetime] = mapped_column(nullable=False, server_default=func.now())
    update_time: Mapped[datetime] = mapped_column(nullable=False, server_default=func.now(), onupdate=func.now())


class FindAgentV2Round(Base):
    __tablename__ = "find_agent_v2_round"
    __table_args__ = (
        UniqueConstraint("run_id", "round_index", name="uk_find_agent_v2_round"),
        Index("idx_find_agent_v2_round_run", "run_id", "round_index"),
    )

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    run_id: Mapped[str] = mapped_column(String(64), nullable=False)
    round_index: Mapped[int] = mapped_column(Integer, nullable=False)
    phase: Mapped[str] = mapped_column(String(24), nullable=False, default="planning")
    status: Mapped[str] = mapped_column(String(16), nullable=False, default="open")
    plan_json: Mapped[str | None] = mapped_column(_LONG_TEXT, nullable=True)
    start_snapshot_json: Mapped[str | None] = mapped_column(Text, nullable=True)
    end_snapshot_json: Mapped[str | None] = mapped_column(Text, nullable=True)
    error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
    create_time: Mapped[datetime] = mapped_column(nullable=False, server_default=func.now())
    update_time: Mapped[datetime] = mapped_column(nullable=False, server_default=func.now(), onupdate=func.now())


class FindAgentV2Search(Base):
    __tablename__ = "find_agent_v2_search"
    __table_args__ = (Index("idx_find_agent_v2_search_run", "run_id", "id"),)

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    run_id: Mapped[str] = mapped_column(String(64), nullable=False)
    round_index: Mapped[int] = mapped_column(Integer, nullable=False)
    keyword: Mapped[str] = mapped_column(String(256), nullable=False)
    query_reason: Mapped[str] = mapped_column(Text, nullable=False)
    source_type: Mapped[str] = mapped_column(String(32), nullable=False)
    provider: Mapped[str] = mapped_column(String(32), nullable=False)
    cursor: Mapped[str] = mapped_column(String(128), nullable=False, default="0")
    page_no: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
    has_more: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    next_cursor: Mapped[str | None] = mapped_column(String(128), nullable=True)
    provider_state_json: Mapped[str | None] = mapped_column(Text, nullable=True)
    result_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    status: Mapped[str] = mapped_column(String(16), nullable=False)
    error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
    raw_response_json: Mapped[str | None] = mapped_column(_LONG_TEXT, nullable=True)
    create_time: Mapped[datetime] = mapped_column(nullable=False, server_default=func.now())


class FindAgentV2Candidate(Base):
    __tablename__ = "find_agent_v2_candidate"
    __table_args__ = (
        UniqueConstraint("run_id", "aweme_id", name="uk_find_agent_v2_candidate_aweme"),
        Index("idx_find_agent_v2_candidate_bucket", "run_id", "decision_bucket"),
    )

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    run_id: Mapped[str] = mapped_column(String(64), nullable=False)
    # Logical reference only. find_agent_v2 deliberately uses no database FKs.
    first_search_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    aweme_id: Mapped[str] = mapped_column(String(64), nullable=False)
    title: Mapped[str | None] = mapped_column(String(512), nullable=True)
    content_link: Mapped[str | None] = mapped_column(String(1024), nullable=True)
    author_name: Mapped[str | None] = mapped_column(String(256), nullable=True)
    author_sec_uid: Mapped[str | None] = mapped_column(String(256), nullable=True)
    source_keywords_json: Mapped[str | None] = mapped_column(Text, nullable=True)
    tags_json: Mapped[str | None] = mapped_column(Text, nullable=True)
    publish_at: Mapped[datetime | None] = mapped_column(nullable=True)
    duration_seconds: Mapped[Decimal | None] = mapped_column(Numeric(10, 3), nullable=True)
    play_count: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    like_count: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    comment_count: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    collect_count: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    share_count: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    detail_json: Mapped[str | None] = mapped_column(_LONG_TEXT, nullable=True)
    portrait_json: Mapped[str | None] = mapped_column(_LONG_TEXT, nullable=True)
    detail_status: Mapped[str] = mapped_column(String(16), nullable=False, default="pending")
    portrait_status: Mapped[str] = mapped_column(String(16), nullable=False, default="pending")
    content_50_plus_ratio: Mapped[Decimal | None] = mapped_column(Numeric(8, 6), nullable=True)
    account_50_plus_ratio: Mapped[Decimal | None] = mapped_column(Numeric(8, 6), nullable=True)
    relevance_score: Mapped[Decimal | None] = mapped_column(Numeric(8, 6), nullable=True)
    elder_score: Mapped[Decimal | None] = mapped_column(Numeric(8, 6), nullable=True)
    share_score: Mapped[Decimal | None] = mapped_column(Numeric(8, 6), nullable=True)
    value_score: Mapped[Decimal | None] = mapped_column(Numeric(8, 6), nullable=True)
    gate_status: Mapped[str | None] = mapped_column(String(16), nullable=True)
    gate_result_json: Mapped[str | None] = mapped_column(Text, nullable=True)
    decision_bucket: Mapped[str] = mapped_column(String(24), nullable=False, default="pending_evaluation")
    decision_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
    reject_reason_code: Mapped[str | None] = mapped_column(String(64), nullable=True)
    create_time: Mapped[datetime] = mapped_column(nullable=False, server_default=func.now())
    update_time: Mapped[datetime] = mapped_column(nullable=False, server_default=func.now(), onupdate=func.now())


class FindAgentV2Evidence(Base):
    __tablename__ = "find_agent_v2_evidence"
    __table_args__ = (Index("idx_find_agent_v2_evidence_subject", "run_id", "candidate_id", "id"),)

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    run_id: Mapped[str] = mapped_column(String(64), nullable=False)
    candidate_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    evidence_type: Mapped[str] = mapped_column(String(32), nullable=False)
    provider: Mapped[str] = mapped_column(String(32), nullable=False)
    status: Mapped[str] = mapped_column(String(16), nullable=False)
    raw_json: Mapped[str | None] = mapped_column(_LONG_TEXT, nullable=True)
    normalized_json: Mapped[str | None] = mapped_column(_LONG_TEXT, nullable=True)
    error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
    create_time: Mapped[datetime] = mapped_column(nullable=False, server_default=func.now())
