import os
import json
import logging
from pathlib import Path
from collections import defaultdict, deque

import httpx
from dotenv import load_dotenv
from fastapi import FastAPI, Request

# ---------------------------------------------------------------------
# Inicialização
# ---------------------------------------------------------------------
BASE_DIR = Path(__file__).resolve().parent
load_dotenv(dotenv_path=BASE_DIR / ".env", override=True)

INST_ID      = os.getenv("ZAPI_INSTANCE_ID")
INST_TOKEN   = os.getenv("ZAPI_INSTANCE_TOKEN")
SECURITY_TK  = os.getenv("ZAPI_CLIENT_TOKEN")
OPENAI_KEY   = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-3.5-turbo")

SEND_ENDPOINT = (
    f"https://api.z-api.io/instances/{INST_ID}/token/{INST_TOKEN}/send-text"
    if INST_ID and INST_TOKEN else None
)

logging.basicConfig(level=logging.INFO, format="%(levelname)s:%(name)s:%(message)s")
logger = logging.getLogger("main")

app = FastAPI()

# ---------------------------------------------------------------------
# Memória por cliente
# ---------------------------------------------------------------------
conversas = defaultdict(lambda: deque(maxlen=10))  # armazena as 10 últimas mensagens por cliente

# ---------------------------------------------------------------------
# Utilitários
# ---------------------------------------------------------------------
def ler_regras():
    try:
        regras = (BASE_DIR / "regras.txt").read_text(encoding="utf-8")
        logger.info("📜 Regras carregadas:\n%s", regras)
        return regras
    except Exception as e:
        logger.error("Erro ao ler regras.txt: %s", e)
        return "Não consegui acessar as regras agora."

async def enviar_whats(phone: str, texto: str):
    if not SEND_ENDPOINT:
        raise RuntimeError("SEND_ENDPOINT não configurado")

    payload = {"phone": phone, "message": texto}
    async with httpx.AsyncClient() as cli:
        r = await cli.post(
            SEND_ENDPOINT,
            headers={
                "Client-Token": SECURITY_TK,
                "Content-Type": "application/json",
            },
            json=payload,
            timeout=30,
        )
        if r.status_code == 404 and "Instance not found" in r.text:
            logger.error("❗ Z-API: instância não existe ou está inativa. Verifique ID e TOKEN.")
        r.raise_for_status()

async def gpt_resposta(phone: str, mensagem: str) -> str:
    regras = ler_regras()

    system_prompt = (
        "Você é Luna, uma assistente virtual da Lumix.\n"
        "Seu papel é atender os clientes com simpatia, clareza e agilidade.\n"
        "Use as regras abaixo como orientação, mas responda com naturalidade, adaptando-se à mensagem do cliente:\n\n"
        "- Sempre cumprimente o cliente de forma simpática.\n"
        "- Após a primeira saudação, pergunte qual tipo de atendimento ele precisa.\n"
        "- Se a opção for 'Orçamento', solicite os seguintes dados e informe que irá encaminhá-lo a um especialista:\n"
        "  - Nome:\n"
        "  - Telefone ou e-mail:\n"
        "- Se não tiver certeza sobre a resposta, diga que seu conhecimento é limitado às informações da empresa.\n"
        "- Se houver múltiplas perguntas, responda uma por uma.\n"
        "- Recuse-se a contar piadas.\n"
        "- Se não souber a resposta, peça que o cliente entre em contato com o SAC.\n"
        "- Informe sempre que todos os produtos são originais e com garantia.\n"
        "- Evite repetir as mesmas frases em todas as mensagens. Varie a linguagem mantendo o mesmo tom simpático e profissional.\n"
    )

    messages = [{"role": "system", "content": system_prompt}]
    messages.extend(conversas[phone])  # adiciona histórico
    messages.append({"role": "user", "content": mensagem.strip()})

    logger.info("📤 Enviando prompt ao GPT com regras e histórico...")

    async with httpx.AsyncClient() as cli:
        r = await cli.post(
            "https://api.openai.com/v1/chat/completions",
            headers={"Authorization": f"Bearer {OPENAI_KEY}"},
            json={
                "model": OPENAI_MODEL,
                "messages": messages,
                "temperature": 0.5
            },
            timeout=30,
        )
        r.raise_for_status()
        resposta = r.json()["choices"][0]["message"]["content"].strip()

        # Atualiza histórico
        conversas[phone].append({"role": "user", "content": mensagem.strip()})
        conversas[phone].append({"role": "assistant", "content": resposta})

        return resposta

# ---------------------------------------------------------------------
# Webhook principal
# ---------------------------------------------------------------------
@app.post("/webhook")
async def webhook(req: Request):
    client_host = req.client.host
    method = req.method
    headers = dict(req.headers)

    raw_body = await req.body()
    if not raw_body or raw_body.strip() == b"":
        logger.debug("🔁 Ignorado: corpo vazio (provável ping HTTP/2)")
        return {"status": "ignorado"}

    logger.info("📥 Nova requisição: %s %s", method, client_host)
    logger.info("📄 Headers: %s", json.dumps(headers, indent=2))
    logger.info("📦 Body (raw): %s", raw_body)

    try:
        data = await req.json()

        # ✅ Ignora mensagens enviadas por você mesmo (evita loop)
        if data.get("fromMe") is True or data.get("fromApi") is True:
            logger.info("🔁 Ignorado: mensagem enviada por mim mesmo.")
            return {"status": "ignorado"}

        # ✅ Verifica se é mensagem recebida
        if data.get("type") != "ReceivedCallback":
            logger.info("⚠️ Ignorado: tipo não é 'ReceivedCallback' (%s)", data.get("type"))
            return {"status": "ignorado"}

        phone = data.get("phone")
        msg = data.get("text", {}).get("message")

        if not phone or not msg:
            logger.warning("⚠️ Payload incompleto: %s", data)
            return {"status": "ignorado"}

        logger.info("📩 [%s] %s", phone, msg)

        resposta = await gpt_resposta(phone, msg)
        logger.info("✅ GPT: %s", resposta)

        await enviar_whats(phone, resposta)
        return {"status": "ok", "mensagem": resposta}

    except Exception as e:
        logger.exception("❌ Erro no webhook: %s", e)
        return {"status": "erro", "detalhe": str(e)}
