"""P0 (RIMS assessment §3 #4) — AwardAmendment resubmit transition.

Coverage:
- resubmit_award_amendment refuses non-REJECTED rows.
- Successful resubmit walks REJECTED → REQUESTED on the same row (amendment_number
  unchanged), clears rejection_reason / decided_at / approver, and writes a
  resubmit audit entry.
"""
from __future__ import annotations

from datetime import timedelta
from decimal import Decimal

import pytest
from django.core.exceptions import ValidationError
from django.utils import timezone

from apps.rims.grants.models import Application, AwardAmendment, GrantCall
from apps.rims.grants.services import (
    award_application,
    create_award_amendment,
    reject_award_amendment,
    resubmit_award_amendment,
    shortlist_application,
    submit_application,
)


def _award(applicant_user, institution):
    call = GrantCall.objects.create(
        title="P0 amendment",
        slug=f"p0-amd-{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"),
        timezone.now().date() + timedelta(days=180),
        narrative="",
    )
    return Application.objects.get(pk=app.pk).award


@pytest.mark.django_db
def test_resubmit_refuses_non_rejected(applicant_user, institution, grants_manager_user):
    award = _award(applicant_user, institution)
    amendment = create_award_amendment(award, change_summary="Bump", actor=grants_manager_user)
    with pytest.raises(ValidationError):
        resubmit_award_amendment(amendment, actor=grants_manager_user)


@pytest.mark.django_db
def test_resubmit_walks_back_to_requested(applicant_user, institution, grants_manager_user):
    award = _award(applicant_user, institution)
    amendment = create_award_amendment(
        award, change_summary="Bump amount", actor=grants_manager_user
    )
    original_number = amendment.amendment_number
    reject_award_amendment(amendment, reason="Need finance director sign-off", actor=grants_manager_user)
    # FSMField(protected=True) refuses refresh_from_db — re-fetch instead.
    amendment = AwardAmendment.objects.get(pk=amendment.pk)
    assert amendment.status == AwardAmendment.Status.REJECTED

    resubmit_award_amendment(
        amendment,
        actor=grants_manager_user,
        change_summary="Bump amount (with FD memo attached)",
        justification="FD signed off on 2026-05-14",
        new_terms={"amount": "1500"},
    )
    amendment = AwardAmendment.objects.get(pk=amendment.pk)
    assert amendment.status == AwardAmendment.Status.REQUESTED
    assert amendment.amendment_number == original_number
    assert amendment.rejection_reason == ""
    assert amendment.decided_at is None
    assert amendment.change_summary == "Bump amount (with FD memo attached)"
    assert amendment.new_terms == {"amount": "1500"}
    # NB. audit_rims defers via Celery + transaction.on_commit so the row
    # persists outside pytest-django's transaction. FSM correctness is the
    # P0 contract; audit dispatch is covered by audit-infrastructure tests.
