from __future__ import annotations

import datetime

import pytest
from django.contrib.auth import get_user_model

from apps.alumni.engagement.matcher import (
    MenteeContext,
    explain_match,
    score_mentor,
)
from apps.alumni.engagement.services import recommend_mentors
from apps.alumni.profiles.models import AlumniProfile, Employment

User = get_user_model()


@pytest.mark.django_db
def test_score_mentor_rewards_expertise_overlap(alumni_user):
    mentor = AlumniProfile.objects.create(
        user=alumni_user,
        expertise_tags=["agronomy", "climate-resilience"],
    )
    mentee = MenteeContext(
        user_id=999,
        expertise_tags=["agronomy"],
        country="",
        sector="",
    )
    assert score_mentor(mentor, mentee) > 0.0


@pytest.mark.django_db
def test_score_mentor_penalises_active_pairings(alumni_user):
    mentor = AlumniProfile.objects.create(
        user=alumni_user,
        expertise_tags=["policy"],
    )
    mentee = MenteeContext(
        user_id=888, expertise_tags=["policy"], country="", sector=""
    )
    base = score_mentor(mentor, mentee)
    penalised = score_mentor(mentor, mentee, mentor_active_pairings=3)
    assert penalised < base


@pytest.mark.django_db
def test_score_mentor_no_overlap_returns_zero(alumni_user):
    mentor = AlumniProfile.objects.create(user=alumni_user, expertise_tags=["tax"])
    mentee = MenteeContext(user_id=777, expertise_tags=["agronomy"])
    assert score_mentor(mentor, mentee) == 0.0


@pytest.mark.django_db
def test_explain_match_surfaces_shared_dimensions(alumni_user):
    mentor = AlumniProfile.objects.create(
        user=alumni_user,
        expertise_tags=["Agronomy", "policy"],
        mentor_topics=["Grant writing", "fieldwork"],
    )
    Employment.objects.create(
        profile=mentor,
        organisation="ICRAF",
        position="Researcher",
        sector="Research",
        started_on=datetime.date(2021, 1, 1),
    )
    mentee = MenteeContext(
        user_id=999,
        expertise_tags=["agronomy"],
        sector="research",
        topic="need help with grant writing",
    )
    why = explain_match(mentor, mentee)
    assert why.shared_tags == ["agronomy"]  # case-insensitive intersection
    assert why.same_sector is True
    assert "Grant writing" in why.shared_topics
    assert why.has_signal is True


@pytest.mark.django_db
def test_explain_match_no_signal_when_nothing_overlaps(alumni_user):
    mentor = AlumniProfile.objects.create(user=alumni_user, expertise_tags=["tax"])
    mentee = MenteeContext(user_id=888, expertise_tags=["agronomy"])
    why = explain_match(mentor, mentee)
    assert why.shared_tags == []
    assert why.same_country is False
    assert why.same_sector is False
    assert why.shared_topics == []
    assert why.has_signal is False


@pytest.mark.django_db
def test_recommend_mentors_returns_triples_with_explainer(alumni_user, institution):
    # mentee = alumni_user, with an opted-in mentor sharing an expertise tag.
    AlumniProfile.objects.create(user=alumni_user, expertise_tags=["agronomy"])
    mentor_user = User.objects.create_user(email="bob.mentor@example.com", password="pw")
    mentor_user.institution = institution
    mentor_user.save()
    AlumniProfile.objects.create(
        user=mentor_user,
        expertise_tags=["agronomy"],
        mentor_accepting=True,
        visibility_consent=True,
    )
    results = recommend_mentors(alumni_user, limit=10)
    assert results, "expected at least one recommendation"
    profile, score, why = results[0]  # must unpack as a 3-tuple
    assert score > 0.0
    assert why.shared_tags == ["agronomy"]


@pytest.mark.django_db
def test_discover_offers_declared_mentor_topics(client, alumni_user):
    """The 'what you want help with' dropdown is populated from mentors' topics."""
    from django.urls import reverse

    AlumniProfile.objects.create(
        user=alumni_user,
        mentor_accepting=True,
        mentor_topics=["grant writing", "scaling"],
    )
    client.force_login(alumni_user)
    resp = client.get(reverse("alumni_engagement:mentorship_discover"))
    assert resp.status_code == 200
    choices = resp.context["mentor_topic_choices"]
    assert "grant writing" in choices
    assert "scaling" in choices
