"""Tests for scripts/suggest_helpers.py."""
import json
import pytest
from pathlib import Path
from unittest.mock import patch, MagicMock

RESUME_PATH = Path(__file__).parent.parent / "config" / "plain_text_resume.yaml"


# ── _parse_json ───────────────────────────────────────────────────────────────

def test_parse_json_extracts_valid_object():
    from scripts.suggest_helpers import _parse_json
    raw = 'Here is the result: {"a": [1, 2], "b": "hello"} done.'
    assert _parse_json(raw) == {"a": [1, 2], "b": "hello"}


def test_parse_json_returns_empty_on_invalid():
    from scripts.suggest_helpers import _parse_json
    assert _parse_json("no json here") == {}
    assert _parse_json('{"broken": ') == {}


# ── suggest_search_terms ──────────────────────────────────────────────────────

BLOCKLIST = {
    "companies": ["Meta", "Amazon"],
    "industries": ["gambling"],
    "locations": [],
}
USER_PROFILE = {
    "career_summary": "Customer success leader with 10 years in B2B SaaS.",
    "mission_preferences": {
        "animal_welfare": "I volunteer at my local shelter.",
        "education": "",
    },
    "nda_companies": ["Acme Corp"],
}


def _mock_llm(response_dict: dict):
    """Return a patcher that makes LLMRouter().complete() return a JSON string."""
    mock_router = MagicMock()
    mock_router.complete.return_value = json.dumps(response_dict)
    return patch("scripts.suggest_helpers.LLMRouter", return_value=mock_router)


def test_suggest_search_terms_returns_titles_and_excludes():
    from scripts.suggest_helpers import suggest_search_terms
    payload = {"suggested_titles": ["VP Customer Success"], "suggested_excludes": ["cold calling"]}
    with _mock_llm(payload):
        result = suggest_search_terms(["Customer Success Manager"], RESUME_PATH, BLOCKLIST, USER_PROFILE)
    assert result["suggested_titles"] == ["VP Customer Success"]
    assert result["suggested_excludes"] == ["cold calling"]


def test_suggest_search_terms_prompt_contains_blocklist_companies():
    from scripts.suggest_helpers import suggest_search_terms
    with _mock_llm({"suggested_titles": [], "suggested_excludes": []}) as mock_cls:
        suggest_search_terms(["CSM"], RESUME_PATH, BLOCKLIST, USER_PROFILE)
    prompt_sent = mock_cls.return_value.complete.call_args[0][0]
    assert "Meta" in prompt_sent
    assert "Amazon" in prompt_sent


def test_suggest_search_terms_prompt_contains_mission():
    from scripts.suggest_helpers import suggest_search_terms
    with _mock_llm({"suggested_titles": [], "suggested_excludes": []}) as mock_cls:
        suggest_search_terms(["CSM"], RESUME_PATH, BLOCKLIST, USER_PROFILE)
    prompt_sent = mock_cls.return_value.complete.call_args[0][0]
    assert "animal_welfare" in prompt_sent or "animal welfare" in prompt_sent.lower()


def test_suggest_search_terms_prompt_contains_career_summary():
    from scripts.suggest_helpers import suggest_search_terms
    with _mock_llm({"suggested_titles": [], "suggested_excludes": []}) as mock_cls:
        suggest_search_terms(["CSM"], RESUME_PATH, BLOCKLIST, USER_PROFILE)
    prompt_sent = mock_cls.return_value.complete.call_args[0][0]
    assert "Customer success leader" in prompt_sent


def test_suggest_search_terms_returns_empty_on_bad_json():
    from scripts.suggest_helpers import suggest_search_terms
    mock_router = MagicMock()
    mock_router.complete.return_value = "sorry, I cannot help with that"
    with patch("scripts.suggest_helpers.LLMRouter", return_value=mock_router):
        result = suggest_search_terms(["CSM"], RESUME_PATH, BLOCKLIST, USER_PROFILE)
    assert result == {"suggested_titles": [], "suggested_excludes": []}


def test_suggest_search_terms_raises_on_llm_exhausted():
    from scripts.suggest_helpers import suggest_search_terms
    mock_router = MagicMock()
    mock_router.complete.side_effect = RuntimeError("All LLM backends exhausted")
    with patch("scripts.suggest_helpers.LLMRouter", return_value=mock_router):
        with pytest.raises(RuntimeError, match="All LLM backends exhausted"):
            suggest_search_terms(["CSM"], RESUME_PATH, BLOCKLIST, USER_PROFILE)


# ── suggest_resume_keywords ───────────────────────────────────────────────────

CURRENT_KW = {
    "skills": ["Customer Success", "SQL"],
    "domains": ["B2B SaaS"],
    "keywords": ["NPS"],
}


def test_suggest_resume_keywords_returns_all_three_categories():
    from scripts.suggest_helpers import suggest_resume_keywords
    payload = {
        "skills": ["Project Management"],
        "domains": ["EdTech"],
        "keywords": ["churn prevention"],
    }
    with _mock_llm(payload):
        result = suggest_resume_keywords(RESUME_PATH, CURRENT_KW)
    assert "skills" in result
    assert "domains" in result
    assert "keywords" in result


def test_suggest_resume_keywords_excludes_already_selected():
    from scripts.suggest_helpers import suggest_resume_keywords
    with _mock_llm({"skills": [], "domains": [], "keywords": []}) as mock_cls:
        suggest_resume_keywords(RESUME_PATH, CURRENT_KW)
    prompt_sent = mock_cls.return_value.complete.call_args[0][0]
    # Already-selected tags should appear in the prompt so LLM knows to skip them
    assert "Customer Success" in prompt_sent
    assert "NPS" in prompt_sent


def test_suggest_resume_keywords_returns_empty_on_bad_json():
    from scripts.suggest_helpers import suggest_resume_keywords
    mock_router = MagicMock()
    mock_router.complete.return_value = "I cannot assist."
    with patch("scripts.suggest_helpers.LLMRouter", return_value=mock_router):
        result = suggest_resume_keywords(RESUME_PATH, CURRENT_KW)
    assert result == {"skills": [], "domains": [], "keywords": []}


def test_suggest_resume_keywords_raises_on_llm_exhausted():
    from scripts.suggest_helpers import suggest_resume_keywords
    mock_router = MagicMock()
    mock_router.complete.side_effect = RuntimeError("All LLM backends exhausted")
    with patch("scripts.suggest_helpers.LLMRouter", return_value=mock_router):
        with pytest.raises(RuntimeError, match="All LLM backends exhausted"):
            suggest_resume_keywords(RESUME_PATH, CURRENT_KW)
