"""FRREP-UR006 — role-agnostic profile-completion nudge.

Covers: the ``profile_completion`` helper, the universal dashboard banner
(and that it defers to the existing RIMS applicant banner rather than
double-showing), and the post-verification message nudge.
"""
from __future__ import annotations

import pytest
from django.contrib.auth import get_user_model
from django.core.signing import TimestampSigner
from django.urls import reverse

from apps.core.authentication.models import UserProfile
from apps.core.authentication.profile_completion import profile_completion
from apps.core.dashboard.widgets.core_widgets import ProfileCompletionBanner
from apps.core.permissions.roles import UserRole

User = get_user_model()
pytestmark = pytest.mark.django_db


def _user(email="profile@x.com", **kw):
    return User.objects.create_user(email=email, password="x", **kw)


# ------------------------------------------------------------- helper


def test_profile_completion_fresh_user_is_zero_percent():
    # A post_save signal (apps.core.signals.ensure_user_profile) creates an
    # empty UserProfile row for every new user — completion starts at 0%.
    u = _user()
    result = profile_completion(u)
    assert result["percent"] == 0
    assert set(result["missing"]) == {
        "country",
        "areas of interest",
        "biography",
        "professional background",
        "academic qualifications",
    }


def test_profile_completion_partial():
    u = _user(email="partial@x.com")
    UserProfile.objects.filter(user=u).update(country="Uganda", bio="Hello there.")
    u = User.objects.get(pk=u.pk)  # drop the cached (stale) profile descriptor
    result = profile_completion(u)
    assert result["percent"] == 40  # 2 of 5 fields
    assert "country" not in result["missing"]
    assert "biography" not in result["missing"]
    assert "areas of interest" in result["missing"]
    assert "professional background" in result["missing"]
    assert "academic qualifications" in result["missing"]


def test_profile_completion_full():
    u = _user(email="full@x.com")
    UserProfile.objects.filter(user=u).update(
        country="Kenya",
        areas_of_interest="soil science",
        bio="A short bio.",
        professional_background="Worked in agriculture extension for 5 years.",
        qualifications=[{"institution": "Makerere", "qualification": "BSc"}],
    )
    u = User.objects.get(pk=u.pk)
    result = profile_completion(u)
    assert result["percent"] == 100
    assert result["missing"] == []


def test_profile_completion_anonymous_user():
    class Anon:
        is_authenticated = False

    result = profile_completion(Anon())
    assert result["percent"] == 0
    assert len(result["missing"]) == 5


# ------------------------------------------------------------- banner widget


def test_banner_shown_for_incomplete_profile():
    u = _user(email="incomplete@x.com", role=UserRole.LEARNER)
    assert ProfileCompletionBanner.is_enabled(u) is True
    ctx = ProfileCompletionBanner().get_context(u)
    assert "Complete your professional profile" in ctx["title"]
    assert ctx["cta_href"].startswith(reverse("accounts:profile"))


def test_banner_hidden_for_complete_profile():
    u = _user(email="complete@x.com", role=UserRole.LEARNER)
    UserProfile.objects.filter(user=u).update(
        country="Kenya",
        areas_of_interest="soil science",
        bio="A short bio.",
        professional_background="Worked in agriculture extension.",
        qualifications=[{"institution": "Makerere", "qualification": "BSc"}],
    )
    u = User.objects.get(pk=u.pk)
    assert ProfileCompletionBanner.is_enabled(u) is False


def test_banner_defers_to_rims_applicant_banner():
    """RIMS applicants already get IncompleteProfileBanner — the universal
    banner must not also show for them (no double-banner)."""
    u = _user(email="applicant@x.com", role=UserRole.APPLICANT)
    assert ProfileCompletionBanner.is_enabled(u) is False


def test_banner_disabled_for_anonymous():
    class Anon:
        is_authenticated = False

    assert ProfileCompletionBanner.is_enabled(Anon()) is False


# ------------------------------------------------------------- post-verification nudge


def test_verify_email_message_mentions_profile_completion(client):
    signer = TimestampSigner()
    u = _user(email="verify-me@x.com")
    u.email_verified = False
    u.save(update_fields=["email_verified"])
    token = signer.sign(str(u.pk))

    resp = client.get(reverse("accounts:verify_email", kwargs={"token": token}), follow=True)
    assert resp.status_code == 200
    messages = [str(m) for m in resp.context["messages"]]
    assert any("complete your professional profile" in m.lower() for m in messages)
    u.refresh_from_db()
    assert u.email_verified is True
