from datetime import datetime, timezone
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import declared_attr

db = SQLAlchemy()

# Maximum number of entries retained per leaderboard after a prune
LEADERBOARD_CAP = 1000


class ScoreEntryMixin:
    """Shared column definitions and serialization for all leaderboard tables."""

    @declared_attr
    def id(cls):
        return db.Column(db.Integer, primary_key=True, autoincrement=True)

    @declared_attr
    def name(cls):
        return db.Column(db.String(100), nullable=False)

    @declared_attr
    def score(cls):
        # Index score descending so top-N queries hit the index directly
        return db.Column(db.Integer, nullable=False, index=True)

    @declared_attr
    def created(cls):
        return db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), nullable=False)

    def to_dict(self):
        return {
            "id": self.id,
            "name": self.name,
            "score": self.score,
            "created": self.created.isoformat() if self.created else None,
        }


class GlobalEntry(ScoreEntryMixin, db.Model):
    __tablename__ = "global"


class WeeklyEntry(ScoreEntryMixin, db.Model):
    __tablename__ = "weekly"


class DailyEntry(ScoreEntryMixin, db.Model):
    __tablename__ = "daily"


# Maps the URL <leaderboard> segment to its model class
LEADERBOARD_MAP = {
    "global": GlobalEntry,
    "weekly": WeeklyEntry,
    "daily": DailyEntry,
}
