"""Budget create/edit capture BudgetLine rows (ceiling = sum of amounts)."""

import uuid
from datetime import timedelta
from decimal import Decimal

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

from apps.rims.finance.models import Budget, BudgetLine
from apps.rims.grants.models import Application, GrantCall
from apps.rims.grants.services import award_application, shortlist_application, submit_application


def _award_without_budget(applicant_user, institution):
    call = GrantCall.objects.create(
        title="Budget UI call",
        slug=f"budget-ui-{uuid.uuid4().hex[:10]}",
        opens_at=timezone.now() - timedelta(days=1),
        closes_at=timezone.now() + timedelta(days=30),
        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("50000"), timezone.now().date() + timedelta(days=365), narrative="")
    return app.award


@pytest.mark.django_db
def test_budget_create_saves_lines(client, finance_user, applicant_user, institution):
    award = _award_without_budget(applicant_user, institution)
    client.force_login(finance_user)
    url = reverse("rims_finance:budget_create")
    data = {
        "award": str(award.pk),
        "name": "Operating",
        "fiscal_year": "",
        "funding_source": "",
        "lines-TOTAL_FORMS": "3",
        "lines-INITIAL_FORMS": "0",
        "lines-MIN_NUM_FORMS": "0",
        "lines-MAX_NUM_FORMS": "1000",
        "lines-0-label": "Personnel",
        "lines-0-amount": "12000",
        "lines-1-label": "",
        "lines-1-amount": "",
        "lines-2-label": "Travel",
        "lines-2-amount": "3000.50",
    }
    resp = client.post(url, data, follow=False)
    assert resp.status_code == 302
    budget = Budget.objects.get(name="Operating")
    lines = list(budget.lines.order_by("pk").values_list("label", "amount"))
    assert len(lines) == 2
    assert lines[0][0] == "Personnel"
    assert lines[0][1] == Decimal("12000")
    assert lines[1][0] == "Travel"
    assert lines[1][1] == Decimal("3000.50")


@pytest.mark.django_db
def test_budget_edit_updates_lines(client, finance_user, applicant_user, institution):
    award = _award_without_budget(applicant_user, institution)
    budget = Budget.objects.create(award=award, name="B")
    line = BudgetLine.objects.create(budget=budget, label="Old", amount=Decimal("100"))

    client.force_login(finance_user)
    url = reverse("rims_finance:budget_edit", kwargs={"pk": budget.pk})
    data = {
        "award": str(award.pk),
        "name": "B",
        "fiscal_year": "",
        "funding_source": "",
        "lines-TOTAL_FORMS": "1",
        "lines-INITIAL_FORMS": "1",
        "lines-MIN_NUM_FORMS": "0",
        "lines-MAX_NUM_FORMS": "1000",
        "lines-0-id": str(line.pk),
        "lines-0-label": "Revised",
        "lines-0-amount": "250",
    }
    resp = client.post(url, data, follow=False)
    assert resp.status_code == 302
    line.refresh_from_db()
    assert line.label == "Revised"
    assert line.amount == Decimal("250")
