from datetime import datetime
from typing import TYPE_CHECKING, List, Optional

from sqlalchemy import DateTime, ForeignKey, Integer, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.database.session import Base

if TYPE_CHECKING:
    from app.home.models import Project
    from app.lyric.models import Lyric
    from app.video.models import Video


class Song(Base):
    """
    노래 테이블

    AI를 통해 생성된 노래 정보를 저장합니다.
    가사를 기반으로 생성됩니다.

    Attributes:
        id: 고유 식별자 (자동 증가)
        project_id: 연결된 Project의 id (외래키)
        lyric_id: 연결된 Lyric의 id (외래키)
        task_id: 노래 생성 작업의 고유 식별자 (UUID 형식)
        suno_task_id: Suno API 작업 고유 식별자 (선택)
        status: 처리 상태 (pending, processing, completed, failed 등)
        song_prompt: 노래 생성에 사용된 프롬프트
        song_result_url: 생성 결과 URL (선택)
        language: 출력 언어
        created_at: 생성 일시 (자동 설정)

    Relationships:
        project: 연결된 Project
        lyric: 연결된 Lyric
        videos: 이 노래를 사용한 영상 결과 목록
    """

    __tablename__ = "song"
    __table_args__ = (
        {
            "mysql_engine": "InnoDB",
            "mysql_charset": "utf8mb4",
            "mysql_collate": "utf8mb4_unicode_ci",
        },
    )

    id: Mapped[int] = mapped_column(
        Integer,
        primary_key=True,
        nullable=False,
        autoincrement=True,
        comment="고유 식별자",
    )

    project_id: Mapped[int] = mapped_column(
        Integer,
        ForeignKey("project.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
        comment="연결된 Project의 id",
    )

    lyric_id: Mapped[int] = mapped_column(
        Integer,
        ForeignKey("lyric.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
        comment="연결된 Lyric의 id",
    )

    task_id: Mapped[str] = mapped_column(
        String(36),
        nullable=False,
        comment="노래 생성 작업 고유 식별자 (UUID)",
    )

    suno_task_id: Mapped[Optional[str]] = mapped_column(
        String(64),
        nullable=True,
        comment="Suno API 작업 고유 식별자",
    )

    status: Mapped[str] = mapped_column(
        String(50),
        nullable=False,
        comment="처리 상태 (processing, completed, failed)",
    )

    song_prompt: Mapped[str] = mapped_column(
        Text,
        nullable=False,
        comment="노래 생성에 사용된 프롬프트",
    )

    song_result_url: Mapped[Optional[str]] = mapped_column(
        String(2048),
        nullable=True,
        comment="노래 결과 URL",
    )

    duration: Mapped[Optional[float]] = mapped_column(
        nullable=True,
        comment="노래 재생 시간 (초)",
    )

    language: Mapped[str] = mapped_column(
        String(50),
        nullable=False,
        default="Korean",
        comment="출력 언어 (Korean, English, Chinese, Japanese, Thai, Vietnamese)",
    )

    created_at: Mapped[datetime] = mapped_column(
        DateTime,
        nullable=False,
        server_default=func.now(),
        comment="생성 일시",
    )

    # Relationships
    project: Mapped["Project"] = relationship(
        "Project",
        back_populates="songs",
    )

    lyric: Mapped["Lyric"] = relationship(
        "Lyric",
        back_populates="songs",
    )

    videos: Mapped[List["Video"]] = relationship(
        "Video",
        back_populates="song",
        cascade="all, delete-orphan",
        lazy="selectin",
    )

    def __repr__(self) -> str:
        def truncate(value: str | None, max_len: int = 10) -> str:
            if value is None:
                return "None"
            return (value[:max_len] + "...") if len(value) > max_len else value

        return (
            f"<Song("
            f"id={self.id}, "
            f"task_id='{truncate(self.task_id)}', "
            f"status='{self.status}'"
            f")>"
        )
