"""Description brief builder and NAICS vertical lookup for Zoho push enrichment.

build_description_brief(lead) -> structured plain-text brief for Zoho Description field.
get_vertical_segment(naics) -> (Business_Vertical, Vertical_Segment) from NAICS prefix.
"""

import re
from pathlib import Path
from typing import Tuple

import yaml


_NAICS_VERTICALS_PATH = Path(__file__).resolve().parent.parent / "config" / "naics-verticals.yaml"
_naics_verticals = None

AGENT_TYPE_LABELS = {
    "individual": "Individual (founder-registered)",
    "business": "Formation service",
    "secretary_of_state": "SoS default",
}

_TIER_MAP = {
    "tier_1": "1",
    "tier_2": "2",
    "tier_3": "3",
    "tier_4": "4",
    "tier_0": "0",
    "pllc_fast_track": "1",
    "default": "-",
}


def _load_verticals():
    """Load NAICS vertical mapping from config file (lazy, cached)."""
    global _naics_verticals
    if _naics_verticals is not None:
        return _naics_verticals
    if _NAICS_VERTICALS_PATH.exists():
        with open(_NAICS_VERTICALS_PATH) as f:
            _naics_verticals = yaml.safe_load(f)
    else:
        _naics_verticals = {"mapping": {}}
    return _naics_verticals


def _parse_naics(naics_raw: str) -> tuple:
    """Parse NAICS field into (code, label).

    Handles both formats:
    - "Label (CODE)" -> ("CODE", "Label")
    - "541720"       -> ("541720", "")
    """
    if not naics_raw:
        return ("", "")

    naics_raw = naics_raw.strip()

    # Format 1: "Label (CODE)"
    m = re.search(r"\((\d+)\)\s*$", naics_raw)
    if m:
        code = m.group(1)
        label = naics_raw[: m.start()].strip()
        return (code, label)

    # Format 2: bare digits
    cleaned = re.sub(r"[^0-9]", "", naics_raw)
    if cleaned and cleaned.isdigit():
        return (cleaned, "")

    return ("", "")


def _get_phone_and_source(lead: dict) -> tuple:
    """Return (phone, source_label) using merge order matching integrations/zoho.py.

    Phone: lead.phone or lead.domain_phone or lead.brave_phone
    Source: "Brave Search" if brave_phone, "Website" if domain_phone, "Filing" if phone.
    """
    phone = lead.get("phone") or lead.get("domain_phone") or lead.get("brave_phone", "")

    source = ""
    if phone:
        if lead.get("brave_phone"):
            source = "Brave Search"
        elif lead.get("domain_phone"):
            source = "Website"
        elif lead.get("phone"):
            source = "Filing"

    return (phone or "", source)


def _get_competitor_status(lead: dict) -> str:
    """Format competitor displacement status for the brief."""
    displacement = lead.get("competitor_displacement")
    if displacement is True:
        brands = lead.get("competitor_brands", [])
        if brands:
            return f"Detected -- {', '.join(brands)}"
        return "Detected"
    if displacement is False:
        return "None detected"
    return "Not checked"


def _get_filing_signals(lead: dict) -> str:
    """Compile filing history signals as comma-separated string."""
    signals = []
    if lead.get("has_recent_amendment"):
        signals.append("Recent amendment")
    if lead.get("uses_paper_filing"):
        signals.append("Paper filer")
    if lead.get("annual_report_current"):
        signals.append("Annual report current")
    return ", ".join(signals) if signals else "None"


def _get_agent_label(lead: dict) -> str:
    """Map agent_type to display label. Returns "" for omission.

    For business-type agents, appends the agent name (formation service name).
    """
    agent_type = lead.get("agent_type", "")
    if not agent_type:
        return ""

    label = AGENT_TYPE_LABELS.get(agent_type, "")
    if not label:
        return ""

    # Append formation service name for business agents
    if agent_type == "business":
        agent_name = lead.get("agent_name", "")
        if agent_name:
            label = f"{label} -- {agent_name}"

    return label


def _format_filing_date(date_str: str) -> str:
    """Format filing date as M/DD/YYYY. Returns "--" on failure."""
    if not date_str:
        return "--"
    try:
        # ISO: "2026-05-18T00:00:00.000" or "2026-05-18"
        dt = date_str.replace("Z", "").split(".")[0]
        from datetime import datetime
        parsed = datetime.fromisoformat(dt)
        return f"{parsed.month}/{parsed.day:02d}/{parsed.year}"
    except Exception:
        return date_str[:10] if len(date_str) >= 10 else "--"


def build_description_brief(lead: dict) -> str:
    """Build a structured plain-text brief from enriched lead data.

    Renders a multi-line string suitable for the Zoho Lead Description field.
    Always produces output even with sparse data -- partial is better than none.
    """
    lines = []

    # --- Header line ---
    entity_type = lead.get("entity_type") or "Unknown"
    tier_raw = lead.get("tier", "")
    tier = _TIER_MAP.get(tier_raw, tier_raw) if tier_raw else "--"
    score = lead.get("score", "--")
    temporal = lead.get("temporal_category") or "unknown"
    lines.append(f"[{entity_type} | Tier {tier} | Score: {score} | {temporal}]")

    # --- Filed line ---
    filing_date = _format_filing_date(lead.get("filing_date", ""))
    county_raw = lead.get("county") or "Unknown"
    county = county_raw if county_raw.endswith(" County") else f"{county_raw} County"
    lines.append(f"Filed: {filing_date} | {county}")

    # --- NAICS line ---
    naics_raw = lead.get("naics", "")
    code, label = _parse_naics(naics_raw)
    if code and label:
        lines.append(f"NAICS: {code} -- {label}")
    elif code:
        lines.append(f"NAICS: {code}")
    else:
        lines.append("NAICS: --")

    # --- Principal line (omit if empty) ---
    # Use full principal name if available, fall back to primary_principal_name
    principal_names = lead.get("principal_names", [])
    if principal_names:
        # Title case the full name
        principal = principal_names[0].title() if principal_names[0] else ""
    else:
        principal = lead.get("primary_principal_name", "")
    if principal:
        lines.append(f"Principal: {principal}")

    # --- Agent line (omit if no agent_type) ---
    agent_label = _get_agent_label(lead)
    if agent_label:
        lines.append(f"Agent: {agent_label}")

    # --- Domain / Phone line ---
    domain = lead.get("domain") or "None found"
    phone, source = _get_phone_and_source(lead)
    if phone:
        lines.append(f"Domain: {domain} | Phone: {phone} ({source})")
    else:
        lines.append(f"Domain: {domain} | Phone: None found")

    # --- Competitor line ---
    competitor = _get_competitor_status(lead)
    lines.append(f"Competitor: {competitor}")

    # --- Filing signals line ---
    signals = _get_filing_signals(lead)
    lines.append(f"Filing signals: {signals}")

    # --- Window line ---
    window = lead.get("outreach_window") or "--"
    lines.append(f"Window: {window}")

    return "\n".join(lines)


def get_vertical_segment(naics_raw: str) -> tuple:
    """Derive Business_Vertical and Vertical_Segment from NAICS code.

    Matches longest prefix first against config/naics-verticals.yaml.

    Args:
        naics_raw: Raw NAICS string (label+code or bare code)

    Returns:
        Tuple of (vertical, segment) strings.
    """
    if not naics_raw:
        return ("Unknown", "Unknown")

    code, _ = _parse_naics(naics_raw)
    if not code:
        return ("Unknown", "Unknown")

    cfg = _load_verticals()
    mapping = cfg.get("mapping", {})

    # Match longest prefix first (4-digit before 3-digit before 2-digit)
    for prefix_len in (4, 3, 2):
        prefix = code[:prefix_len]
        if prefix in mapping:
            return tuple(mapping[prefix])

    # Catch-all
    return ("Other", code)