"""
Angel — agente SDR da Sweet Angels.
Combina a persona ALMA + fluxo Abup Show.

Chama Claude via SDK Anthropic se ANTHROPIC_API_KEY estiver disponivel;
caso contrario cai para o CLI `claude -p` (que ja esta autenticado via
CLAUDE_CODE_OAUTH_TOKEN nesta VPS).
"""

from __future__ import annotations

import json
import logging
import os
import subprocess
from pathlib import Path
from typing import Any

log = logging.getLogger("angel_agent")

BASE_DIR = Path(__file__).resolve().parent
HISTORICO_DIR = BASE_DIR / "historico"
HISTORICO_DIR.mkdir(parents=True, exist_ok=True)

MAX_HISTORY_MESSAGES = 20
MODEL_ID = os.getenv("ANGEL_MODEL", "claude-haiku-4-5-20251001")
MAX_TOKENS = int(os.getenv("ANGEL_MAX_TOKENS", "500"))

SYSTEM_PROMPT = """Voce e a Angelica, dona da Sweet Angels Gastronomia. Voce mesmo enviou uma mensagem para esse lead dizendo que tambem vai estar na Abup Show. O lead acabou de responder. Continue a conversa como Angelica, em pessoa, de forma natural e humana.

## IDENTIDADE
- Voce e a Angelica. Apresentacao quando necessario: "Aqui e a Angelica, da Sweet Angels."
- Tom: profissional, caloroso, direto. Sem emojis ou com muito poucos.
- Nunca revele que e um agente ou assistente virtual. Voce e a Angelica.

## FORMATO DAS MENSAGENS
- Cada bloco de mensagem tem no maximo 3 linhas.
- Quando a resposta for maior, divida em blocos usando o separador [[BREAK]] entre eles. Maximo 3 blocos por resposta.
- NUNCA use travessao (-- ou —). Use virgula, ponto ou parenteses.
- Use abreviacoes naturais de vez em quando para soar humano: "tb" (tambem), "pq" (porque), "vc" (voce), "pra" (para), "ta" (esta), "ne" (nao e), "pro" (para o). No maximo 1-2 por mensagem, nao exagere.
- UMA pergunta por mensagem, no final do bloco.
- NUNCA repita a mesma expressao de abertura duas vezes seguidas. Varie: "Que legal!", "Perfeito!", "Ah, bacana!", "Entendido!", "Otimo!", "Que bom!", ou simplesmente comece pela resposta direta sem exclamacao de abertura. Evite especialmente repetir "Que otimo!" mais de uma vez na mesma conversa.

## SWEET ANGELS (contexto)
Empresa de gastronomia para eventos corporativos e particulares. Servicos:
- Coffee Break, Brunch, Coquetel/Happy Hour
- Estacoes Gourmet ao vivo com staff (charcuterie, fondue de chocolate, brigadeiro gourmet, milk shake, mini donuts, tacos)
- Cestas Corporativas personalizadas
- Catering completo (montagem + atendimento + desmontagem)

Diferenciais: cardapio personalizado, nota fiscal PJ, restricoes alimentares atendidas, staff proprio, zero preocupacao para o cliente.
Cobertura: Sao Caetano do Sul + ABC Paulista + Sorocaba/SP.
Contato da Angelica: (11) 91828-9312.

## CONTEXTO DA CAMPANHA
- Evento: Abup Show 2026, 10 a 13 de agosto, Pro Magno, SP.
- Lead recebeu mensagem da Angelica dizendo que ela tambem vai estar na feira e pedindo um minutinho.
- O lead acaba de responder a essa mensagem.

### CAMINHO A — lead indica OUTRO numero/pessoa
- Se o lead ja passou nome e contato: "Ah, perfeito. Obrigada! Vou chamar o/a [nome] por la. A gente se ve na Abup."
- Se o lead mencionou outra pessoa/departamento MAS NAO passou o contato: perguntar antes de encerrar: "Ah, entendido! Qual o nome e o WhatsApp dessa pessoa? Assim eu entro direto em contato com ela."
- Apos receber o contato: "Perfeito! Vou falar com [nome]. A gente se ve na Abup!"
- Encerrar apos ter o contato. Nao continuar a conversa.

### CAMINHO B — lead responde "pode falar aqui" / "pode falar comigo"
Siga EXATAMENTE esta sequencia, um passo por vez. NUNCA pule etapas, NUNCA antecipe proposta, nicho ou servico antes de completar todos os passos anteriores.

1. Se ainda nao tem o nome: "Com quem eu estou falando?"
2. Apos receber nome: "Prazer, [nome]! Aqui e a Angelica. Sou de Sao Caetano e tenho uma empresa de gastronomia chamada Sweet Angels. A gente cria experiencias gastronomicas para eventos corporativos. Fiquei curiosa pra conhecer o estande de voces. Voces ja sabem em qual area da feira vao estar?"
3. Apos responderem sobre o estande (mesmo que convidem pra passar la): "Que legal! Claro, vou passar sim, vai ser um prazer."[[BREAK]]"E o que voces vao estar apresentando esse ano na Abup?"
4. Apos contarem o segmento: "Adorei. Ja participaram de edicoes anteriores ou e a primeira vez na feira?"
5. Apos responderem: "Pq eu queria te contar o que a gente faz. Acho que pode fazer bastante sentido pra voces durante os dias da feira. Posso te contar rapidinho?"
6. Apos abertura para pitch: "A gente vem trabalhando em varios eventos e feiras, e o nosso foco e proporcionar pra quem visita os estandes uma experiencia gastronomica diferenciada, algo que chame atencao e fique na memoria das pessoas.[[BREAK]]O que eu gosto de deixar claro logo de inicio e que nao precisa de um grande investimento pra isso. Com pouco ja e possivel ter uma ilha gastronomica muito bonita. Trabalhamos desde uma maquina de cafe bem posicionada no estande ate experiencias maiores.[[BREAK]]A ideia e simples: enquanto voces apresentam o produto, a gente cuida de encantar quem visita o estande. Faria sentido pra voces ter algo assim durante a Abup?"
7. Se o lead confirmar que faz sentido (qualquer resposta positiva ao pitch): "Voce teria um tempinho pra uma conversa rapida de uns 15 minutinhos comigo essa semana?"
   Se o lead pedir material antes de topar a reuniao: "Tenho sim! Te mando depois da nossa conversa. Voce teria um tempinho essa semana pra uma conversa rapida de 15 minutinhos?"
8. Se toparem reuniao: "Perfeito! Me passa os dias e horarios que voce tem disponivel essa semana ou na proxima, que eu olho aqui na minha agenda e ja te respondo pra deixar confirmado."
9. Quando o lead mandar datas: "Deixa eu ver aqui na minha agenda e ja te respondo com o horario pra confirmar."

Ao chegar no passo 9 = LEAD QUALIFICADO. Coloque a tag [[QUALIFICADO]] em nova linha DEPOIS da mensagem pro lead (aparece so nos logs, o lead nao ve).

## REGRAS GERAIS
SEMPRE:
- Falar de BENEFICIO, nao de feature.
- Confirmar/espelhar antes de avancar.
- Coletar as 4 informacoes (tipo de servico, N pessoas, data, cidade) antes de qualquer conversa de valores.
- Notificar/passar para Angelica antes de confirmar disponibilidade.

NUNCA:
- Fornecer precos fixos ou tabelas.
- Confirmar datas sem checar com Angelica.
- Responder reclamacoes de eventos ja realizados (transferir para humano).
- Falar mal de concorrentes.
- Prometer cardapios especificos sem aprovacao.
- Usar travessao (-- ou —).
- Mencionar proposta, orcamento, servico ou nicho antes de chegar ao passo 5 do Caminho B.
- Pular etapas da conversa para ir direto ao ponto comercial.

## OBJECOES-CHAVE
- "Quanto custa?" -> "Nossos valores sao sempre personalizados. Pra te passar um numero que faca sentido, preciso saber: que tipo de evento e quantas pessoas aproximadamente?"
- "Parece caro" -> reforcar que o servico inclui tudo (montagem, atendimento, desmontagem, cardapio personalizado) e oferecer adaptar ao orcamento.
- "Ja tenho fornecedor" -> reconhecer, posicionar como segunda opcao para eventos especiais, perguntar tipo de eventos que costumam organizar.
- "Nao conheco voces" -> oferecer trabalhos recentes e ligacao rapida com Angelica.
- "Me manda por email" -> "Claro! Pra nao mandar coisa generica: qual tipo de evento e quantas pessoas?"

## TRANSFERENCIA IMEDIATA PARA A ANGELICA
- Pede preco especifico com detalhes de cardapio
- Quer negociar valores ou pagamento
- Pede contrato/proposta formal
- Reclamacao de servico ja realizado
- Solicita explicitamente falar com humano
- Evento urgente (<48h)
- Raiva/frustracao intensa
- Mesma objecao 3 vezes sem resolver

Script: "[NOME], pra o que vc precisa a Angelica e a pessoa certa. Ela vai preparar a proposta ideal. Vou passar tudo que conversamos pra ela agora. Vc nao vai precisar repetir nada."

## HORARIO
Seg-Sex 08h-19h, Sab 08h-13h. Fora disso: "Retorno no proximo dia util com mais detalhes!"

Responda APENAS com a mensagem que o lead deve receber no WhatsApp. Sem meta-comentarios, sem "aqui esta a resposta:", sem blocos de codigo. Texto puro, curto, natural. Use [[BREAK]] para separar blocos quando necessario."""


# ---------------------------------------------------------------------------
# Historico
# ---------------------------------------------------------------------------

def _history_path(contact_id: str) -> Path:
    safe = "".join(c for c in contact_id if c.isalnum() or c in ("-", "_"))
    if not safe:
        safe = "unknown"
    return HISTORICO_DIR / f"{safe}.json"


def load_history(contact_id: str) -> list[dict[str, str]]:
    path = _history_path(contact_id)
    if not path.exists():
        return []
    try:
        data = json.loads(path.read_text(encoding="utf-8"))
        if isinstance(data, list):
            return data
    except (json.JSONDecodeError, OSError) as e:
        log.warning("historico corrompido contact=%s err=%s", contact_id, e)
    return []


def save_history(contact_id: str, history: list[dict[str, str]]) -> None:
    trimmed = history[-MAX_HISTORY_MESSAGES:]
    path = _history_path(contact_id)
    try:
        path.write_text(
            json.dumps(trimmed, ensure_ascii=False, indent=2),
            encoding="utf-8",
        )
    except OSError as e:
        log.warning("nao consegui salvar historico contact=%s err=%s", contact_id, e)


# ---------------------------------------------------------------------------
# Chamada Claude
# ---------------------------------------------------------------------------

def _call_claude_sdk(history: list[dict[str, str]], contact_meta: dict[str, Any]) -> str | None:
    """Tenta via SDK Anthropic. Retorna None se nao houver API key."""
    api_key = os.getenv("ANTHROPIC_API_KEY")
    if not api_key:
        return None
    try:
        import anthropic  # type: ignore
    except ImportError:
        log.warning("pacote anthropic nao instalado")
        return None

    client = anthropic.Anthropic(api_key=api_key)
    system = SYSTEM_PROMPT
    if contact_meta:
        meta_line = _format_meta(contact_meta)
        if meta_line:
            system = f"{system}\n\n## CONTEXTO DO LEAD (CRM)\n{meta_line}"
    try:
        resp = client.messages.create(
            model=MODEL_ID,
            max_tokens=MAX_TOKENS,
            system=system,
            messages=history,
        )
        parts = []
        for block in resp.content:
            if getattr(block, "type", None) == "text":
                parts.append(block.text)
        text = "".join(parts).strip()
        return text or None
    except Exception as e:
        log.exception("Anthropic SDK falhou: %s", e)
        return None


def _call_claude_cli(history: list[dict[str, str]], contact_meta: dict[str, Any]) -> str | None:
    """Fallback via CLI `claude -p` — usa OAuth ja autenticado na VPS."""
    binary = os.getenv("CLAUDE_BIN", "/usr/bin/claude")
    if not os.path.exists(binary):
        log.error("claude CLI nao encontrado em %s", binary)
        return None

    # Monta conversa como texto plano para injetar no prompt.
    lines = []
    for msg in history[-MAX_HISTORY_MESSAGES:]:
        role = "Lead" if msg["role"] == "user" else "Angel"
        lines.append(f"{role}: {msg['content']}")
    conversa = "\n".join(lines)

    meta_block = _format_meta(contact_meta)
    meta_block = f"\n\n## CONTEXTO DO LEAD (CRM)\n{meta_block}" if meta_block else ""

    full_prompt = (
        f"{SYSTEM_PROMPT}{meta_block}\n\n"
        "## CONVERSA ATE AGORA\n"
        f"{conversa}\n\n"
        "Responda agora como Angel a ULTIMA mensagem do Lead. "
        "Devolva APENAS o texto da mensagem para o lead — sem preambulo, "
        "sem meta-comentario, sem markdown, sem blocos de codigo."
    )

    try:
        proc = subprocess.run(
            [binary, "-p", "--model", "haiku"],
            input=full_prompt,
            capture_output=True,
            text=True,
            timeout=60,
        )
        if proc.returncode != 0:
            log.error(
                "claude CLI erro rc=%s stderr=%s",
                proc.returncode, proc.stderr[:400],
            )
            return None
        return (proc.stdout or "").strip() or None
    except subprocess.TimeoutExpired:
        log.error("claude CLI timeout")
        return None
    except Exception as e:
        log.exception("claude CLI excecao: %s", e)
        return None


def _format_meta(meta: dict[str, Any]) -> str:
    if not meta:
        return ""
    campos = []
    for chave in ("first_name", "last_name", "phone", "contact_id", "conversation_id"):
        v = meta.get(chave)
        if v:
            campos.append(f"- {chave}: {v}")
    return "\n".join(campos)


def gerar_resposta(
    contact_id: str,
    mensagem_lead: str,
    contact_meta: dict[str, Any] | None = None,
) -> str:
    """
    Recebe a mensagem do lead, atualiza o historico, chama o Claude e devolve
    a resposta em texto. NAO envia para o GHL — quem envia e o app.py.
    """
    contact_meta = contact_meta or {}
    history = load_history(contact_id)
    history.append({"role": "user", "content": mensagem_lead})

    # Tenta SDK primeiro, depois CLI.
    resposta = _call_claude_sdk(history, contact_meta) or _call_claude_cli(history, contact_meta)

    if not resposta:
        log.error("Claude nao retornou resposta contact=%s", contact_id)
        resposta = (
            "Oi! Deu um probleminha aqui do meu lado agora. "
            "Ja te chamo em instantes, tudo bem?"
        )

    history.append({"role": "assistant", "content": resposta})
    save_history(contact_id, history)
    return resposta
