"""
LLM-powered suggestion helpers for Settings UI.
Two functions, each makes one LLMRouter call:
  - suggest_search_terms: enhanced title + three-angle exclude suggestions
  - suggest_resume_keywords: skills/domains/keywords gap analysis
"""
import json
import re
from pathlib import Path
from typing import Any

from scripts.llm_router import LLMRouter


def _load_resume_context(resume_path: Path) -> str:
    """Extract 3 most recent positions from plain_text_resume.yaml as a short summary."""
    import yaml
    if not resume_path.exists():
        return ""
    resume = yaml.safe_load(resume_path.read_text()) or {}
    lines = []
    for exp in (resume.get("experience_details") or [])[:3]:
        pos = exp.get("position", "")
        co = exp.get("company", "")
        skills = ", ".join((exp.get("skills_acquired") or [])[:5])
        lines.append(f"- {pos} at {co}: {skills}")
    return "\n".join(lines)


def _parse_json(text: str) -> dict[str, Any]:
    """Extract the first JSON object from LLM output. Returns {} on failure."""
    m = re.search(r"\{.*\}", text, re.DOTALL)
    if m:
        try:
            return json.loads(m.group())
        except Exception:
            pass
    return {}


def suggest_search_terms(
    current_titles: list[str],
    resume_path: Path,
    blocklist: dict[str, Any],
    user_profile: dict[str, Any],
) -> dict:
    """
    Suggest additional job titles and exclude keywords.

    Three-angle exclude analysis:
      A: Blocklist alias expansion (blocked companies/industries → keyword variants)
      B: Values misalignment (mission preferences → industries/culture to avoid)
      C: Role-type filter (career summary → role types that don't fit)

    Returns: {"suggested_titles": [...], "suggested_excludes": [...]}
    """
    resume_context = _load_resume_context(resume_path)
    titles_str = "\n".join(f"- {t}" for t in current_titles) or "(none yet)"

    bl_companies = ", ".join(blocklist.get("companies", [])) or "none"
    bl_industries = ", ".join(blocklist.get("industries", [])) or "none"
    nda = ", ".join(user_profile.get("nda_companies", [])) or "none"
    career_summary = user_profile.get("career_summary", "") or "Not provided"
    mission_raw = user_profile.get("mission_preferences", {}) or {}
    # Three exclude angles are intentionally collapsed into one flat suggested_excludes list
    mission_str = "\n".join(
        f"  - {k}: {v}" for k, v in mission_raw.items() if v and isinstance(v, str) and v.strip()
    ) or "  (none specified)"

    prompt = f"""You are helping a job seeker optimise their search configuration.

--- RESUME BACKGROUND ---
{resume_context or "Not provided"}

--- CAREER SUMMARY ---
{career_summary}

--- CURRENT TITLES BEING SEARCHED ---
{titles_str}

--- BLOCKED ENTITIES ---
Companies blocked: {bl_companies}
Industries blocked: {bl_industries}
NDA / confidential employers: {nda}

--- MISSION & VALUES ---
{mission_str}

Provide all four of the following:

1. TITLE SUGGESTIONS
   5-8 additional job titles they may be missing: alternative names, adjacent roles, or senior variants of their current titles.

2. EXCLUDE KEYWORDS — BLOCKLIST ALIASES
   The user has blocked the companies/industries above. Suggest keyword variants that would also catch their aliases, subsidiaries, or related brands.
   Example: blocking "Meta" → also exclude "facebook", "instagram", "metaverse", "oculus".

3. EXCLUDE KEYWORDS — VALUES MISALIGNMENT
   Based on the user's mission and values above, suggest industry or culture keywords to exclude.
   Examples: "tobacco", "gambling", "fossil fuel", "defense contractor", "MLM", "commission-only", "pyramid".

4. EXCLUDE KEYWORDS — ROLE TYPE FILTER
   Based on the user's career background, suggest role-type terms that don't match their trajectory.
   Examples for a CS/TAM leader: "cold calling", "door to door", "quota-driven", "SDR", "sales development rep".

Return ONLY valid JSON in exactly this format (no extra text):
{{"suggested_titles": ["Title 1", "Title 2"],
  "suggested_excludes": ["keyword 1", "keyword 2", "keyword 3"]}}"""

    raw = LLMRouter().complete(prompt).strip()
    parsed = _parse_json(raw)
    return {
        "suggested_titles": parsed.get("suggested_titles", []),
        "suggested_excludes": parsed.get("suggested_excludes", []),
    }


def suggest_resume_keywords(
    resume_path: Path,
    current_kw: dict[str, list[str]],
) -> dict:
    """
    Suggest skills, domains, and keywords not already in the user's resume_keywords.yaml.

    Returns: {"skills": [...], "domains": [...], "keywords": [...]}
    """
    resume_context = _load_resume_context(resume_path)

    already_skills   = ", ".join(current_kw.get("skills", []))   or "none"
    already_domains  = ", ".join(current_kw.get("domains", []))  or "none"
    already_keywords = ", ".join(current_kw.get("keywords", [])) or "none"

    prompt = f"""You are helping a job seeker build a keyword profile used to score job description matches.

--- RESUME BACKGROUND ---
{resume_context or "Not provided"}

--- ALREADY SELECTED (do not repeat these) ---
Skills:   {already_skills}
Domains:  {already_domains}
Keywords: {already_keywords}

Suggest additional tags in each of the three categories below. Only suggest tags NOT already in the lists above.

SKILLS — specific technical or soft skills (e.g. "Salesforce", "Executive Communication", "SQL", "Stakeholder Management")
DOMAINS — industry verticals, company types, or functional areas (e.g. "B2B SaaS", "EdTech", "Non-profit", "Series A-C")
KEYWORDS — specific terms, methodologies, metrics, or JD phrases (e.g. "NPS", "churn prevention", "QBR", "cross-functional")

Return ONLY valid JSON in exactly this format (no extra text):
{{"skills": ["Skill A", "Skill B"],
  "domains": ["Domain A"],
  "keywords": ["Keyword A", "Keyword B"]}}"""

    raw = LLMRouter().complete(prompt).strip()
    parsed = _parse_json(raw)
    return {
        "skills":   parsed.get("skills", []),
        "domains":  parsed.get("domains", []),
        "keywords": parsed.get("keywords", []),
    }
