from __future__ import annotations

from datetime import datetime

from sqlalchemy import DateTime, ForeignKey, Index, String, Text, text
from sqlalchemy.orm import Mapped, mapped_column

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


class ModuleGenerationProject(Base, TimestampMixin, SoftDeleteMixin):
    """通用模块生成项目/总任务表。

    说明：
    - 本表的 id 就是前端理解的“项目ID/总任务ID”，不再额外保存 project_id。
    - 通过 module 区分业务模块，后续其它功能也可以复用这张总任务项目表。
    - 爆款开头复刻使用 module=hot_opening_replicate。
    """

    __tablename__ = "module_generation_projects"
    __table_args__ = (
        Index("idx_module_generation_projects_user_module", "user_id", "module"),
        Index("idx_module_generation_projects_status", "module", "status"),
        Index(
            "uq_module_generation_projects_user_module_idempotency",
            "user_id",
            "module",
            "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
    )
    module: Mapped[str] = mapped_column(String(64), index=True, nullable=False)
    title: Mapped[str | None] = mapped_column(String(160), nullable=True)
    status: Mapped[str] = mapped_column(String(32), default="pending", index=True)
    current_step_code: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
    final_image_url: Mapped[str | None] = mapped_column(String(512), nullable=True)
    final_video_url: Mapped[str | None] = mapped_column(String(512), nullable=True)
    final_video_cover_url: Mapped[str | None] = mapped_column(String(512), nullable=True)
    error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
    idempotency_key: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
    completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
