"""Applicant profile-completeness gate.

Several of the eligibility rule types (sector, age, degree, nationality —
see EligibilityRule.RuleType) evaluate fields on CustomUser/UserProfile that
are optional at the account level (blank=True everywhere, since the same
model serves REP students, alumni, SME Hub users, and RIMS applicants
alike). An applicant who never filled these in doesn't get treated as
"not applicable" by a configured rule — they fail it outright, with no
indication the real problem is a blank profile field, not their actual
age/degree/nationality.

This module is the single source of truth for what "a complete-enough
profile to apply" means, used both by the apply-flow gate (hard block) and
the dashboard banner (proactive nudge before they even try).
"""
from django.contrib import messages
from django.shortcuts import redirect
from django.urls import reverse

# (label, get-value-from-user) — checked in this order so the banner/redirect
# message lists them in a sensible reading order.
REQUIRED_FIELDS = [
    ("first name", lambda u: u.first_name),
    ("last name", lambda u: u.last_name),
    ("phone number", lambda u: u.phone),
    ("country", lambda u: getattr(u.profile, "country", "") if hasattr(u, "profile") else ""),
    ("highest degree level", lambda u: getattr(u.profile, "degree_level", "") if hasattr(u, "profile") else ""),
    ("date of birth", lambda u: getattr(u.profile, "date_of_birth", None) if hasattr(u, "profile") else None),
    ("areas of interest", lambda u: getattr(u.profile, "areas_of_interest", "") if hasattr(u, "profile") else ""),
]


def missing_profile_fields(user) -> list[str]:
    """Return the labels of required fields the user hasn't filled in."""
    if not user.is_authenticated:
        return [label for label, _ in REQUIRED_FIELDS]
    return [label for label, getter in REQUIRED_FIELDS if not getter(user)]


def is_profile_complete(user) -> bool:
    return not missing_profile_fields(user)


class ProfileCompleteRequiredMixin:
    """Blocks starting a new application until the applicant's profile has
    every field REQUIRED_FIELDS lists — mirrors the "complete your candidate
    profile before you can apply" pattern common to UN/multilateral
    recruitment systems. Only guards entry points that *create* an
    Application (GET on the first wizard step / the generic apply view);
    resuming an already-started draft isn't re-gated.
    """

    def dispatch(self, request, *args, **kwargs):
        missing = missing_profile_fields(request.user)
        if missing:
            messages.warning(
                request,
                "Complete your profile before applying — missing: " + ", ".join(missing) + ".",
            )
            next_url = request.get_full_path()
            return redirect(f"{reverse('accounts:profile')}?next={next_url}")
        return super().dispatch(request, *args, **kwargs)
