import { randomUUID } from "node:crypto";
import { getDbPool } from "@/db";

type WhatsAppDeliveryInput = {
  inspectionId: string;
  tenantId: string;
  responsibleName: string | null;
  responsiblePhone: string | null;
  inspectionUrl: string;
};

export type WhatsAppDeliveryResult = {
  status: "sent" | "failed" | "awaiting_provider";
  message: string;
  providerMessageSid?: string;
};

function normalizePhone(value: string) {
  const trimmed = value.trim();
  const digits = trimmed.replace(/\D/g, "");
  if (!digits) return "";
  // Números em E.164 (como o remetente americano da Twilio no Sandbox)
  // não podem receber automaticamente o código brasileiro +55.
  if (trimmed.startsWith("+")) return `+${digits}`;
  if (digits.startsWith("00")) return `+${digits.slice(2)}`;
  return digits.startsWith("55") ? `+${digits}` : `+55${digits}`;
}

function maskPhone(value: string) {
  if (value.length < 6) return "***";
  return `${value.slice(0, 5)}******${value.slice(-2)}`;
}

function getContentVariables(input: WhatsAppDeliveryInput, recipientName: string) {
  const raw = process.env.TWILIO_WHATSAPP_CONTENT_VARIABLES?.trim();
  if (!raw) return undefined;

  try {
    const configured = JSON.parse(raw) as Record<string, unknown>;
    const replacements: Record<string, string> = {
      "{{responsibleName}}": recipientName,
      "{{inspectionUrl}}": input.inspectionUrl,
      "{{inspectionId}}": input.inspectionId,
    };

    return Object.fromEntries(
      Object.entries(configured).map(([key, value]) => [
        key,
        typeof value === "string"
          ? Object.entries(replacements).reduce((text, [placeholder, replacement]) => text.replaceAll(placeholder, replacement), value)
          : String(value ?? ""),
      ]),
    );
  } catch {
    throw new Error("TWILIO_WHATSAPP_CONTENT_VARIABLES deve conter um JSON válido.");
  }
}

async function writeLog(input: WhatsAppDeliveryInput, status: "sent" | "failed" | "awaiting_provider", recipient: string, summary: string, providerMessageSid?: string, errorCode?: string) {
  try {
    await getDbPool().execute(
      `INSERT INTO inspection_message_logs
       (id, inspection_id, tenant_id, channel, provider, status, recipient_masked, provider_message_sid, error_code, summary)
       VALUES (?, ?, ?, 'whatsapp', 'twilio', ?, ?, ?, ?, ?)`,
      [randomUUID(), input.inspectionId, input.tenantId, status, maskPhone(recipient), providerMessageSid || null, errorCode || null, summary.slice(0, 500)],
    );
  } catch (error) {
    // A mensagem não deve deixar de ser enviada caso a auditoria ainda não tenha sido migrada.
    console.error("Erro ao registrar envio de WhatsApp", error);
  }
}

export async function sendInspectionWhatsApp(input: WhatsAppDeliveryInput): Promise<WhatsAppDeliveryResult> {
  const accountSid = process.env.TWILIO_ACCOUNT_SID?.trim();
  const authToken = process.env.TWILIO_AUTH_TOKEN?.trim();
  const from = normalizePhone(process.env.TWILIO_WHATSAPP_FROM || "");
  const testRecipient = normalizePhone(process.env.TWILIO_WHATSAPP_TEST_TO || "");
  const contentSid = process.env.TWILIO_WHATSAPP_CONTENT_SID?.trim();
  const recipient = normalizePhone(input.responsiblePhone || "");

  if (!accountSid || !authToken || !from || process.env.TWILIO_WHATSAPP_ENABLED !== "true") {
    return { status: "awaiting_provider", message: "Link gerado. O disparo automático será realizado quando o broker de mensageria deste cliente estiver configurado." };
  }
  if (!recipient) return { status: "failed", message: "Link gerado, mas o telefone do responsável está ausente ou inválido." };
  if (testRecipient && recipient !== testRecipient) {
    const message = "Link gerado. O ambiente Twilio está em modo de teste e só permite o número autorizado.";
    await writeLog(input, "awaiting_provider", recipient, message);
    return { status: "awaiting_provider", message };
  }

  const recipientName = input.responsibleName?.trim() || "responsável";
  const body = `Olá, ${recipientName}! Sua Autovistoria Veicular está pronta. Abra o link seguro para iniciar: ${input.inspectionUrl}`;
  let form: URLSearchParams;

  try {
    form = new URLSearchParams({ To: `whatsapp:${recipient}`, From: `whatsapp:${from}` });
    if (contentSid) {
      form.set("ContentSid", contentSid);
      const contentVariables = getContentVariables(input, recipientName);
      if (contentVariables) form.set("ContentVariables", JSON.stringify(contentVariables));
    } else {
      form.set("Body", body);
    }
  } catch (error) {
    const message = error instanceof Error ? error.message : "Não foi possível preparar o template do WhatsApp.";
    await writeLog(input, "failed", recipient, message);
    return { status: "failed", message };
  }

  try {
    const response = await fetch(`https://api.twilio.com/2010-04-01/Accounts/${encodeURIComponent(accountSid)}/Messages.json`, {
      method: "POST",
      headers: {
        Authorization: `Basic ${Buffer.from(`${accountSid}:${authToken}`).toString("base64")}`,
        "Content-Type": "application/x-www-form-urlencoded",
      },
      body: form.toString(),
    });
    const payload = await response.json().catch(() => ({})) as { sid?: string; message?: string; code?: number };
    if (!response.ok) {
      const message = `Link gerado, mas o WhatsApp não foi enviado pela Twilio: ${payload.message || `HTTP ${response.status}`}`;
      await writeLog(input, "failed", recipient, message, undefined, payload.code ? String(payload.code) : String(response.status));
      return { status: "failed", message };
    }
    const message = "Link gerado e enviado por WhatsApp.";
    await writeLog(input, "sent", recipient, message, payload.sid);
    return { status: "sent", message, providerMessageSid: payload.sid };
  } catch (error) {
    const message = "Link gerado, mas não foi possível alcançar o serviço de WhatsApp da Twilio.";
    await writeLog(input, "failed", recipient, message);
    console.error("Erro ao enviar WhatsApp pela Twilio", error);
    return { status: "failed", message };
  }
}
