"""PRD §5.1 FRFA-AM005 — per-field validation reasons on the application form.

Asserts the form surfaces specific, actionable reasons when fields are
missing or too short, rather than Django's generic "This field is required".
"""

from __future__ import annotations

from datetime import timedelta

import pytest
from django.utils import timezone

from apps.rims.grants.forms import ApplicationForm
from apps.rims.grants.models import GrantCall


def _published_call(**overrides) -> GrantCall:
    base = {
        "title": "Validation test call",
        "slug": "validation-test-call",
        "opens_at": timezone.now() - timedelta(days=1),
        "closes_at": timezone.now() + timedelta(days=14),
        "status": GrantCall.Status.PUBLISHED,
    }
    base.update(overrides)
    return GrantCall.objects.create(**base)


@pytest.mark.django_db
def test_missing_proposal_surfaces_specific_reason(institution):
    """FRFA-AM005 — empty proposal must explain *why* a proposal matters."""
    call = _published_call()
    form = ApplicationForm(
        data={"institution": institution.pk, "proposal": ""},
        call=call,
    )
    assert not form.is_valid()
    assert "proposal" in form.errors
    msg = form.errors["proposal"][0]
    # Reason should reference what the applicant needs to do, not "required".
    assert "proposal is required" in msg.lower()
    assert "describe" in msg.lower() or "describe your project" in msg.lower()


@pytest.mark.django_db
def test_short_proposal_surfaces_character_count(institution):
    """FRFA-AM005 — a too-short proposal cites the actual vs minimum length."""
    call = _published_call(slug="validation-call-short")
    form = ApplicationForm(
        data={"institution": institution.pk, "proposal": "short."},
        call=call,
    )
    assert not form.is_valid()
    msg = form.errors["proposal"][0]
    assert str(ApplicationForm.PROPOSAL_MIN_LENGTH) in msg
    assert "characters" in msg.lower()


@pytest.mark.django_db
def test_missing_institution_explains_why_it_matters(institution):
    """FRFA-AM005 — missing institution explains the downstream consequence."""
    long_proposal = "Lorem ipsum " * 40  # well above the 200-char minimum
    call = _published_call(slug="validation-call-inst")
    form = ApplicationForm(
        data={"institution": "", "proposal": long_proposal},
        call=call,
    )
    assert not form.is_valid()
    assert "institution" in form.errors
    msg = form.errors["institution"][0]
    assert "institution" in msg.lower()
    assert "affiliation" in msg.lower() or "eligibility" in msg.lower()


@pytest.mark.django_db
def test_scholarship_university_required_when_call_demands_it(institution):
    """FRFA-CS013 / FRFA-AM005 — scholarship target university error is specific."""
    long_proposal = "Lorem ipsum " * 40
    call = _published_call(
        slug="validation-call-scholarship",
        call_type=GrantCall.CallType.SCHOLARSHIP,
        scholarship_university_required=True,
    )
    form = ApplicationForm(
        data={
            "institution": institution.pk,
            "proposal": long_proposal,
            "scholarship_university_choice": "",
            "scholarship_course_choice": "",
        },
        call=call,
    )
    assert not form.is_valid()
    assert "scholarship_university_choice" in form.errors
    msg = form.errors["scholarship_university_choice"][0]
    assert "scholarship" in msg.lower() and "university" in msg.lower()
