import base64
import hashlib
import hmac
import os
import uuid

import httpx
from fastapi import FastAPI, Header, HTTPException, Request

app = FastAPI()

API_BASE = os.getenv("NAHUI_API_BASE", "https://api.nahui.studio")
CONNECTION_ID = os.environ["NAHUI_CONNECTION_ID"]
API_KEY = os.environ["NAHUI_API_KEY"]
WEBHOOK_SECRET = os.environ["NAHUI_WEBHOOK_SECRET"]

# Demostración únicamente. Usa almacenamiento persistente con índice único.
processed_deliveries: set[str] = set()


def expected_signature(raw_body: bytes) -> str:
    digest = hmac.new(
        WEBHOOK_SECRET.encode("utf-8"),
        raw_body,
        hashlib.sha256,
    ).digest()
    encoded = base64.urlsafe_b64encode(digest).decode("ascii").rstrip("=")
    return f"sha256={encoded}"


@app.get("/health")
async def health():
    return {"ok": True}


@app.post("/webhooks/nahui")
async def nahui_webhook(
    request: Request,
    x_nahui_signature_256: str | None = Header(default=None),
):
    raw_body = await request.body()
    expected = expected_signature(raw_body)
    if not x_nahui_signature_256 or not hmac.compare_digest(x_nahui_signature_256, expected):
        raise HTTPException(status_code=401, detail="Firma inválida")

    try:
        event = await request.json()
    except Exception as exc:
        raise HTTPException(status_code=400, detail="JSON inválido") from exc

    delivery_id = event.get("deliveryId")
    if not delivery_id or event.get("type") != "message.received":
        raise HTTPException(status_code=400, detail="Evento no soportado")

    if delivery_id in processed_deliveries:
        return {}
    processed_deliveries.add(delivery_id)

    message = event.get("message") or {}
    if message.get("type") == "text" and message.get("text"):
        return {"reply": {"text": f"Recibí: {message['text']}"[:4000]}}
    return {}


async def send_reply(
    conversation_id: str,
    text: str,
    idempotency_key: str | None = None,
):
    key = idempotency_key or str(uuid.uuid4())
    async with httpx.AsyncClient(timeout=20.0) as client:
        response = await client.post(
            f"{API_BASE}/v1/connect/relay/{CONNECTION_ID}/reply",
            headers={
                "Authorization": f"Bearer {API_KEY}",
                "Content-Type": "application/json",
                "Idempotency-Key": key,
            },
            json={
                "conversationId": conversation_id,
                "message": {"text": text[:4000]},
            },
        )
    response.raise_for_status()
    return response.json()
