"""Detect likely technographics from domain or description."""

from __future__ import annotations

from functools import lru_cache
from typing import Any, Dict, Optional, Sequence

ALLOWED_CRM = {"Salesforce", "HubSpot", "Dynamics", "Zoho", "Unknown"}
ALLOWED_MARKETING = {"HubSpot", "Marketo", "Pardot", "Mailchimp", "Unknown"}
ALLOWED_HOSTING = {"AWS", "Azure", "GCP", "On-Prem", "Unknown"}


def _normalize(text: Optional[str]) -> str:
    return str(text or "").strip().lower()


def _first_non_empty_from_row(
    row: Sequence[Any], headers: Sequence[Any], keys: Sequence[str]
) -> str:
    header_map = {
        _normalize(str(headers[idx] or "")): idx for idx in range(len(headers))
    }
    for key in keys:
        idx = header_map.get(_normalize(key))
        if idx is None or idx >= len(row):
            continue
        value = row[idx]
        if value:
            cleaned = _normalize(str(value))
            if cleaned:
                return cleaned
    return ""


def _extract_row_fields(payload: Dict[str, Any]) -> Dict[str, str]:
    domain = ""
    description = ""

    row = payload.get("row")
    headers = payload.get("headers") or []

    if isinstance(row, dict):
        lowered = {str(k).strip().lower(): v for k, v in row.items()}
        domain = _normalize(
            lowered.get("domain")
            or lowered.get("website")
            or lowered.get("url")
            or lowered.get("company_domain")
        )
        description = _normalize(
            lowered.get("description")
            or lowered.get("company")
            or lowered.get("summary")
            or lowered.get("notes")
        )
    elif isinstance(row, (list, tuple)) and headers:
        domain = _first_non_empty_from_row(
            row, headers, ("domain", "website", "url", "company_domain")
        )
        description = _first_non_empty_from_row(
            row, headers, ("description", "company", "summary", "notes")
        )

    return {"domain": domain, "description": description}


def _detect_crm(text: str) -> str:
    if "salesforce" in text or "force.com" in text:
        return "Salesforce"
    if "dynamics" in text:
        return "Dynamics"
    if "zoho" in text:
        return "Zoho"
    if "hubspot" in text:
        return "HubSpot"
    return "Unknown"


def _detect_marketing(text: str) -> str:
    if "hubspot" in text:
        return "HubSpot"
    if "marketo" in text:
        return "Marketo"
    if "pardot" in text:
        return "Pardot"
    if "mailchimp" in text or "mandrill" in text:
        return "Mailchimp"
    return "Unknown"


def _detect_hosting(text: str) -> str:
    if "amazonaws" in text or "cloudfront" in text or "aws" in text:
        return "AWS"
    if "azure" in text:
        return "Azure"
    if "gcp" in text or "google cloud" in text:
        return "GCP"
    if "on-prem" in text or "datacenter" in text:
        return "On-Prem"
    return "Unknown"


@lru_cache(maxsize=512)
def _detect_technographics(domain: str, description: str) -> Dict[str, Any]:
    combined = f"{domain} {description}".lower()
    crm = _detect_crm(combined)
    marketing = _detect_marketing(combined)
    hosting = _detect_hosting(combined)

    explains = {}
    if crm != "Unknown":
        explains["crm"] = crm
    if marketing != "Unknown":
        explains["marketing"] = marketing
    if hosting != "Unknown":
        explains["hosting"] = hosting

    return {
        "crm": crm if crm in ALLOWED_CRM else "Unknown",
        "marketing": marketing if marketing in ALLOWED_MARKETING else "Unknown",
        "hosting": hosting if hosting in ALLOWED_HOSTING else "Unknown",
        "explain": explains,
    }


def detect_technographics(payload: Dict[str, Any]) -> Dict[str, Any]:
    domain = ""
    description = ""

    if isinstance(payload, dict) and "row" in payload:
        extracted = _extract_row_fields(payload)
        domain = extracted["domain"]
        description = extracted["description"]
    else:
        domain = _normalize(
            (payload or {}).get("domain")
            or (payload or {}).get("website")
            or (payload or {}).get("url")
        )
        description = _normalize(
            (payload or {}).get("description")
            or (payload or {}).get("company")
            or (payload or {}).get("summary")
        )

    result = _detect_technographics(domain, description)
    values = [result["crm"], result["marketing"], result["hosting"]]

    return {
        "value": values,
        "meta": {
            "domain": domain,
            "description_present": bool(description),
            "explain": result["explain"],
        },
    }
