"""ORM modely: Player, Game, Guess, PageView.

`won` sa neuklada -- vyplyva z `points > 0`
(trafeny tip = 10 + tip, inak 0; pozri Round.get_points_summary v bridzik.py).
"""

import uuid
from datetime import datetime

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

from db.db import Base


class Player(Base):
    """Trvaly ucet hraca + autentifikacia (TOTP)."""

    __tablename__ = "players"

    id: Mapped[int] = mapped_column(primary_key=True)
    username: Mapped[str] = mapped_column(String(40), unique=True, index=True)
    # Sifrovany cez db/crypto.py (Fernet) -- nikdy neuklada plaintext secret.
    totp_secret: Mapped[str] = mapped_column(String(255))
    # Posledny pouzity TOTP casovy krok -- ochrana proti replay v ramci okna.
    totp_last_step: Mapped[int] = mapped_column(Integer, default=0)
    # Session token pre auto-reconnect (poslany v Socket.IO `auth`).
    # Uklada sa SHA-256 hash (db/crypto.hash_token), nie surovy token.
    auth_token: Mapped[str | None] = mapped_column(
        String(64), unique=True, nullable=True
    )
    created_at: Mapped[datetime] = mapped_column(
        DateTime, server_default=func.now()
    )


class Game(Base):
    """Jedna partia. Drzi priamo 4 ID hracov podla sedadla (0-3)."""

    __tablename__ = "games"

    id: Mapped[str] = mapped_column(
        String(36), primary_key=True, default=lambda: str(uuid.uuid4())
    )
    name: Mapped[str] = mapped_column(String(40), default="")
    player0_id: Mapped[int] = mapped_column(ForeignKey("players.id"))
    player1_id: Mapped[int] = mapped_column(ForeignKey("players.id"))
    player2_id: Mapped[int] = mapped_column(ForeignKey("players.id"))
    player3_id: Mapped[int] = mapped_column(ForeignKey("players.id"))
    # Aktualna pozicia hry. Spolu s rozdanim kariet nanovo plne urcuju stav hry
    # po zaciatok kola -> staci na restore (pozri api/history.rebuild_core).
    series: Mapped[int] = mapped_column(Integer, default=0)
    round: Mapped[int] = mapped_column(Integer, default=0)
    created_at: Mapped[datetime] = mapped_column(
        DateTime, server_default=func.now()
    )
    ended_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)

    def player_id_for_seat(self, seat: int) -> int:
        return (self.player0_id, self.player1_id, self.player2_id, self.player3_id)[seat]


class Guess(Base):
    """Tip a vysledok jedneho hraca v jednom kole.

    Unikat (game_id, series_number, round_number, player_id) robi zapis
    idempotentnym -- opakovany `record_completed_rounds` nezaklada duplikaty.
    """

    __tablename__ = "guesses"
    __table_args__ = (
        UniqueConstraint(
            "game_id",
            "series_number",
            "round_number",
            "player_id",
            name="uq_guess_round_player",
        ),
    )

    id: Mapped[int] = mapped_column(primary_key=True)
    game_id: Mapped[str] = mapped_column(ForeignKey("games.id"), index=True)
    player_id: Mapped[int] = mapped_column(ForeignKey("players.id"), index=True)
    series_number: Mapped[int] = mapped_column(Integer)
    round_number: Mapped[int] = mapped_column(Integer)
    guess: Mapped[int] = mapped_column(Integer)
    points: Mapped[int] = mapped_column(Integer)


class PageView(Base):
    """Jedna navsteva stranky (pre /track). Bez schema migracii -- create_all only."""

    __tablename__ = "page_views"

    id: Mapped[int] = mapped_column(primary_key=True)
    # Konvencia: zacina "/" -> skutocna URL cesta; inak nazov eventu (napr.
    # "rules_view", "login") -- ziadny osobitny stlpec, rovnaky stlpec pre oboje.
    path: Mapped[str] = mapped_column(String(200))
    # Vyplnene len ak je znamy prihlaseny hrac v momente zapisu (napr. event "login").
    player_id: Mapped[int | None] = mapped_column(
        ForeignKey("players.id"), nullable=True, index=True
    )
    referrer: Mapped[str] = mapped_column(String(300), default="")
    user_agent: Mapped[str] = mapped_column(String(300), default="")
    browser: Mapped[str] = mapped_column(String(40), default="")
    os: Mapped[str] = mapped_column(String(40), default="")
    device_type: Mapped[str] = mapped_column(String(20), default="")  # mobile/tablet/pc/bot
    ip: Mapped[str] = mapped_column(String(45), default="")  # surova IP (IPv4/IPv6), "" ak nezname
    country: Mapped[str] = mapped_column(String(60), default="")  # anglicky nazov z GeoIP, "" ak nerozlusene
    created_at: Mapped[datetime] = mapped_column(
        DateTime, server_default=func.now()
    )
