from __future__ import annotations

from datetime import date
from unittest.mock import patch

import pytest

from apps.alumni.profiles.models import AlumniProfile
from apps.alumni.tracking.models import (
    CareerMilestone,
    ImpactMetric,
    ImpactRecord,
    ImpactSource,
    MilestoneType,
    ResearchOutput,
)
from apps.alumni.tracking.orcid import OrcidUpstreamError, OrcidWork
from apps.alumni.tracking.services import (
    build_impact_snapshot,
    record_milestone,
    sync_orcid,
)


@pytest.mark.django_db
def test_record_milestone_creates_row_and_triggers_notification(alumni_user):
    profile = AlumniProfile.objects.create(user=alumni_user)
    milestone = record_milestone(
        profile,
        milestone_type=MilestoneType.AWARD,
        title="Young Scientist Award",
        occurred_on=date(2025, 5, 1),
    )
    assert milestone.pk is not None
    assert profile.milestones.count() == 1


@pytest.mark.django_db
def test_sync_orcid_upserts_research_output(alumni_user):
    profile = AlumniProfile.objects.create(user=alumni_user, orcid_id="0000-0000-0000-0001")
    fake_works = [
        OrcidWork(
            put_code="777",
            title="ORCID test work",
            publication_type="journal-article",
            doi="10.1/test",
            year=2024,
            payload={"x": 1},
        )
    ]
    with patch("apps.alumni.tracking.services.fetch_works", return_value=fake_works):
        log = sync_orcid(profile)
    assert log.consecutive_failures == 0
    assert log.last_success_at is not None
    assert ResearchOutput.objects.filter(profile=profile, put_code="777").count() == 1


@pytest.mark.django_db
def test_sync_orcid_records_failure(alumni_user):
    profile = AlumniProfile.objects.create(user=alumni_user, orcid_id="0000-0000-0000-0002")
    with patch(
        "apps.alumni.tracking.services.fetch_works",
        side_effect=OrcidUpstreamError("boom"),
    ):
        log = sync_orcid(profile)
    assert log.consecutive_failures == 1
    assert "boom" in log.last_error


@pytest.mark.django_db
def test_build_impact_snapshot_idempotent(alumni_user):
    AlumniProfile.objects.create(user=alumni_user)
    s1 = build_impact_snapshot("2026-Q1")
    s2 = build_impact_snapshot("2026-Q1")
    assert s1.pk == s2.pk
    assert s1.total_alumni == 1
