import json

import pytest
from django.urls import reverse

from apps.alumni.careers.models import CVProfile, CVSection


@pytest.mark.django_db
def test_cv_builder_saves_profile_and_sections(client, django_user_model):
    user = django_user_model.objects.create_user(email="cvuser@example.com", password="secret123")
    client.force_login(user)
    url = reverse("rep_career:cv_builder")
    sections = {
        "education": [{"degree": "PhD Soil Science", "institution": "University of Nairobi", "year": "2019"}],
        "experience": [{"role": "Researcher", "org": "CIMMYT", "years": "2019–present"}],
        "skills": ["R", "Field trials"],
        "certifications": [],
        "publications": [],
        "languages": ["English (fluent)"],
    }
    resp = client.post(
        url,
        {
            "headline": "Soil scientist",
            "summary": "<p>Summary text</p>",
            "is_public": "on",
            "cv_sections_json": json.dumps(sections),
        },
    )
    assert resp.status_code == 302
    cv = CVProfile.objects.get(user=user)
    assert cv.headline == "Soil scientist"
    assert "<p>Summary text</p>" in cv.summary
    assert cv.is_public is True
    assert CVSection.objects.filter(cv=cv, section_type="education").count() == 1
    edu = CVSection.objects.get(cv=cv, section_type="education")
    assert edu.data[0]["degree"] == "PhD Soil Science"
    assert CVSection.objects.filter(cv=cv, section_type="skills").first().data == ["R", "Field trials"]


@pytest.mark.django_db
def test_cv_builder_clears_section_when_empty_arrays(client, django_user_model):
    user = django_user_model.objects.create_user(email="cvuser2@example.com", password="secret123")
    cv = CVProfile.objects.create(user=user)
    CVSection.objects.create(
        cv=cv,
        section_type="skills",
        data=["Old"],
        sort_order=2,
    )
    client.force_login(user)
    url = reverse("rep_career:cv_builder")
    empty = {
        "education": [],
        "experience": [],
        "skills": [],
        "certifications": [],
        "publications": [],
        "languages": [],
    }
    resp = client.post(
        url,
        {
            "headline": "",
            "summary": "",
            "cv_sections_json": json.dumps(empty),
        },
    )
    assert resp.status_code == 302
    assert not CVSection.objects.filter(cv=cv).exists()


@pytest.mark.django_db
def test_cv_builder_invalid_json_shows_error(client, django_user_model):
    user = django_user_model.objects.create_user(email="cvuser3@example.com", password="secret123")
    client.force_login(user)
    url = reverse("rep_career:cv_builder")
    resp = client.post(
        url,
        {
            "headline": "H",
            "summary": "S",
            "cv_sections_json": "not-json{",
        },
    )
    assert resp.status_code == 200
    cv = CVProfile.objects.get(user=user)
    assert cv.headline != "H"  # profile not saved on sections parse failure


@pytest.mark.django_db
def test_cv_builder_invalid_section_shape(client, django_user_model):
    user = django_user_model.objects.create_user(email="cvuser4@example.com", password="secret123")
    client.force_login(user)
    url = reverse("rep_career:cv_builder")
    bad = {
        "education": "not-a-list",
        "experience": [],
        "skills": [],
        "certifications": [],
        "publications": [],
        "languages": [],
    }
    resp = client.post(
        url,
        {
            "headline": "H",
            "summary": "S",
            "cv_sections_json": json.dumps(bad),
        },
    )
    assert resp.status_code == 200
    cv = CVProfile.objects.get(user=user)
    assert cv.headline != "H"


# NOTE: a post_save signal (apps/core/signals.ensure_user_profile) auto-creates
# an empty UserProfile for every CustomUser. Tests fill that row, then re-fetch
# the user so the reverse `.profile` relation loads fresh from the DB — exactly
# what happens on a real HTTP request (the create-time cached instance is stale).


@pytest.mark.django_db
def test_prefill_populates_from_profile_on_first_creation(client, django_user_model):
    """FRREP-TS005 — a learner with a populated profile gets a pre-filled CV."""
    from apps.core.authentication.models import UserProfile
    from apps.alumni.careers.services import get_or_create_cv

    user = django_user_model.objects.create_user(
        email="prefill@example.com", password="secret123", first_name="Ada", last_name="Bio"
    )
    UserProfile.objects.update_or_create(
        user=user,
        defaults={
            "bio": "<p>Plant breeder focused on drought-tolerant maize.</p>",
            "country": "Uganda",
            "degree_level": "phd",
            "professional_background": "Senior Research Scientist, CGIAR\nSecond line ignored",
            "areas_of_interest": "Plant breeding, Genomics, Plant breeding, Data science",
            "qualifications": [
                {"institution": "Makerere University", "qualification": "PhD Plant Breeding", "year": "2018"},
                "BSc Agriculture",
            ],
        },
    )
    user = django_user_model.objects.get(pk=user.pk)  # fresh reverse relation

    cv = get_or_create_cv(user)

    assert cv.headline == "Senior Research Scientist, CGIAR"
    assert "drought-tolerant maize" in cv.summary
    assert "<p>" not in cv.summary  # HTML stripped
    skills = CVSection.objects.get(cv=cv, section_type="skills").data
    assert skills == ["Plant breeding", "Genomics", "Data science"]  # deduped, order kept
    edu = CVSection.objects.get(cv=cv, section_type="education").data
    assert edu[0]["degree"] == "PhD Plant Breeding"
    assert edu[0]["institution"] == "Makerere University"
    assert edu[1]["degree"] == "BSc Agriculture"


@pytest.mark.django_db
def test_prefill_headline_falls_back_to_degree_and_country(client, django_user_model):
    from apps.core.authentication.models import UserProfile
    from apps.alumni.careers.services import get_or_create_cv

    user = django_user_model.objects.create_user(email="prefill2@example.com", password="secret123")
    UserProfile.objects.update_or_create(
        user=user,
        defaults={"degree_level": "masters", "country": "Kenya"},
    )
    user = django_user_model.objects.get(pk=user.pk)
    cv = get_or_create_cv(user)
    assert "Master" in cv.headline
    assert "Kenya" in cv.headline


@pytest.mark.django_db
def test_prefill_does_not_overwrite_existing_cv(client, django_user_model):
    """An existing CVProfile is never re-seeded from the profile."""
    from apps.core.authentication.models import UserProfile
    from apps.alumni.careers.services import get_or_create_cv

    user = django_user_model.objects.create_user(email="prefill3@example.com", password="secret123")
    UserProfile.objects.update_or_create(
        user=user,
        defaults={"professional_background": "Should not appear", "areas_of_interest": "X, Y"},
    )
    existing = CVProfile.objects.create(user=user, headline="Kept headline")
    user = django_user_model.objects.get(pk=user.pk)

    cv = get_or_create_cv(user)

    assert cv.pk == existing.pk
    assert cv.headline == "Kept headline"
    assert not CVSection.objects.filter(cv=cv, section_type="skills").exists()


@pytest.mark.django_db
def test_prefill_no_profile_does_not_crash(client, django_user_model):
    """A learner with no profile row (legacy user) gets a bare CV without error."""
    from apps.core.authentication.models import UserProfile
    from apps.alumni.careers.services import get_or_create_cv

    user = django_user_model.objects.create_user(email="prefill4@example.com", password="secret123")
    # Simulate a legacy account that never got a profile row.
    UserProfile.objects.filter(user=user).delete()
    user = django_user_model.objects.get(pk=user.pk)
    assert not hasattr(user, "profile")

    cv = get_or_create_cv(user)
    assert cv.pk is not None
    assert cv.headline == ""
    assert not cv.sections.exists()


@pytest.mark.django_db
def test_prefill_empty_profile_fields_seed_nothing(client, django_user_model):
    from apps.core.authentication.models import UserProfile
    from apps.alumni.careers.services import get_or_create_cv

    user = django_user_model.objects.create_user(email="prefill5@example.com", password="secret123")
    UserProfile.objects.update_or_create(
        user=user,
        defaults={"bio": "", "professional_background": "", "areas_of_interest": "", "qualifications": []},
    )
    user = django_user_model.objects.get(pk=user.pk)
    cv = get_or_create_cv(user)
    assert cv.headline == ""
    assert cv.summary == ""
    assert not cv.sections.exists()
