from __future__ import annotations

from typing import Any

from sqlalchemy import Float, ForeignKey, Index, Integer, JSON, String, Text, text
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column

from app.models.base import Base, SoftDeleteMixin, TimestampMixin

_JSON_TYPE = JSON().with_variant(JSONB, "postgresql")


class ShotReplicateTaskSet(Base, TimestampMixin, SoftDeleteMixin):
    """拆镜复刻总任务集。"""

    __tablename__ = "shot_replicate_task_sets"
    __table_args__ = (
        Index("idx_shot_replicate_task_sets_user_created", "user_id", "created_at"),
        Index("idx_shot_replicate_task_sets_status", "status"),
        Index("idx_shot_replicate_task_sets_analysis_status", "analysis_status"),
        Index("idx_shot_replicate_task_sets_split_status", "split_status"),
        Index(
            "uq_shot_replicate_task_sets_user_idempotency",
            "user_id",
            "idempotency_key",
            unique=True,
            postgresql_where=text("deleted_at IS NULL AND idempotency_key IS NOT NULL"),
        ),
    )

    id: Mapped[str] = mapped_column(String(32), primary_key=True)
    user_id: Mapped[str] = mapped_column(
        String(32), ForeignKey("users.id", ondelete="CASCADE"), index=True, nullable=False
    )
    title: Mapped[str | None] = mapped_column(String(160), nullable=True)

    video_url: Mapped[str] = mapped_column(String(512), nullable=False)
    video_path: Mapped[str] = mapped_column(String(512), nullable=False)
    video_duration_seconds: Mapped[float] = mapped_column(Float, nullable=False)

    status: Mapped[str] = mapped_column(String(32), default="pending_analysis", index=True, nullable=False)
    analysis_status: Mapped[str] = mapped_column(String(32), default="pending", index=True, nullable=False)
    split_status: Mapped[str] = mapped_column(String(32), default="none", index=True, nullable=False)

    original_video_content: Mapped[str | None] = mapped_column(Text, nullable=True)
    original_video_category: Mapped[str | None] = mapped_column(String(160), nullable=True)
    original_video_audience: Mapped[str | None] = mapped_column(Text, nullable=True)

    ai_suggestion_json: Mapped[list[Any] | dict[str, Any] | None] = mapped_column(_JSON_TYPE, nullable=True)
    analysis_raw_json: Mapped[dict[str, Any] | list[Any] | None] = mapped_column(_JSON_TYPE, nullable=True)
    analysis_result_json: Mapped[dict[str, Any] | list[Any] | None] = mapped_column(_JSON_TYPE, nullable=True)

    segment_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    completed_segment_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    failed_segment_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)

    analysis_error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
    split_error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
    idempotency_key: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
