"""Resolver de Canal de Origen + tag canonico para un contacto.

Combina señales (source nativo de GHL, tags existentes, Canal de Origen previo,
Fuente de Prospecto) para producir UNA decisión consistente:

- `decided_tag`: tag canonico que debe quedar (facebook-ads | sucursal | formulario).
- `canal_value`: valor para custom field "Canal de Origen" (FACEBOOK | SUCURSAL | FORMULARIO).
- `tags_to_add` / `tags_to_remove`: ajustes necesarios sobre las etiquetas actuales.
- `confident` / `review`: si la decisión es segura o requiere revisión humana.
- `reason`: explicación textual para auditoría.

Reglas de prioridad (de mayor a menor):
1. `source` nativo de GHL si es interpretable.
2. Único tag target ya presente, salvo que source Y canal previo lo contradigan.
3. Canal de Origen previo si existe y es del catálogo.
4. Fuente de Prospecto (SUCURSAL fuerza sucursal; LEAD DIGITAL favorece formulario sobre facebook salvo evidencia).
"""

TARGET_TAGS = ("facebook-ads", "sucursal", "formulario")

CANAL_BY_TAG = {
    "facebook-ads": "FACEBOOK",
    "sucursal": "SUCURSAL",
    "formulario": "FORMULARIO",
}

TAG_BY_CANAL = {v: k for k, v in CANAL_BY_TAG.items()}

FUENTE_BY_TAG = {
    "facebook-ads": "LEAD DIGITAL",
    "sucursal": "SUCURSAL",
    "formulario": "LEAD DIGITAL",
}

DIGITAL_KEYWORDS = ("facebook", "ads", "instagram", "fb.com", "ig ", " ig", "ig:", "meta")
FORM_KEYWORDS = (
    "form", "formulario", "web", "landing", "page", "survey", "encuesta",
    "qr", "chat", "widget", "inbound", "tiktok", "whatsapp", "wa.me", "api",
    "sms", "lead-form", "leadform",
)
SUCURSAL_KEYWORDS = ("sucursal", "manual", "tienda", "offline", "store", "walk-in", "walkin")


def classify_source(source):
    s = (source or "").strip().lower()
    if not s:
        return None
    if any(w in s for w in DIGITAL_KEYWORDS):
        return "facebook-ads"
    if any(w in s for w in FORM_KEYWORDS):
        return "formulario"
    if any(w in s for w in SUCURSAL_KEYWORDS):
        return "sucursal"
    return None


def canal_value_to_tag(canal_value):
    return TAG_BY_CANAL.get((canal_value or "").strip().upper())


def opportunity_canal_to_tag(opp_canal_value):
    """Mapea el campo 'Canal de Origen de la Oportunidad' (Facebook|Formulario|Sucursal|...)."""
    v = (opp_canal_value or "").strip().lower()
    if not v:
        return None
    if "facebook" in v or "ig" in v or "instagram" in v:
        return "facebook-ads"
    if "formulario" in v or "form" in v or "web" in v or "whatsapp" in v:
        return "formulario"
    if "sucursal" in v or "tienda" in v or "manual" in v:
        return "sucursal"
    return None


def decide(tags, fuente_value, canal_value, source, opportunity_canal_value=None):
    tags_lower = {str(t).strip().lower() for t in tags or []}
    present_targets = tags_lower & set(TARGET_TAGS)
    source_tag = classify_source(source)
    prior_canal_tag = canal_value_to_tag(canal_value)
    opp_tag = opportunity_canal_to_tag(opportunity_canal_value)
    fuente_norm = (fuente_value or "").strip().upper()

    decided_tag = None
    confident = False
    review = False
    reason = ""

    if len(present_targets) == 1:
        only_tag = next(iter(present_targets))
        contradicts_source = source_tag and source_tag != only_tag
        contradicts_canal = prior_canal_tag and prior_canal_tag != only_tag
        if contradicts_source and contradicts_canal:
            decided_tag = only_tag
            confident = False
            review = True
            reason = (
                f"tag único='{only_tag}', source='{source}' sugiere '{source_tag}', "
                f"canal previo='{canal_value}' -> conflicto, requiere revisión"
            )
        else:
            decided_tag = only_tag
            confident = True
            reason = f"tag único='{only_tag}'"
            if contradicts_source:
                reason += f" (source='{source}' sugiere '{source_tag}', se respeta tag)"
            elif contradicts_canal:
                reason += f" (canal previo='{canal_value}' difiere, se actualiza canal)"

    elif len(present_targets) >= 2:
        if source_tag and source_tag in present_targets:
            decided_tag = source_tag
            confident = True
            reason = f"mix {sorted(present_targets)} -> source='{source}' apunta a '{source_tag}'"
        elif source_tag:
            decided_tag = source_tag
            confident = True
            reason = (
                f"mix {sorted(present_targets)} pero source='{source}' sugiere '{source_tag}' "
                "(fuera del mix); se respeta source"
            )
        elif prior_canal_tag and prior_canal_tag in present_targets:
            decided_tag = prior_canal_tag
            confident = True
            reason = f"mix {sorted(present_targets)} -> canal previo '{canal_value}' apunta a '{prior_canal_tag}'"
        elif prior_canal_tag:
            decided_tag = prior_canal_tag
            confident = True
            reason = (
                f"mix {sorted(present_targets)} -> canal previo '{canal_value}' "
                "(no incluido en mix actual)"
            )
        elif opp_tag and opp_tag in present_targets:
            decided_tag = opp_tag
            confident = True
            reason = (
                f"mix {sorted(present_targets)} -> oportunidad canal='{opportunity_canal_value}' "
                f"-> '{opp_tag}'"
            )
        elif opp_tag:
            decided_tag = opp_tag
            confident = True
            reason = (
                f"mix {sorted(present_targets)} -> oportunidad canal='{opportunity_canal_value}' "
                f"(ajeno al mix) -> '{opp_tag}'"
            )
        elif fuente_norm == "SUCURSAL" and "sucursal" in present_targets:
            decided_tag = "sucursal"
            confident = True
            reason = f"mix {sorted(present_targets)} -> fuente=SUCURSAL"
        elif fuente_norm == "LEAD DIGITAL":
            if "formulario" in present_targets:
                decided_tag = "formulario"
            elif "facebook-ads" in present_targets:
                decided_tag = "facebook-ads"
            if decided_tag:
                confident = True
                reason = f"mix {sorted(present_targets)} -> fuente=LEAD DIGITAL -> '{decided_tag}'"
        if not decided_tag:
            review = True
            reason = f"mix {sorted(present_targets)} sin source/canal/fuente que resuelva"

    else:
        if source_tag:
            decided_tag = source_tag
            confident = True
            reason = f"sin tag target, source='{source}' -> '{source_tag}'"
        elif prior_canal_tag:
            decided_tag = prior_canal_tag
            confident = True
            reason = f"sin tag target, canal previo '{canal_value}' -> '{prior_canal_tag}'"
        elif opp_tag:
            decided_tag = opp_tag
            confident = True
            reason = f"sin tag target, oportunidad canal='{opportunity_canal_value}' -> '{opp_tag}'"
        elif fuente_norm == "SUCURSAL":
            decided_tag = "sucursal"
            confident = True
            reason = "sin tag target, fuente=SUCURSAL"
        elif fuente_norm == "LEAD DIGITAL":
            decided_tag = "formulario"
            confident = True
            reason = "sin tag target, fuente=LEAD DIGITAL -> default 'formulario'"
        else:
            review = True
            reason = "sin tag target, sin source claro, sin canal previo, sin fuente"

    canal_value_out = CANAL_BY_TAG[decided_tag] if decided_tag else None
    tags_to_add = [decided_tag] if decided_tag and decided_tag not in tags_lower else []
    tags_to_remove = sorted(t for t in present_targets if decided_tag and t != decided_tag)

    return {
        "decided_tag": decided_tag,
        "canal_value": canal_value_out,
        "fuente_value": FUENTE_BY_TAG[decided_tag] if decided_tag else None,
        "tags_to_add": tags_to_add,
        "tags_to_remove": tags_to_remove,
        "confident": confident,
        "review": review,
        "reason": reason,
        "present_targets": sorted(present_targets),
        "source_tag": source_tag,
        "prior_canal_tag": prior_canal_tag,
    }
