import pytest
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
from django.utils import timezone

from apps.core.authentication.models import CustomUser
from apps.core.permissions.rep_career import VIEW_REP_JOB_APPLICATIONS
from apps.alumni.careers.access import user_can_view_job_listing_applications
from apps.alumni.careers.models import CVProfile, JobApplication, JobListing
from apps.alumni.careers.services import (
    cv_to_dict,
    get_or_create_cv,
    resolve_cv_display_for_recruiter,
)


@pytest.fixture
def listing_poster(django_user_model):
    return django_user_model.objects.create_user(email="poster@example.com", password="x")


@pytest.fixture
def stranger(django_user_model):
    return django_user_model.objects.create_user(email="stranger@example.com", password="x")


@pytest.fixture
def recruiter(django_user_model):
    u = django_user_model.objects.create_user(email="recruiter@example.com", password="x")
    ct = ContentType.objects.get_for_model(CustomUser)
    perm = Permission.objects.get(content_type=ct, codename="view_rep_job_applications")
    u.user_permissions.add(perm)
    return u


@pytest.fixture
def job_listing(listing_poster):
    return JobListing.objects.create(
        title="Field officer",
        company="RUFORUM",
        location="Nairobi",
        job_type=JobListing.JobType.FULL_TIME,
        description="<p>Do work</p>",
        posted_by=listing_poster,
        is_active=True,
    )


@pytest.mark.django_db
def test_poster_can_view_applications(listing_poster, job_listing):
    assert user_can_view_job_listing_applications(listing_poster, job_listing) is True


@pytest.mark.django_db
def test_stranger_cannot_view_applications(stranger, job_listing):
    assert user_can_view_job_listing_applications(stranger, job_listing) is False


@pytest.mark.django_db
def test_recruiter_perm_can_view_any_listing(recruiter, job_listing):
    assert user_can_view_job_listing_applications(recruiter, job_listing) is True


@pytest.mark.django_db
def test_applications_list_403_for_stranger(client, stranger, job_listing):
    client.force_login(stranger)
    url = reverse("rep_career:job_applications", kwargs={"listing_pk": job_listing.pk})
    assert client.get(url).status_code == 403


@pytest.mark.django_db
def test_applications_list_200_for_poster(client, listing_poster, job_listing):
    client.force_login(listing_poster)
    url = reverse("rep_career:job_applications", kwargs={"listing_pk": job_listing.pk})
    assert client.get(url).status_code == 200


@pytest.mark.django_db
def test_application_detail_requires_access(client, listing_poster, stranger, job_listing):
    applicant = CustomUser.objects.create_user(email="applicant@example.com", password="x")
    app = JobApplication.objects.create(
        listing=job_listing,
        applicant=applicant,
        cover_letter="",
        cv_snapshot={},
    )
    client.force_login(stranger)
    url = reverse(
        "rep_career:job_application_detail",
        kwargs={"listing_pk": job_listing.pk, "pk": app.pk},
    )
    assert client.get(url).status_code == 403

    client.force_login(listing_poster)
    assert client.get(url).status_code == 200


@pytest.mark.django_db
def test_view_perm_string_matches_model():
    assert VIEW_REP_JOB_APPLICATIONS == "core.view_rep_job_applications"


@pytest.mark.django_db
def test_resolve_cv_uses_live_when_updated_after_apply(django_user_model, job_listing):
    applicant = django_user_model.objects.create_user(email="applicant2@example.com", password="x")
    cv = get_or_create_cv(applicant)
    cv.headline = "Old"
    cv.save()
    cv = CVProfile.objects.prefetch_related("sections").get(pk=cv.pk)
    app = JobApplication.objects.create(
        listing=job_listing,
        applicant=applicant,
        cv_snapshot=cv_to_dict(cv),
    )
    applied = app.applied_at
    cv.headline = "New headline after apply"
    cv.save()
    CVProfile.objects.filter(pk=cv.pk).update(updated_at=applied + timezone.timedelta(seconds=5))
    cv = CVProfile.objects.prefetch_related("sections").get(pk=cv.pk)
    display, mode = resolve_cv_display_for_recruiter(app, cv)
    assert mode == "live_updated"
    assert display["headline"] == "New headline after apply"


@pytest.mark.django_db
def test_resolve_cv_backfills_when_snapshot_empty(django_user_model, job_listing):
    applicant = django_user_model.objects.create_user(email="applicant3@example.com", password="x")
    cv = get_or_create_cv(applicant)
    cv.headline = "Only on profile"
    cv.save()
    app = JobApplication.objects.create(listing=job_listing, applicant=applicant, cv_snapshot={})
    cv = CVProfile.objects.prefetch_related("sections").get(pk=cv.pk)
    display, mode = resolve_cv_display_for_recruiter(app, cv)
    assert mode == "live_backfill"
    assert display["headline"] == "Only on profile"

# NOTE: ``test_application_detail_exposes_applicant_certificates`` was removed
# with the REP LMS. Applicant certificates were sourced from REP Certificate/
# Enrolment; with learning on Moodle the inline credential list is no longer
# populated from REP (a Moodle-backed feed can repopulate it later via MEL).
