"""Normalize job titles to functional departments."""

from typing import Dict, Any
import re
import os
from functools import lru_cache
from ..llm_provider import get_llm_provider


# Memoize the LLM provider to avoid repeated initialization
@lru_cache(maxsize=1)
def get_cached_llm_provider():
    """Get a cached instance of the LLM provider."""
    return get_llm_provider()


# Job function mappings based on keywords
JOB_FUNCTION_KEYWORDS = {
    "Sales": [
        "sales",
        "revenue",
        "account executive",
        "ae",
        "bdr",
        "sdr",
        "business development",
        "account manager",
        "sales engineer",
        "sales ops",
        "sales operations",
        "revenue operations",
        "revops",
    ],
    "Marketing": [
        "marketing",
        "demand gen",
        "demand generation",
        "growth",
        "brand",
        "content",
        "seo",
        "sem",
        "paid media",
        "social media",
        "product marketing",
        "pmm",
        "martech",
        "marketing ops",
        "campaign",
        "digital marketing",
        "performance marketing",
    ],
    "Engineering": [
        "engineer",
        "engineering",
        "developer",
        "programmer",
        "software",
        "architect",
        "devops",
        "sre",
        "qa",
        "quality assurance",
        "test",
        "backend",
        "frontend",
        "fullstack",
        "full stack",
        "mobile",
        "data engineer",
        "machine learning engineer",
        "ml engineer",
    ],
    "Product": [
        "product manager",
        "pm",
        "product owner",
        "po",
        "product design",
        "ux",
        "ui",
        "user experience",
        "user interface",
        "design",
        "product ops",
        "product operations",
    ],
    "Customer Success": [
        "customer success",
        "cs",
        "csm",
        "customer support",
        "support",
        "customer service",
        "account management",
        "customer experience",
        "cx",
        "technical support",
        "implementation",
        "onboarding",
    ],
    "Finance": [
        "finance",
        "accounting",
        "cfo",
        "controller",
        "treasurer",
        "financial",
        "fp&a",
        "audit",
        "tax",
        "payroll",
        "accounts payable",
        "accounts receivable",
        "bookkeeper",
        "financial analyst",
    ],
    "Human Resources": [
        "hr",
        "human resources",
        "people",
        "talent",
        "recruiting",
        "recruiter",
        "people ops",
        "people operations",
        "compensation",
        "benefits",
        "learning",
        "training",
        "organizational development",
    ],
    "Operations": [
        "operations",
        "ops",
        "coo",
        "business operations",
        "bizops",
        "strategy",
        "strategic",
        "process",
        "project manager",
        "program manager",
        "supply chain",
        "logistics",
        "procurement",
    ],
    "Legal": [
        "legal",
        "lawyer",
        "attorney",
        "counsel",
        "compliance",
        "contract",
        "paralegal",
        "regulatory",
        "risk",
        "governance",
    ],
    "Data & Analytics": [
        "data",
        "analytics",
        "analyst",
        "data scientist",
        "data analyst",
        "business analyst",
        "bi",
        "business intelligence",
        "insights",
        "research",
        "data ops",
        "dataops",
    ],
    "Information Technology": [
        "it",
        "information technology",
        "systems",
        "network",
        "security",
        "infosec",
        "information security",
        "database",
        "dba",
        "infrastructure",
        "cloud",
        "help desk",
        "it support",
        "system admin",
        "sysadmin",
    ],
    "Executive": [
        "ceo",
        "cto",
        "cfo",
        "coo",
        "cmo",
        "cpo",
        "ciso",
        "cro",
        "chief",
        "president",
        "founder",
        "co-founder",
        "owner",
        "managing director",
        "general manager",
        "gm",
    ],
}

# Build reverse lookup
FUNCTION_LOOKUP = {}
for function, keywords in JOB_FUNCTION_KEYWORDS.items():
    for keyword in keywords:
        FUNCTION_LOOKUP[keyword.lower()] = function


def normalize_job_function(value: str, *, force_llm: bool = False) -> Dict[str, Any]:
    """
    Normalize job title to primary functional department.

    Examples:
        "VP of Sales" -> "Sales"
        "Head of Revenue" -> "Sales"
        "Chief Technology Officer" -> "Engineering"
        "Marketing Operations Manager" -> "Marketing"
    """
    # Handle None/empty
    if value is None or str(value).strip() == "":
        return {"value": None, "confidence": 0.0}

    s = str(value).strip()

    # Clean and lowercase
    cleaned = re.sub(r"[^\w\s&]", " ", s.lower())
    cleaned = re.sub(r"\s+", " ", cleaned).strip()

    # Track all matching functions with scores
    function_scores = {}

    # Check each word/phrase against our keywords
    words = cleaned.split()

    # Check for executive first (often overrides department)
    for exec_keyword in JOB_FUNCTION_KEYWORDS["Executive"]:
        if exec_keyword.lower() in cleaned:
            # For executives, also try to identify their functional area
            primary_function = "Executive"
            secondary_function = None

            # Look for secondary function (e.g., "Chief Marketing Officer" -> Executive + Marketing)
            for function, keywords in JOB_FUNCTION_KEYWORDS.items():
                if function != "Executive":
                    for keyword in keywords:
                        if keyword.lower() in cleaned:
                            secondary_function = function
                            break
                    if secondary_function:
                        break

            return {
                "value": secondary_function or primary_function,
                "primary": primary_function,
                "secondary": secondary_function,
                "confidence": 0.95,
                "is_executive": True,
            }

    # Check for exact phrase matches first
    for keyword, function in FUNCTION_LOOKUP.items():
        if keyword in cleaned:
            # Longer matches are more specific and should score higher
            score = len(keyword.split())
            if function not in function_scores:
                function_scores[function] = 0
            function_scores[function] += score

    # If we have matches, return the highest scoring function
    if function_scores:
        # Sort by score (descending) and take the best match
        best_function = max(function_scores.items(), key=lambda x: x[1])
        confidence = min(
            0.9, 0.5 + (best_function[1] * 0.1)
        )  # Scale confidence by score

        result = {
            "value": best_function[0],
            "confidence": round(confidence, 2),
            "is_executive": False,
        }

        # Check if it's a manager/director level
        if any(
            level in cleaned
            for level in ["manager", "director", "head", "lead", "vp", "vice president"]
        ):
            result["is_manager"] = True

        return result

    # Fallback - check for department indicators
    department_hints = {
        "tech": "Engineering",
        "technical": "Engineering",
        "dev": "Engineering",
        "creative": "Marketing",
        "financial": "Finance",
        "people": "Human Resources",
        "talent": "Human Resources",
        "business": "Operations",
        "strategy": "Operations",
        "research": "Data & Analytics",
    }

    for hint, function in department_hints.items():
        if hint in cleaned:
            return {"value": function, "confidence": 0.6, "is_executive": False}

    # Try AI fallback if enabled and no good match
    fallback_enabled = (
        os.getenv("TRANSFORM_ENABLE_LLM_FALLBACK", "true").lower() == "true"
    )
    use_llm = force_llm or (not function_scores)  # Use LLM if no matches found

    if use_llm and fallback_enabled:
        provider = get_cached_llm_provider()  # Use memoized provider
        if provider:
            valid_functions = list(JOB_FUNCTION_KEYWORDS.keys())
            schema = {
                "type": "object",
                "properties": {
                    "function": {"type": "string"},
                    "is_executive": {"type": "boolean"},
                    "is_manager": {"type": "boolean"},
                    "confidence": {"type": "number"},
                },
                "required": ["function"],
            }
            prompt = (
                f"Categorize this job title into a functional department.\n"
                f"Valid departments: {', '.join(valid_functions)}\n"
                f"Identify if it's an executive (C-level) or manager role.\n"
                f"Return JSON: {{\"function\":\"<department>\", \"is_executive\":bool, \"is_manager\":bool, \"confidence\":0.0-1.0}}\n"
                f"Job title: \"{value}\""
            )
            try:
                out = provider.generate_json(prompt, schema=schema, num_predict=128)
                result = out.get("value", {}) or {}
                if result.get("function"):
                    return {
                        "value": result["function"],
                        "confidence": result.get("confidence", 0.7),
                        "is_executive": result.get("is_executive", False),
                        "is_manager": result.get("is_manager", False),
                        "method": "ai",
                        "original": s,
                    }
            except Exception:
                pass

    # Default to "Other" if no match
    return {"value": "Other", "confidence": 0, "is_executive": False, "original": s}
