"""PRD §5.1 FRFA-AM018 — reviewer workload visibility.

The manager application detail view exposes `reviewer_workload` — a list of
``(reviewer_user, open_assignment_count)`` tuples sorted ascending by count
so the least-loaded reviewers appear first. Already-assigned reviewers are
excluded from the list.
"""
from datetime import timedelta

import pytest
from django.contrib.auth import get_user_model
from django.urls import reverse
from django.utils import timezone

from apps.core.permissions.roles import UserRole
from apps.rims.grants.models import Application, GrantCall, Review
from apps.rims.grants.services import submit_application

User = get_user_model()


def _reviewer(email):
    u = User.objects.create_user(email=email, password="pw")
    u.role = UserRole.REVIEWER
    u.save()
    return u


@pytest.mark.django_db
def test_reviewer_workload_sorted_ascending_by_count(
    client, grants_manager_user, applicant_user, institution
):
    heavy = _reviewer("heavy@example.com")
    medium = _reviewer("medium@example.com")
    light = _reviewer("light@example.com")

    call = GrantCall.objects.create(
        title="Workload visibility",
        slug=f"wl-{int(timezone.now().timestamp())}",
        opens_at=timezone.now() - timedelta(days=1),
        closes_at=timezone.now() + timedelta(days=10),
        status=GrantCall.Status.PUBLISHED,
    )
    target_app = Application.objects.create(call=call, applicant=applicant_user, institution=institution)
    submit_application(target_app)

    # Seed open assignments on different reviewers by creating Review rows
    # against sibling applications on the same call. `heavy` gets 2, `medium`
    # gets 1, `light` gets 0.
    for i in range(3):
        u = User.objects.create_user(email=f"extra{i}@example.com", password="pw")
        extra_app = Application.objects.create(call=call, applicant=u, institution=institution)
        if i < 2:
            Review.objects.create(application=extra_app, reviewer=heavy)
        if i < 1:
            Review.objects.create(application=extra_app, reviewer=medium)

    client.force_login(grants_manager_user)
    resp = client.get(
        reverse("rims_grants:manager_application_detail", kwargs={"pk": target_app.pk})
    )
    assert resp.status_code == 200
    workload = resp.context["reviewer_workload"]
    # Filter to our three test reviewers in case the fixture seeds others.
    relevant = [
        (u, c) for u, c in workload if u.pk in {heavy.pk, medium.pk, light.pk}
    ]
    ordered_emails = [u.email for u, _ in relevant]
    assert ordered_emails == ["light@example.com", "medium@example.com", "heavy@example.com"]
    counts_by_email = {u.email: c for u, c in relevant}
    assert counts_by_email["heavy@example.com"] == 2
    assert counts_by_email["medium@example.com"] == 1
    assert counts_by_email["light@example.com"] == 0


@pytest.mark.django_db
def test_already_assigned_reviewers_excluded_from_workload_list(
    client, grants_manager_user, applicant_user, institution
):
    assigned = _reviewer("already@example.com")
    unassigned = _reviewer("open@example.com")

    call = GrantCall.objects.create(
        title="Excl",
        slug=f"excl-{int(timezone.now().timestamp())}",
        opens_at=timezone.now() - timedelta(days=1),
        closes_at=timezone.now() + timedelta(days=10),
        status=GrantCall.Status.PUBLISHED,
    )
    target_app = Application.objects.create(call=call, applicant=applicant_user, institution=institution)
    submit_application(target_app)
    Review.objects.create(application=target_app, reviewer=assigned)

    client.force_login(grants_manager_user)
    resp = client.get(
        reverse("rims_grants:manager_application_detail", kwargs={"pk": target_app.pk})
    )
    workload_ids = {u.pk for u, _ in resp.context["reviewer_workload"]}
    assert assigned.pk not in workload_ids
    assert unassigned.pk in workload_ids
