"""Time and load guard for player training. Version 1 conservative beta policy.

Daily quota counts completed and scheduled sessions for the same player across
individual/team paths. Cancelled sessions do not consume a slot.
Player row locks in TrainingSchedulingService serialize competing schedulers.
"""
from datetime import timedelta

from django.conf import settings
from django.utils import timezone
from .exceptions import InvalidTrainingDateError, TrainingDailyLimitExceededError
from .models import TrainingParticipant, TrainingSessionStatus

# Deployment can adjust these limits explicitly after game-design approval.
# Defaults are conservative beta safeguards, not hardwired engine constants.
MAX_PLAYER_SESSIONS_PER_DAY = max(1, int(getattr(settings, "FTG_TRAINING_MAX_SESSIONS_PER_DAY", 2)))
MAX_ADVANCE_SCHEDULING_DAYS = max(0, int(getattr(settings, "FTG_TRAINING_MAX_SCHEDULE_AHEAD_DAYS", 7)))


def check_schedule_date(training_date):
    today = timezone.localdate()
    if training_date < today:
        raise InvalidTrainingDateError("Player training cannot be backdated.")
    if training_date > today + timedelta(days=MAX_ADVANCE_SCHEDULING_DAYS):
        raise InvalidTrainingDateError(f"Player training may be scheduled at most {MAX_ADVANCE_SCHEDULING_DAYS} days ahead.")


def check_daily_capacity(*, players, training_date):
    # Each Player must already be locked by its scheduling caller.
    busy_ids = set()
    for player in players:
        count = TrainingParticipant.objects.filter(
            player_id=player.pk,
            session__training_date=training_date,
        ).exclude(session__status=TrainingSessionStatus.CANCELLED).count()
        if count >= MAX_PLAYER_SESSIONS_PER_DAY:
            busy_ids.add(str(player.pk))
    if busy_ids:
        raise TrainingDailyLimitExceededError(
            f"Player daily training limit ({MAX_PLAYER_SESSIONS_PER_DAY} total individual/team sessions) exceeded."
        )


def check_execution_date(training_date):
    if training_date > timezone.localdate():
        raise InvalidTrainingDateError("Scheduled training cannot be executed before its date.")
