#!/usr/bin/env python3
"""
Warmup Dia 2 - Borrello
Seleciona 1000 contatos novos e aplica tag warmup-dia2-cameloterapia
Com retry automático e checkpoint intermediário
"""
import requests
import time
import json
import sys
import os

# Credenciais Borrello em /opt/mia/config/linkia_borrello.env
def _load_env_file(path):
    data = {}
    try:
        with open(path) as f:
            for line in f:
                line = line.strip()
                if not line or line.startswith("#") or "=" not in line:
                    continue
                k, v = line.split("=", 1)
                data[k.strip()] = v.strip().strip('"').strip("'")
    except FileNotFoundError:
        pass
    return data


_BORRELLO_ENV = _load_env_file("/opt/mia/config/linkia_borrello.env")
LOCATION_ID = (
    os.environ.get("LINKIA_BORRELLO_LOCATION_ID")
    or _BORRELLO_ENV.get("LINKIA_BORRELLO_LOCATION_ID", "")
)
TOKEN = (
    os.environ.get("LINKIA_BORRELLO_TOKEN")
    or _BORRELLO_ENV.get("LINKIA_BORRELLO_TOKEN", "")
)
if not TOKEN or not LOCATION_ID:
    raise RuntimeError(
        "warmup_dia2_tagger: credenciais Borrello nao encontradas. "
        "Verifique /opt/mia/config/linkia_borrello.env."
    )
BASE_URL = "https://services.leadconnectorhq.com"
HEADERS = {
    "Authorization": f"Bearer {TOKEN}",
    "Version": "2021-07-28",
    "Content-Type": "application/json",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
}

TAG_EXCLUIR = "warmup-dia1-cameloterapia"
TAG_NOVA = "warmup-dia2-cameloterapia"
TAG_ALUNO = "todos-os-alunos-10.25"
TAG_CLIENTE = "rd-cliente"
TAG_ENGAJADO = "engajados-30.08.2025"
META = 1000
CHECKPOINT_FILE = "/opt/mia/workspace/clientes/borrello/kit_tratamento/warmup_dia2_checkpoint.json"

def get_with_retry(url, max_retries=5, base_timeout=60):
    """GET com retry exponencial"""
    for attempt in range(max_retries):
        try:
            resp = requests.get(url, headers=HEADERS, timeout=base_timeout + attempt*30)
            if resp.status_code == 200:
                return resp
            elif resp.status_code == 429:
                wait = (2 ** attempt) * 2
                print(f"  Rate limit 429, aguardando {wait}s...", flush=True)
                time.sleep(wait)
            else:
                print(f"  Erro {resp.status_code}: {resp.text[:100]}", flush=True)
                time.sleep(2)
        except requests.exceptions.ReadTimeout:
            wait = (2 ** attempt) * 3
            print(f"  Timeout na tentativa {attempt+1}, aguardando {wait}s...", flush=True)
            time.sleep(wait)
        except Exception as e:
            print(f"  Erro inesperado: {e}", flush=True)
            time.sleep(5)
    return None

def fetch_all_contacts():
    """Pagina todos os contatos com checkpoint"""
    # Verificar se existe checkpoint
    contacts = []
    start_url = f"{BASE_URL}/contacts/?locationId={LOCATION_ID}&limit=100"
    
    if os.path.exists(CHECKPOINT_FILE):
        with open(CHECKPOINT_FILE) as f:
            checkpoint = json.load(f)
        contacts = checkpoint.get("contacts", [])
        start_url = checkpoint.get("next_url", start_url)
        if checkpoint.get("done"):
            print(f"  Usando checkpoint completo: {len(contacts)} contatos", flush=True)
            return contacts
        print(f"  Retomando do checkpoint: {len(contacts)} contatos, próxima URL carregada", flush=True)
    
    url = start_url
    page = 0
    
    while url:
        page += 1
        
        resp = get_with_retry(url)
        if resp is None:
            print(f"  FALHA após retries na página {page}. Salvando checkpoint...", flush=True)
            with open(CHECKPOINT_FILE, "w") as f:
                json.dump({"contacts": contacts, "next_url": url, "done": False}, f)
            print(f"  Checkpoint salvo com {len(contacts)} contatos. Relance o script.", flush=True)
            sys.exit(1)
        
        data = resp.json()
        batch = data.get("contacts", [])
        contacts.extend(batch)
        
        if len(contacts) % 1000 == 0 and len(contacts) > 0:
            print(f"  Carregados: {len(contacts)} contatos", flush=True)
        
        meta = data.get("meta", {})
        next_url = meta.get("nextPageUrl")
        
        if next_url and len(batch) > 0:
            url = next_url
            # Salvar checkpoint a cada 5000 contatos
            if len(contacts) % 5000 == 0:
                with open(CHECKPOINT_FILE, "w") as f:
                    json.dump({"contacts": contacts, "next_url": url, "done": False}, f)
        else:
            url = None
        
        time.sleep(0.12)
    
    # Marcar como completo
    with open(CHECKPOINT_FILE, "w") as f:
        json.dump({"contacts": contacts, "next_url": None, "done": True}, f)
    
    return contacts

def apply_tag(contact_id, tag):
    """Aplica uma tag a um contato com retry"""
    url = f"{BASE_URL}/contacts/{contact_id}/tags"
    payload = {"tags": [tag]}
    for attempt in range(3):
        try:
            resp = requests.post(url, headers=HEADERS, json=payload, timeout=20)
            if resp.status_code in (200, 201):
                return True
            elif resp.status_code == 429:
                time.sleep(3)
            elif resp.status_code == 400:
                # Já tem a tag ou outro erro - tratar como OK pra não bloquear
                body = resp.text
                if "contactId" in body or "already" in body.lower():
                    return True
                print(f"  400 em {contact_id}: {body[:80]}", flush=True)
                return False
            else:
                print(f"  Erro {resp.status_code} em {contact_id}", flush=True)
                return False
        except Exception as e:
            time.sleep(2)
    return False

def main():
    print("=== Warmup Dia 2 - Borrello ===")
    print(f"Meta: {META} contatos com tag '{TAG_NOVA}'")
    print()
    
    # FASE 1: Carregar todos os contatos
    print("FASE 1: Carregando base de contatos...")
    all_contacts = fetch_all_contacts()
    print(f"Total carregado: {len(all_contacts)} contatos")
    print()
    
    # FASE 2: Classificar contatos
    print("FASE 2: Classificando por tags...")
    
    ja_receberam_ids = []
    candidatos_tier1 = []
    candidatos_tier2 = []
    ja_tem_dia2 = []
    sem_email_count = 0
    
    for c in all_contacts:
        tags = set(c.get("tags", []))
        cid = c.get("id")
        email = c.get("email", "")
        
        if not email or "@" not in email:
            sem_email_count += 1
            continue
        
        if TAG_EXCLUIR in tags:
            ja_receberam_ids.append(cid)
            continue
        
        if TAG_NOVA in tags:
            ja_tem_dia2.append(cid)
            continue
        
        if TAG_ALUNO in tags or TAG_CLIENTE in tags:
            candidatos_tier1.append(cid)
        elif TAG_ENGAJADO in tags:
            candidatos_tier2.append(cid)
    
    print(f"  Já receberam (dia1 - excluídos): {len(ja_receberam_ids)}")
    print(f"  Já têm dia2 (retomada):          {len(ja_tem_dia2)}")
    print(f"  Tier 1 (aluno/cliente):           {len(candidatos_tier1)}")
    print(f"  Tier 2 (engajados):               {len(candidatos_tier2)}")
    print(f"  Sem email:                         {sem_email_count}")
    print()
    
    # FASE 3: Montar lista de 1000
    faltam = META - len(ja_tem_dia2)
    
    if faltam <= 0:
        print(f"Tag '{TAG_NOVA}' já aplicada em {len(ja_tem_dia2)} contatos. Nada a fazer.")
        return
    
    selecionados_tier1 = candidatos_tier1[:faltam]
    restante = faltam - len(selecionados_tier1)
    selecionados_tier2 = candidatos_tier2[:restante] if restante > 0 else []
    
    selecionados = selecionados_tier1 + selecionados_tier2
    
    print(f"FASE 3: Seleção final")
    print(f"  Já tinham dia2 (retomada): {len(ja_tem_dia2)}")
    print(f"  Tier 1 a taggear:          {len(selecionados_tier1)}")
    print(f"  Tier 2 a taggear:          {len(selecionados_tier2)}")
    print(f"  Total a aplicar agora:     {len(selecionados)}")
    print(f"  Total esperado após:       {len(ja_tem_dia2) + len(selecionados)}")
    print()
    
    if len(selecionados) == 0:
        print("ERRO: Sem candidatos disponíveis para selecionar!")
        # Diagnóstico extra
        total_com_email = sum(1 for c in all_contacts if c.get("email") and "@" in c.get("email",""))
        print(f"  Total com email: {total_com_email}")
        print(f"  Total tier1+tier2 disponível: {len(candidatos_tier1)+len(candidatos_tier2)}")
        return
    
    # FASE 4: Aplicar tags
    print(f"FASE 4: Aplicando tag '{TAG_NOVA}' em {len(selecionados)} contatos...")
    sucesso = 0
    falha = 0
    
    for i, cid in enumerate(selecionados):
        ok = apply_tag(cid, TAG_NOVA)
        if ok:
            sucesso += 1
        else:
            falha += 1
        
        if (i + 1) % 100 == 0:
            print(f"  Progresso: {i+1}/{len(selecionados)} | OK: {sucesso} | Falha: {falha}", flush=True)
        
        time.sleep(0.17)
    
    print()
    print("=== RESULTADO FINAL ===")
    print(f"Tag aplicada com sucesso: {sucesso}")
    print(f"Falhas:                   {falha}")
    print(f"Já tinham (retomada):     {len(ja_tem_dia2)}")
    total_final = sucesso + len(ja_tem_dia2)
    print(f"TOTAL com '{TAG_NOVA}':   {total_final}")
    print()
    print(f"COMPOSICAO DO PUBLICO:")
    print(f"  Tier 1 (aluno/cliente): {len(selecionados_tier1)} ({len(selecionados_tier1)/max(total_final,1)*100:.1f}%)")
    print(f"  Tier 2 (engajados):     {len(selecionados_tier2)} ({len(selecionados_tier2)/max(total_final,1)*100:.1f}%)")
    
    resultado = {
        "data": "2026-09-14",
        "tag_aplicada": TAG_NOVA,
        "total_com_tag": total_final,
        "tier1_aluno_cliente": len(selecionados_tier1),
        "tier2_engajados": len(selecionados_tier2),
        "ja_tinham_retomada": len(ja_tem_dia2),
        "falhas_ao_taggear": falha,
        "excluidos_dia1": len(ja_receberam_ids),
        "sem_email": sem_email_count
    }
    
    with open("/opt/mia/workspace/clientes/borrello/kit_tratamento/warmup_dia2_resultado.json", "w") as f:
        json.dump(resultado, f, ensure_ascii=False, indent=2)
    
    print()
    print("Resultado salvo em warmup_dia2_resultado.json")

if __name__ == "__main__":
    main()
