import enum
import uuid
from datetime import datetime

from sqlalchemy import DateTime, ForeignKey, Integer, String
from sqlalchemy import Enum as SAEnum
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.database import Base


class Mode(str, enum.Enum):
    casual = "casual"


class ServerStatus(str, enum.Enum):
    available = "available"
    full = "full"
    offline = "offline"


# No account/auth system yet (GodotSteam auth is still on the networking
# checklist), so callsign is the identity key for now — same as the game
# client itself, which only has a free-text name field today.
class Player(Base):
    __tablename__ = "players"

    id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)
    callsign: Mapped[str] = mapped_column(String(32), unique=True, index=True)
    mmr: Mapped[int] = mapped_column(Integer, default=1000)
    wins: Mapped[int] = mapped_column(Integer, default=0)
    losses: Mapped[int] = mapped_column(Integer, default=0)
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)


class GameServer(Base):
    __tablename__ = "game_servers"

    id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)
    ip: Mapped[str] = mapped_column(String(255))
    port: Mapped[int] = mapped_column(Integer)
    mode: Mapped[Mode] = mapped_column(SAEnum(Mode))
    status: Mapped[ServerStatus] = mapped_column(SAEnum(ServerStatus), default=ServerStatus.available)
    last_heartbeat: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    # DB-stored fallback shown immediately in the server list; a live server
    # is queried directly for its real-time count (see
    # spacewar/autoload/network_manager.gd's UDP query responder and
    # menu/server_select.gd's ping probe), which overrides this in the UI
    # once that probe answers.
    player_count: Mapped[int] = mapped_column(Integer, default=0)
    max_players: Mapped[int] = mapped_column(Integer, default=50)


class Match(Base):
    __tablename__ = "matches"

    id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)
    mode: Mapped[Mode] = mapped_column(SAEnum(Mode))
    server_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("game_servers.id"))
    started_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

    players: Mapped[list["MatchPlayer"]] = relationship(back_populates="match")


class MatchPlayer(Base):
    __tablename__ = "match_players"

    id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)
    match_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("matches.id"))
    player_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("players.id"))
    team: Mapped[int] = mapped_column(Integer)  # 0 or 1

    match: Mapped["Match"] = relationship(back_populates="players")
