"""Old-system parity: legacy grants_reports.Month12Report (and its
per-period siblings) — structured mid-project PI narrative reporting.

Covers:
- Creating a draft PeriodicNarrativeReport against an Award
- DRAFT -> SUBMITTED transition stamps submitted_at and (when linked)
  back-fills the parent ReportingCalendarEntry.submitted_at
- SUBMITTED -> ACCEPTED / REVISION_REQUIRED decision transitions
- Child records (pictures, linkages, comments) attach correctly
"""
from datetime import date, timedelta
from decimal import Decimal

import pytest
from django.utils import timezone
from django_fsm import TransitionNotAllowed

from apps.rims.grants.models import (
    Application,
    BeneficiaryGroup,
    GrantCall,
    PeriodicNarrativeReport,
    ReportComment,
    ReportingCalendarEntry,
    ReportLinkage,
    ReportPicture,
)
from apps.rims.grants.services import (
    award_application,
    shortlist_application,
    submit_application,
)


def _award_for(applicant_user, institution, *, suffix="pnr"):
    call = GrantCall.objects.create(
        title="Periodic report call",
        slug=f"pnr-{suffix}-{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)
    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_create_draft_report(applicant_user, institution):
    award = _award_for(applicant_user, institution, suffix="create")
    report = PeriodicNarrativeReport.objects.create(
        award=award,
        period_label="Month 12",
        direct_beneficiaries=50,
        indirect_beneficiaries=200,
    )
    assert report.status == PeriodicNarrativeReport.Status.DRAFT
    assert report.submitted_at is None
    assert award.periodic_narrative_reports.count() == 1


@pytest.mark.django_db
def test_beneficiary_groups_m2m(applicant_user, institution):
    award = _award_for(applicant_user, institution, suffix="groups")
    report = PeriodicNarrativeReport.objects.create(award=award, period_label="Month 12")
    group = BeneficiaryGroup.objects.create(name="Smallholder farmers")
    report.beneficiary_groups.add(group)
    assert list(report.beneficiary_groups.all()) == [group]


@pytest.mark.django_db
def test_submit_stamps_timestamp_and_updates_calendar_entry(applicant_user, institution):
    award = _award_for(applicant_user, institution, suffix="submit")
    funding_record = award.application.call.funding_record
    entry = None
    if funding_record is not None:
        entry = ReportingCalendarEntry.objects.create(
            funding_record=funding_record,
            kind=ReportingCalendarEntry.Kind.NARRATIVE,
            due_on=date.today(),
        )
    report = PeriodicNarrativeReport.objects.create(
        award=award,
        reporting_calendar_entry=entry,
        period_label="Month 12",
    )
    report.submit()
    report.save()
    assert report.status == PeriodicNarrativeReport.Status.SUBMITTED
    assert report.submitted_at is not None
    if entry is not None:
        entry.refresh_from_db()
        assert entry.submitted_at is not None


@pytest.mark.django_db
def test_cannot_submit_twice(applicant_user, institution):
    award = _award_for(applicant_user, institution, suffix="twice")
    report = PeriodicNarrativeReport.objects.create(award=award, period_label="Month 12")
    report.submit()
    report.save()
    with pytest.raises(TransitionNotAllowed):
        report.submit()


@pytest.mark.django_db
def test_accept_and_request_revision(applicant_user, institution):
    award = _award_for(applicant_user, institution, suffix="decision")
    report = PeriodicNarrativeReport.objects.create(award=award, period_label="Month 12")
    report.submit()
    report.save()

    report.request_revision()
    report.save()
    assert report.status == PeriodicNarrativeReport.Status.REVISION_REQUIRED

    report.resubmit()
    report.save()
    assert report.status == PeriodicNarrativeReport.Status.SUBMITTED

    report.accept()
    report.save()
    assert report.status == PeriodicNarrativeReport.Status.ACCEPTED
    assert report.accepted_at is not None


@pytest.mark.django_db
def test_child_records(applicant_user, institution):
    award = _award_for(applicant_user, institution, suffix="children")
    report = PeriodicNarrativeReport.objects.create(award=award, period_label="Month 12")
    ReportPicture.objects.create(report=report, image="reports/test.jpg", caption="Field day")
    ReportLinkage.objects.create(report=report, organisation="Partner Org", partner_description="Co-funder")
    ReportComment.objects.create(report=report, comment="Looks good")
    assert report.pictures.count() == 1
    assert report.linkages.count() == 1
    assert report.comments.count() == 1
