from datetime import datetime

from sqlalchemy import DateTime, ForeignKey, SmallInteger, String, UniqueConstraint
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.sql import func

from app.core.database import Base


class Genlocke(Base):
    __tablename__ = "genlockes"

    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(100))
    status: Mapped[str] = mapped_column(String(20), index=True)  # active, completed, failed
    genlocke_rules: Mapped[dict] = mapped_column(JSONB, default=dict)
    nuzlocke_rules: Mapped[dict] = mapped_column(JSONB, default=dict)
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now()
    )

    legs: Mapped[list["GenlockeLeg"]] = relationship(
        back_populates="genlocke", order_by="GenlockeLeg.leg_order"
    )


class GenlockeLeg(Base):
    __tablename__ = "genlocke_legs"
    __table_args__ = (
        UniqueConstraint("genlocke_id", "leg_order", name="uq_genlocke_legs_order"),
    )

    id: Mapped[int] = mapped_column(primary_key=True)
    genlocke_id: Mapped[int] = mapped_column(
        ForeignKey("genlockes.id", ondelete="CASCADE"), index=True
    )
    game_id: Mapped[int] = mapped_column(ForeignKey("games.id"), index=True)
    run_id: Mapped[int | None] = mapped_column(
        ForeignKey("nuzlocke_runs.id"), index=True
    )
    leg_order: Mapped[int] = mapped_column(SmallInteger)
    retired_pokemon_ids: Mapped[list[int] | None] = mapped_column(JSONB, default=None)

    genlocke: Mapped["Genlocke"] = relationship(back_populates="legs")
    game: Mapped["Game"] = relationship()
    run: Mapped["NuzlockeRun | None"] = relationship()
