from uuid import UUID

from sqlalchemy import ForeignKey, PrimaryKeyConstraint, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship

from media_manager.auth.db import User
from media_manager.database import Base
from media_manager.torrent.models import Quality


class Show(Base):
    __tablename__ = "show"
    __table_args__ = (UniqueConstraint("external_id", "metadata_provider"),)

    id: Mapped[UUID] = mapped_column(primary_key=True)
    external_id: Mapped[int]
    metadata_provider: Mapped[str]
    name: Mapped[str]
    overview: Mapped[str]
    year: Mapped[int | None]
    ended: Mapped[bool] = mapped_column(default=False)
    continuous_download: Mapped[bool] = mapped_column(default=False)
    library: Mapped[str] = mapped_column(default="")
    original_language: Mapped[str | None] = mapped_column(default=None)

    imdb_id: Mapped[str | None] = mapped_column(default=None)

    seasons: Mapped[list["Season"]] = relationship(
        back_populates="show", cascade="all, delete"
    )


class Season(Base):
    __tablename__ = "season"
    __table_args__ = (UniqueConstraint("show_id", "number"),)

    id: Mapped[UUID] = mapped_column(primary_key=True)
    show_id: Mapped[UUID] = mapped_column(
        ForeignKey(column="show.id", ondelete="CASCADE"),
    )
    number: Mapped[int]
    external_id: Mapped[int]
    name: Mapped[str]
    overview: Mapped[str]

    show: Mapped["Show"] = relationship(back_populates="seasons")
    episodes: Mapped[list["Episode"]] = relationship(
        back_populates="season", cascade="all, delete"
    )

    season_files = relationship(
        "SeasonFile", back_populates="season", cascade="all, delete"
    )
    season_requests = relationship(
        "SeasonRequest", back_populates="season", cascade="all, delete"
    )


class Episode(Base):
    __tablename__ = "episode"
    __table_args__ = (UniqueConstraint("season_id", "number"),)
    id: Mapped[UUID] = mapped_column(primary_key=True)
    season_id: Mapped[UUID] = mapped_column(
        ForeignKey("season.id", ondelete="CASCADE"),
    )
    number: Mapped[int]
    external_id: Mapped[int]
    title: Mapped[str]

    season: Mapped["Season"] = relationship(back_populates="episodes")


class SeasonFile(Base):
    __tablename__ = "season_file"
    __table_args__ = (PrimaryKeyConstraint("season_id", "file_path_suffix"),)
    season_id: Mapped[UUID] = mapped_column(
        ForeignKey(column="season.id", ondelete="CASCADE"),
    )
    torrent_id: Mapped[UUID | None] = mapped_column(
        ForeignKey(column="torrent.id", ondelete="SET NULL"),
    )
    file_path_suffix: Mapped[str]
    quality: Mapped[Quality]

    torrent = relationship("Torrent", back_populates="season_files", uselist=False)
    season = relationship("Season", back_populates="season_files", uselist=False)


class SeasonRequest(Base):
    __tablename__ = "season_request"
    __table_args__ = (UniqueConstraint("season_id", "wanted_quality"),)
    id: Mapped[UUID] = mapped_column(primary_key=True)
    season_id: Mapped[UUID] = mapped_column(
        ForeignKey(column="season.id", ondelete="CASCADE"),
    )
    wanted_quality: Mapped[Quality]
    min_quality: Mapped[Quality]
    requested_by_id: Mapped[UUID | None] = mapped_column(
        ForeignKey(column="user.id", ondelete="SET NULL"),
    )
    authorized: Mapped[bool] = mapped_column(default=False)
    authorized_by_id: Mapped[UUID | None] = mapped_column(
        ForeignKey(column="user.id", ondelete="SET NULL"),
    )

    requested_by: Mapped["User|None"] = relationship(
        foreign_keys=[requested_by_id], uselist=False
    )
    authorized_by: Mapped["User|None"] = relationship(
        foreign_keys=[authorized_by_id], uselist=False
    )
    season = relationship("Season", back_populates="season_requests", uselist=False)
