from __future__ import annotations

from datetime import date
from decimal import Decimal

import pytest
from django.contrib.auth import get_user_model
from django.urls import reverse

from apps.alumni.profiles.models import AlumniProfile
from apps.alumni.tracking.models import (
    ImpactMetric,
    ImpactRecord,
    ImpactSource,
    ResearchOutput,
)
from apps.alumni.tracking.services import generate_donor_impact_report
from apps.core.permissions.roles import UserRole

User = get_user_model()


# --- Fix 2: MilestoneCreate gated for non-alumni roles ------------------------


@pytest.mark.django_db
def test_milestone_create_blocked_for_non_alumni_role(client):
    """An entrepreneur (not alumni/scholar, no profile) may not record a
    milestone and must NOT be silently turned into an alumni profile."""
    user = User.objects.create_user(email="ent@example.com", password="pw")
    user.role = UserRole.ENTREPRENEUR
    user.save()
    client.force_login(user)

    url = reverse("alumni_tracking:milestone_create")
    resp = client.get(url)

    assert resp.status_code == 302
    assert resp.url == reverse("alumni_tracking:milestone_list")
    # No alumni profile was auto-created for the blocked user.
    assert not AlumniProfile.objects.filter(user=user).exists()

    # And a POST is likewise blocked (no CareerMilestone created).
    post = client.post(
        url,
        {
            "milestone_type": "award",
            "title": "Should not persist",
            "occurred_on": "2026-01-01",
            "visibility": "public",
        },
    )
    assert post.status_code == 302
    assert not AlumniProfile.objects.filter(user=user).exists()


@pytest.mark.django_db
def test_milestone_create_allowed_for_alumni(client, alumni_user):
    client.force_login(alumni_user)
    resp = client.get(reverse("alumni_tracking:milestone_create"))
    assert resp.status_code == 200


# --- Fix 4: ImpactRecord create form persists + shows in report aggregate -----


@pytest.mark.django_db
def test_impact_record_create_persists_and_aggregates(
    client, alumni_user, alumni_officer_user
):
    profile = AlumniProfile.objects.create(user=alumni_user)
    client.force_login(alumni_officer_user)

    resp = client.post(
        reverse("alumni_tracking:impact_record_create"),
        {
            "profile": profile.pk,
            "metric": ImpactMetric.FUNDING_SECURED_USD,
            "value": "5000.00",
            "period_label": "2026",
            "source": ImpactSource.SELF,
        },
    )
    assert resp.status_code == 302

    record = ImpactRecord.objects.get(profile=profile)
    assert record.metric == ImpactMetric.FUNDING_SECURED_USD
    assert record.value == Decimal("5000.00")

    # The saved record rolls into the donor impact report aggregate.
    report = generate_donor_impact_report("2026")
    assert report["funding_secured_usd"] == 5000.0


@pytest.mark.django_db
def test_impact_record_create_blocked_for_non_staff(client, alumni_user):
    client.force_login(alumni_user)
    resp = client.get(reverse("alumni_tracking:impact_record_create"))
    assert resp.status_code in (302, 403)


# --- Fix 1: research outputs page renders -------------------------------------


@pytest.mark.django_db
def test_research_outputs_page_renders(client, alumni_user):
    profile = AlumniProfile.objects.create(
        user=alumni_user, orcid_id="0000-0000-0000-0001"
    )
    ResearchOutput.objects.create(
        profile=profile,
        put_code="1",
        title="A syntropic agroforestry trial",
        publication_type="journal-article",
        doi="10.1/abc",
        year=2025,
    )
    client.force_login(alumni_user)

    resp = client.get(reverse("alumni_tracking:research_outputs"))
    assert resp.status_code == 200
    assert b"A syntropic agroforestry trial" in resp.content


@pytest.mark.django_db
def test_research_sync_requires_orcid(client, alumni_user):
    AlumniProfile.objects.create(user=alumni_user)  # no orcid_id
    client.force_login(alumni_user)

    resp = client.post(reverse("alumni_tracking:research_outputs_sync"))
    assert resp.status_code == 302
    assert resp.url == reverse("alumni_tracking:research_outputs")
