#!/usr/bin/env python3
"""
ETAPA 2 FINAL - Completa gelado-lote2 e gelado-lote3 com filtro de waitlist.
gelado-lote1: já completo no checkpoint (750 aplicados, 5 pulados).
gelado-lote2: index 1000-1999 (1000 emails)
gelado-lote3: index 2000-9999 (331 emails)
"""

import csv
import json
import sys
import time
from pathlib import Path
import requests

BASE = "https://services.leadconnectorhq.com"
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/126.0 Safari/537.36"
WORK_DIR = Path("/opt/mia/workspace/clientes/px3lab/mapeamento_leads_lancamento_1007")
CHECKPOINT_FILE = Path("/tmp/correcao_px3_checkpoint.json")
CHECKPOINT_INTERVAL = 250
DELAY = 0.22

_env = {}
with open("/opt/mia/config/linkia_px3.env") as f:
    for line in f:
        line = line.strip()
        if "=" in line and not line.startswith("#"):
            k, v = line.split("=", 1)
            _env[k.strip()] = v.strip().strip('"').strip("'")

TOKEN = _env.get("LINKIA_PX3_TOKEN", "")
LOC = _env.get("LINKIA_PX3_LOCATION_ID", "")

if not TOKEN or not LOC:
    print("ERRO: credenciais não encontradas")
    sys.exit(1)

HEADERS = {
    "Authorization": f"Bearer {TOKEN}",
    "Version": "2021-07-28",
    "Content-Type": "application/json",
    "User-Agent": UA,
}

print(f"TOKEN: ...{TOKEN[-8:]}")
print(f"LOCATION_ID: {LOC}")


def load_checkpoint() -> dict:
    if CHECKPOINT_FILE.exists():
        with open(CHECKPOINT_FILE) as f:
            return json.load(f)
    return {}


def save_checkpoint(cp: dict):
    with open(CHECKPOINT_FILE, "w") as f:
        json.dump(cp, f, indent=2)


def get_waitlist() -> tuple[set, set]:
    """Busca waitlist de /tmp/waitlist_data.json (pré-carregado) ou via API."""
    cache = Path("/tmp/waitlist_data.json")
    if cache.exists():
        d = json.loads(cache.read_text())
        ids = set(d.get("ids", []))
        emails = set(d.get("emails", []))
        print(f"  Waitlist do cache: {len(ids)} IDs, {len(emails)} emails")
        return ids, emails

    print("  Buscando waitlist via API...")
    try:
        r = requests.post(
            f"{BASE}/contacts/search",
            headers=HEADERS,
            json={
                "locationId": LOC,
                "filters": [{"field": "tags", "operator": "contains", "value": "waitlist-photorf2-v2"}],
                "page": 1,
                "pageLimit": 100,
            },
            timeout=20,
        )
        if r.status_code == 200:
            contacts = r.json().get("contacts", [])
            ids = {c["id"] for c in contacts if c.get("id")}
            emails = {c["email"].strip().lower() for c in contacts if c.get("email")}
            print(f"  Waitlist via API: {len(ids)} IDs, {len(emails)} emails")
            cache.write_text(json.dumps({"ids": list(ids), "emails": list(emails)}))
            return ids, emails
        else:
            print(f"  [waitlist] ERRO {r.status_code}: {r.text[:100]}")
            return set(), set()
    except Exception as e:
        print(f"  [waitlist EXCEPTION]: {e}")
        return set(), set()


def lookup_contact(email: str) -> dict | None:
    try:
        r = requests.get(
            f"{BASE}/contacts/",
            headers=HEADERS,
            params={"locationId": LOC, "query": email, "limit": 5},
            timeout=15,
        )
        if r.status_code == 200:
            contacts = r.json().get("contacts", [])
            for c in contacts:
                if (c.get("email") or "").strip().lower() == email.lower():
                    return c
            if len(contacts) == 1:
                return contacts[0]
        return None
    except Exception as e:
        print(f"  [lookup EXCEPTION] {email}: {e}")
        return None


def apply_tag(contact_id: str, tag: str) -> tuple[bool, int]:
    try:
        r = requests.post(
            f"{BASE}/contacts/{contact_id}/tags",
            headers=HEADERS,
            json={"tags": [tag]},
            timeout=15,
        )
        return r.status_code in (200, 201), r.status_code
    except Exception as e:
        print(f"  [apply_tag EXCEPTION] id={contact_id}: {e}")
        return False, 0


def load_csv_slice(path: Path, start: int, end: int) -> list[str]:
    emails = []
    with open(path, newline="", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for i, row in enumerate(reader):
            if i < start:
                continue
            if i >= end:
                break
            email = (row.get("email") or "").strip().lower()
            if email:
                emails.append(email)
    return emails


def process_lote(batch_name: str, tag: str, emails: list[str], cp: dict, wl_ids: set, wl_emails: set):
    if "etapa2" not in cp:
        cp["etapa2"] = {}
    if batch_name not in cp["etapa2"]:
        cp["etapa2"][batch_name] = {"sucesso": [], "pulados_waitlist": [], "nao_encontrado": [], "falha_tag": []}

    bc = cp["etapa2"][batch_name]
    done = set(bc["sucesso"] + bc["pulados_waitlist"] + bc["nao_encontrado"] + [x["email"] for x in bc["falha_tag"]])

    sucesso = len(bc["sucesso"])
    pulados = len(bc["pulados_waitlist"])
    nao_enc = len(bc["nao_encontrado"])
    falhas = len(bc["falha_tag"])
    ops = 0

    print(f"\n{'='*60}")
    print(f"LOTE: {batch_name} | tag: {tag}")
    print(f"Emails: {len(emails)} | Já feitos: {len(done)}")
    print(f"{'='*60}")

    for i, email in enumerate(emails, 1):
        if email in done:
            continue

        # Verificar waitlist pelo email
        if email in wl_emails:
            bc["pulados_waitlist"].append(email)
            pulados += 1
            done.add(email)
            print(f"  [SKIP waitlist] {email}")
            continue

        # Lookup
        c = lookup_contact(email)
        time.sleep(DELAY)

        if not c:
            bc["nao_encontrado"].append(email)
            nao_enc += 1
            done.add(email)
            continue

        cid = c.get("id", "")

        # Verificar waitlist pelo ID
        if cid in wl_ids:
            bc["pulados_waitlist"].append(email)
            pulados += 1
            done.add(email)
            print(f"  [SKIP waitlist por id] {email}")
            continue

        ok, status = apply_tag(cid, tag)
        time.sleep(DELAY)
        ops += 1

        if ok:
            sucesso += 1
            bc["sucesso"].append(email)
        else:
            falhas += 1
            bc["falha_tag"].append({"email": email, "id": cid, "status": status})
            print(f"  [FALHA] {email} status={status}")

        done.add(email)

        if ops % 50 == 0:
            pct = i / len(emails) * 100
            print(f"  [{i}/{len(emails)} {pct:.0f}%] ok={sucesso} skip={pulados} nc={nao_enc} fail={falhas}")

        if ops % CHECKPOINT_INTERVAL == 0:
            save_checkpoint(cp)
            print(f"  [CP {ops}] saved")

    save_checkpoint(cp)
    print(f"\n  RESULTADO {batch_name}: ok={sucesso} skip_wl={pulados} nc={nao_enc} fail={falhas}")
    return {"sucesso": sucesso, "pulados_waitlist": pulados, "nao_encontrado": nao_enc, "falhas": falhas}


def contar_tags() -> dict:
    print("\n" + "=" * 60)
    print("CONTAGEM FINAL")
    print("=" * 60)
    tags = [
        "lancamento-cloudphotorf2-quente",
        "lancamento-cloudphotorf2-morno",
        "lancamento-cloudphotorf2-frio",
        "lancamento-cloudphotorf2-gelado-lote1",
        "lancamento-cloudphotorf2-gelado-lote2",
        "lancamento-cloudphotorf2-gelado-lote3",
    ]
    contagens = {}
    for tag in tags:
        try:
            r = requests.post(
                f"{BASE}/contacts/search",
                headers=HEADERS,
                json={"locationId": LOC, "filters": [{"field": "tags", "operator": "contains", "value": tag}], "page": 1, "pageLimit": 1},
                timeout=15,
            )
            n = r.json().get("total", -1) if r.status_code == 200 else -1
            contagens[tag] = n
            print(f"  {tag}: {n}")
        except Exception as e:
            contagens[tag] = -1
            print(f"  {tag}: EXCEPTION {e}")
        time.sleep(DELAY)
    return contagens


def main():
    t0 = time.time()
    print("=" * 60)
    print("ETAPA 2 FINAL — GELADOS LOTE2+LOTE3 COM FILTRO WAITLIST")
    print("=" * 60)

    cp = load_checkpoint()

    print("\nCarregando waitlist...")
    wl_ids, wl_emails = get_waitlist()

    gelado_csv = WORK_DIR / "leads_gelado.csv"

    lotes = [
        # lote1 já está completo, mas deixar aqui para confirmar via checkpoint
        ("gelado-lote1", "lancamento-cloudphotorf2-gelado-lote1", 250, 1000),
        ("gelado-lote2", "lancamento-cloudphotorf2-gelado-lote2", 1000, 2000),
        ("gelado-lote3", "lancamento-cloudphotorf2-gelado-lote3", 2000, 9999),
    ]

    resultados = {}
    for batch_name, tag, csv_start, csv_end in lotes:
        emails = load_csv_slice(gelado_csv, csv_start, csv_end)
        res = process_lote(batch_name, tag, emails, cp, wl_ids, wl_emails)
        resultados[batch_name] = res

    contagens = contar_tags()

    elapsed = time.time() - t0
    print(f"\nTempo total: {int(elapsed//60)}m {int(elapsed%60)}s")
    print("\n" + "=" * 60)
    print("RESUMO FINAL")
    print("=" * 60)
    for lote, r in resultados.items():
        print(f"  {lote}: ok={r['sucesso']} skip_wl={r['pulados_waitlist']} nc={r['nao_encontrado']} fail={r['falhas']}")
    print("\nCONTAGEM CRM:")
    for tag, n in contagens.items():
        print(f"  {tag}: {n}")


if __name__ == "__main__":
    main()
