"""Bounded, auditable club staff benefits; permanent player ratings never change."""

from decimal import Decimal

from django.db import transaction

from careers.retirement import canonical_hash

from .models import ClubStaffAssignment, StaffMatchEffect

BONUSES = {
    "AMATEUR": Decimal("0.01"),
    "NORMAL": Decimal("0.02"),
    "PROFESSIONAL": Decimal("0.035"),
    "SUPERSTAR": Decimal("0.05"),
}


def current_effect(club_id):
    from django.utils import timezone

    rows = list(
        ClubStaffAssignment.objects.filter(
            club_id=club_id, status="ACTIVE"
        ).select_related("staff_member__capability", "employment_plan")
    )
    # Paid catalogue assignments use their exact salary contract, including its dates.
    today = timezone.localdate()

    def has_contract(row):
        if row.role == "HEAD_COACH":
            from clubs.models import Club
            club=Club.objects.get(pk=club_id)
            if not club.coach_user_id or row.staff_member.coach_career_id!=club.coach_career_id:
                return False
            if not row.employment_plan_id:
                return True
        if row.employment_plan_id:
            plan = row.employment_plan
            return (
                plan.status in ["ACTIVE", "ENDED"]
                and plan.start_date <= today <= plan.end_date
            )
        return row.staff_member.payroll_plans.filter(
            club_id=club_id,
            status__in=["ACTIVE", "ENDED"],
            start_date__lte=today,
            end_date__gte=today,
        ).exists()

    rows = [row for row in rows if has_contract(row)]
    from club_payroll.models import PayrollObligation

    unpaid = set(
        PayrollObligation.objects.filter(
            club_id=club_id,
            plan__staff_member_id__in=[r.staff_member_id for r in rows],
            due_date__lte=timezone.localdate(),
        )
        .exclude(status__in=["PAID", "CANCELLED", "WAIVED"])
        .values_list("plan__staff_member_id", flat=True)
    )
    rows = [r for r in rows if r.staff_member_id not in unpaid]
    assistants = sorted(
        [r for r in rows if r.role == "ASSISTANT_COACH"],
        key=lambda r: BONUSES[r.staff_member.tier],
        reverse=True,
    )
    bonus = min(
        Decimal("0.08"),
        sum(
            (
                BONUSES[r.staff_member.tier] * weight
                for r, weight in zip(
                    assistants, [Decimal(1), Decimal("0.5"), Decimal("0.25")]
                )
            ),
            Decimal(0),
        ),
    )
    fitness = max(
        (BONUSES[r.staff_member.tier] for r in rows if r.role == "FITNESS_COACH"),
        default=Decimal(0),
    )
    contributions={str(r.pk):BONUSES[r.staff_member.tier]*weight for r,weight in zip(assistants,[Decimal(1),Decimal('0.5'),Decimal('0.25')])}
    remaining=Decimal('0.08')
    for key,value in contributions.items():
        contributions[key]=min(value,remaining)
        remaining-=contributions[key]
    return {
        "policy": "ftg.staff.match_effect.v1",
        "team_bonus": str(bonus),
        "fatigue_reduction": str(fitness),
        "staff": [
            {
                "assignment_id": str(r.pk),
                "member_id": str(r.staff_member_id),
                "role": r.role,
                "tier": r.staff_member.tier,
                "capability_revision": r.staff_member.capability.revision,
                "team_bonus_contribution":str(contributions.get(str(r.pk),Decimal(0))),
                "fatigue_reduction_contribution":str(fitness if r.role=='FITNESS_COACH' else Decimal(0)),
            }
            for r in rows
        ],
    }


@transaction.atomic
def for_match(match_id, club_id):
    existing = StaffMatchEffect.objects.filter(
        match_id=match_id, club_id=club_id
    ).first()
    if existing:
        if canonical_hash(existing.payload) != existing.evidence_hash:
            raise ValueError("Staff match evidence integrity check failed.")
        return existing.payload
    payload = current_effect(club_id)
    row, _ = StaffMatchEffect.objects.get_or_create(
        match_id=match_id,
        club_id=club_id,
        defaults={"payload": payload, "evidence_hash": canonical_hash(payload)},
    )
    return row.payload
