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

from advanced_alchemy.base import BigIntBase


class DuplicateDismissal(BigIntBase):
    """
    Two books a reader has said are not the same book.

    Title and author matching is probabilistic, so it will keep proposing a second
    edition, a translation and a sequel that shares its predecessor's name. A review
    screen with no way to disagree with it nags forever, which is how people learn to
    ignore a screen.

    The pair is stored ordered — `book_a_id` is always the lower id — so "A and B" and
    "B and A" are one row and the unique constraint can do its job. Use `pair()` rather
    than assigning the columns directly.
    """

    __tablename__ = "duplicate_dismissals"
    __table_args__ = (UniqueConstraint("book_a_id", "book_b_id"),)

    book_a_id: Mapped[int] = mapped_column(
        ForeignKey("books.id", ondelete="cascade"), index=True
    )
    book_b_id: Mapped[int] = mapped_column(
        ForeignKey("books.id", ondelete="cascade"), index=True
    )

    @staticmethod
    def pair(first: int, second: int) -> tuple[int, int]:
        """The two book ids in the order this table stores them."""
        return (first, second) if first <= second else (second, first)

    def __repr__(self) -> str:
        return f"DuplicateDismissal({self.book_a_id!r}, {self.book_b_id!r})"
