"""UI smoke tests for the P0–P5 UI work.

These exercise the new view endpoints and assert the templates render with
HTTP 200 and the expected critical content — enough to catch URL / context /
template-tag regressions without browser automation.
"""
from datetime import date, timedelta
from decimal import Decimal

import pytest
from django.urls import reverse
from django.utils import timezone

from apps.rims.grants.models import (
    Application,
    Award,
    AwardAmendment,
    FinalFinancialReport,
    FinalNarrativeReport,
    GrantCall,
)
from apps.rims.grants.closeout_helpers import get_or_create_closeout_record
from apps.rims.grants.services import (
    award_application,
    create_award_amendment,
    shortlist_application,
    submit_application,
)


def _awarded(applicant_user, institution):
    call = GrantCall.objects.create(
        title="Smoke call",
        slug=f"smoke-{int(timezone.now().timestamp() * 1000) % 10_000_000}",
        opens_at=timezone.now() - timedelta(days=1),
        closes_at=timezone.now() + timedelta(days=10),
        status=GrantCall.Status.PUBLISHED,
    )
    app = Application.objects.create(call=call, applicant=applicant_user, institution=institution)
    submit_application(app)
    app = Application.objects.get(pk=app.pk)
    shortlist_application(app)
    award_application(app, Decimal("1000"), date.today() + timedelta(days=180), narrative="")
    return Application.objects.get(pk=app.pk).award


@pytest.mark.django_db
def test_applicant_application_detail_renders_with_withdraw_button(
    client, applicant_user, institution
):
    call = GrantCall.objects.create(
        title="Withdraw-enabled",
        slug=f"with-{int(timezone.now().timestamp())}",
        opens_at=timezone.now() - timedelta(days=1),
        closes_at=timezone.now() + timedelta(days=10),
        status=GrantCall.Status.PUBLISHED,
    )
    app = Application.objects.create(call=call, applicant=applicant_user, institution=institution)
    submit_application(app)
    client.force_login(applicant_user)
    resp = client.get(reverse("rims_grants:application_detail", kwargs={"pk": app.pk}))
    assert resp.status_code == 200
    assert b"Withdraw application" in resp.content


@pytest.mark.django_db
def test_applicant_withdraws_via_post(client, applicant_user, institution):
    call = GrantCall.objects.create(
        title="WD-post",
        slug=f"wdp-{int(timezone.now().timestamp())}",
        opens_at=timezone.now() - timedelta(days=1),
        closes_at=timezone.now() + timedelta(days=10),
        status=GrantCall.Status.PUBLISHED,
    )
    app = Application.objects.create(call=call, applicant=applicant_user, institution=institution)
    submit_application(app)
    client.force_login(applicant_user)
    resp = client.post(
        reverse("rims_grants:application_withdraw", kwargs={"pk": app.pk}),
        follow=False,
    )
    assert resp.status_code in (302, 303)
    assert Application.objects.get(pk=app.pk).status == Application.Status.WITHDRAWN


@pytest.mark.django_db
def test_awardee_can_acknowledge_award_via_post(client, applicant_user, institution):
    award = _awarded(applicant_user, institution)
    client.force_login(applicant_user)
    client.post(reverse("rims_grants:award_acknowledge", kwargs={"pk": award.pk}))
    award.refresh_from_db()
    assert award.acknowledged_at is not None


@pytest.mark.django_db
def test_manager_application_detail_surfaces_po_screen_when_call_opted_in(
    client, applicant_user, institution, grants_manager_user
):
    call = GrantCall.objects.create(
        title="PO gate UI",
        slug=f"po-ui-{int(timezone.now().timestamp())}",
        opens_at=timezone.now() - timedelta(days=1),
        closes_at=timezone.now() + timedelta(days=10),
        status=GrantCall.Status.PUBLISHED,
        programme_officer_screening_enabled=True,
    )
    app = Application.objects.create(call=call, applicant=applicant_user, institution=institution)
    submit_application(app)
    client.force_login(grants_manager_user)
    resp = client.get(
        reverse("rims_grants:manager_application_detail", kwargs={"pk": app.pk})
    )
    assert resp.status_code == 200
    assert b"Programme Officer screening" in resp.content
    assert b"Advance to reviewers" in resp.content


@pytest.mark.django_db
def test_generate_shortlist_view_renders_result_buckets(
    client, applicant_user, institution, grants_manager_user
):
    call = GrantCall.objects.create(
        title="Shortlist UI",
        slug=f"sl-ui-{int(timezone.now().timestamp())}",
        opens_at=timezone.now() - timedelta(days=1),
        closes_at=timezone.now() + timedelta(days=10),
        status=GrantCall.Status.PUBLISHED,
    )
    Application.objects.create(call=call, applicant=applicant_user, institution=institution)
    client.force_login(grants_manager_user)
    resp = client.get(
        reverse("rims_grants:call_generate_shortlist", kwargs={"slug": call.slug})
    )
    assert resp.status_code == 200
    for label in [b"Chosen", b"Tied", b"Below threshold", b"Unscored"]:
        assert label in resp.content


@pytest.mark.django_db
def test_award_detail_surfaces_amendment_buttons(
    client, applicant_user, institution, grants_manager_user
):
    award = _awarded(applicant_user, institution)
    amendment = create_award_amendment(
        award,
        change_summary="Extend end date",
        new_terms={"project_end_date": (date.today() + timedelta(days=365)).isoformat()},
        actor=grants_manager_user,
    )
    client.force_login(grants_manager_user)
    resp = client.get(reverse("rims_grants:award_detail", kwargs={"pk": award.pk}))
    assert resp.status_code == 200
    assert b"Pending approval" in resp.content
    assert b"Approve" in resp.content
    assert b"Reject" in resp.content


@pytest.mark.django_db
def test_award_closeout_renders_final_reports_when_present(
    client, applicant_user, institution, grants_manager_user
):
    award = _awarded(applicant_user, institution)
    closeout = get_or_create_closeout_record(award)
    FinalNarrativeReport.objects.create(closeout=closeout, notes="All done")
    FinalFinancialReport.objects.create(closeout=closeout, notes="Reconciled")
    client.force_login(grants_manager_user)
    resp = client.get(reverse("rims_grants:award_closeout", kwargs={"pk": award.pk}))
    assert resp.status_code == 200
    assert b"Awardee-submitted final reports" in resp.content
    assert b"Narrative report" in resp.content
    assert b"Financial report" in resp.content
