import { chatWithTools, type ChatTableReport } from "../mistral";
import { sendText, sendMedia, sendPresence } from "../evolution";
import { extractAndRenderTables, parseMarkdownTable, renderTableToImage } from "../render-table";
import { getSession } from "../sessions";
import { handleInteractiveTextReply } from "./interactive";

const BOT_PREFIX = /^BOT\s+/i;
const BOT_MENTION_PREFIX = /^@\S+\s*/i;
const CONFIRMATION_PHRASES = /^(ok|si|sí|confirmar|dale|confirmo|listo|yes|1)\s*$/i;
const HELP_PHRASES = /^(menu|ayuda|help|comandos|comando|opciones)\s*$/i;

const HELP_TEXT = `*BOT Ruiz — Comandos disponibles*

📌 Para hablar conmigo escribí "BOT" antes del mensaje o mencioname con @BOT.

*DEUDA Y SALDOS*
• *deuda de servicios* — Muestra el total que el inquilino adeuda por cada servicio (ABL, AYSA, Destapaciones).
• *deuda de servicios mensual* — Desglosa la deuda de servicios mes a mes, para ver qué períodos tienen saldo pendiente.
• *deuda de alquiler* — Resumen de la deuda total de alquiler: cuotas impagas, diferencia de IPC y penalidades por mora.
• *cuotas impagas* — Lista los meses de alquiler que siguen abiertos, cuánto se espera y cuántos días de mora llevan.

*DETALLE POR SERVICIO*
• *detalle ABL* — Historial completo del servicio ABL: lo facturado, lo que corresponde pagar, lo pagado y la deuda restante. Funciona con cualquier servicio (ABL, AYSA, Destapaciones).

*REPORTES (se envían como imagen)*
• *reporte servicios* — Tabla con la deuda total por cada servicio.
• *reporte alquiler* — Tabla con el desglose de deuda de alquiler (impaga, IPC, penalidades).
• *reporte cuotas impagas* — Tabla de meses de alquiler pendientes con días de mora.
• *reporte mensual completo* — Auditoría completa de alquiler: esperado, acordado, pagado, diferencia y penalidad.
• *reporte pagos alquiler* — Historial de pagos de alquiler registrados (fecha, monto, notas, comprobante).
• *reporte pagos servicios* — Historial de pagos de servicios registrados (fecha, monto, modo, comprobante).
• *reporte distribución servicios* — Muestra cómo se distribuyeron los pagos de servicios entre cada servicio.

*REGISTRAR PAGOS*
• *registrar pago alquiler* — Inicia el flujo para registrar un pago de alquiler (monto, período, notas).
• *registrar pago servicio* — Inicia el flujo para registrar un pago de servicio (monto, servicio destino).
• *enviá una foto* de un comprobante bancario y registro el pago automáticamente usando OCR.

*EXPORTAR DATOS*
• *exportar CSV deuda servicios* — Descarga un spreadsheet con la deuda detallada por período y servicio.
• *exportar CSV alquiler* — Descarga un spreadsheet con todos los períodos de alquiler y sus estados.
• *exportar CSV completo* — Descarga un archivo con deuda de alquiler y servicios combinados.

*OTROS*
• *próximo ajuste IPC* — Muestra cuándo es el próximo ajuste trimestral por IPC y cuánto va a quedar el alquiler.
• *ok / cancelar* — Para confirmar o cancelar acciones pendientes (registrar pagos, etc.).`;

function mdToWhatsApp(text: string): string {
  return text
    .replace(/\*\*(.+?)\*\*/g, "$1")
    .replace(/__(.+?)__/g, "$1")
    .replace(/^#{1,6}\s+/gm, "");
}

export function isBotCommand(text: string): boolean {
  const t = text.trim();
  return BOT_PREFIX.test(t) || BOT_MENTION_PREFIX.test(t);
}

export function isConfirmationCommand(text: string): boolean {
  const query = text.replace(BOT_PREFIX, "").replace(BOT_MENTION_PREFIX, "").trim();
  return CONFIRMATION_PHRASES.test(query);
}

/**
 * Build a caption from a table report's markdown data.
 * - 2-column summary tables: formatted as a list (label: value)
 * - Multi-column tables: just the title (image has the detail)
 */
function buildCaptionFromTable(report: ChatTableReport): string {
  const { table } = parseMarkdownTable(report.markdown);
  if (!table) return report.title;

  // For 2-column summary tables, show all data in the caption
  if (table.headers.length === 2) {
    const lines: string[] = [];
    for (const row of table.rows) {
      const label = row[0]?.trim();
      const value = row[1]?.trim();
      if (label && value) {
        lines.push(`${label}: ${value}`);
      }
    }
    return lines.join("\n");
  }

  // For multi-column tables (detalle, historial, etc.), just use title
  // The image has all the detail
  return "";
}

/**
 * Build a full caption with title + table data.
 */
function buildFullCaption(report: ChatTableReport): string {
  const hoy = new Date().toLocaleDateString("es-AR");
  const tableCaption = buildCaptionFromTable(report);
  if (tableCaption) {
    return `${report.title} al ${hoy}:\n\n${tableCaption}`;
  }
  return `${report.title} — ${hoy}`;
}

async function sendRenderedTableReport(
  groupJid: string,
  report: ChatTableReport,
  caption?: string
) {
  const { table, rawTable } = parseMarkdownTable(report.markdown);
  const fallbackText = [report.title, rawTable || report.markdown].filter(Boolean).join("\n\n");

  if (!table) {
    await sendText(groupJid, mdToWhatsApp(caption ?? fallbackText));
    return;
  }

  const image = await renderTableToImage(table, {
    watermarkSubtitle: report.watermarkTitle ?? report.title,
  });

  if (!image) {
    await sendText(groupJid, mdToWhatsApp(caption ?? fallbackText));
    return;
  }

  const base64 = image.toString("base64");
  const dataUri = `data:image/png;base64,${base64}`;
  const result = await sendMedia(
    groupJid,
    dataUri,
    "image/png",
    caption ? mdToWhatsApp(caption) : undefined,
    "image",
    "tabla.png"
  );

  if (!result) {
    await sendText(groupJid, mdToWhatsApp(caption ?? fallbackText));
  }
}

async function sendImageWithCaption(
  groupJid: string,
  image: Buffer,
  caption: string
) {
  const base64 = image.toString("base64");
  const dataUri = `data:image/png;base64,${base64}`;
  const result = await sendMedia(
    groupJid,
    dataUri,
    "image/png",
    mdToWhatsApp(caption),
    "image",
    "tabla.png"
  );

  if (!result) {
    console.warn("[TABLE] sendMedia failed, falling back to text");
    await sendText(groupJid, mdToWhatsApp(caption));
  }
}

export async function handleTextMessage(
  groupJid: string,
  senderPhone: string,
  senderName: string,
  text: string
) {
  const query = text.replace(BOT_PREFIX, "").replace(BOT_MENTION_PREFIX, "").trim();
  if (!query) {
    await sendPresence(groupJid, "composing");
    try { await sendText(groupJid, HELP_TEXT); } finally { await sendPresence(groupJid, "paused"); }
    return;
  }

  if (HELP_PHRASES.test(query)) {
    await sendPresence(groupJid, "composing");
    try { await sendText(groupJid, HELP_TEXT); } finally { await sendPresence(groupJid, "paused"); }
    return;
  }

  if (CONFIRMATION_PHRASES.test(query)) {
    const { state } = await getSession(senderPhone);
    if (state !== "idle") {
      const result = await handleInteractiveTextReply(groupJid, senderPhone, senderName, query);
      if (result === "handled") return;
    }
  }

  let presenceInterval: ReturnType<typeof setInterval> | null = null;

  try {
    await sendPresence(groupJid, "composing");
    presenceInterval = setInterval(() => {
      void sendPresence(groupJid, "composing");
    }, 4000);

    const contextualQuery = `${senderName} pregunta: ${query}`;
    const reply = await chatWithTools(contextualQuery);

    console.log(
      "[BOT] reply length:",
      reply.text.length,
      "attachments:",
      reply.attachments.length,
      "tables:",
      reply.tableReports.length,
      "preview:",
      reply.text.substring(0, 200)
    );

    if (reply.tableReports.length > 0) {
      // Only send the FIRST table report — 1 query = 1 message
      const report = reply.tableReports[0];
      const caption = buildFullCaption(report);
      await sendRenderedTableReport(groupJid, report, caption);
    } else if (reply.text.trim()) {
      // No table reports — try to extract inline markdown tables
      const segments = await extractAndRenderTables(reply.text);
      console.log("[TABLE] segments:", segments.length, "hasImage:", segments.some(s => s.image !== null));

      let pendingText = "";

      for (const seg of segments) {
        if (seg.image) {
          const caption = pendingText.trim() || seg.text || "";
          await sendImageWithCaption(groupJid, seg.image, caption);
          pendingText = "";
        } else if (seg.text) {
          pendingText += (pendingText ? "\n\n" : "") + seg.text;
        }
      }

      if (pendingText.trim()) {
        await sendText(groupJid, mdToWhatsApp(pendingText));
      }
    }

    for (const attachment of reply.attachments) {
      console.log("[ATTACHMENT] sending", attachment.filename, attachment.url);
      const result = await sendMedia(
        groupJid,
        attachment.url,
        attachment.mimetype,
        undefined,
        "document",
        attachment.filename
      );

      if (!result) {
        console.warn("[ATTACHMENT] sendMedia failed for", attachment.filename);
        await sendText(
          groupJid,
          `No pude adjuntar ${attachment.filename} por WhatsApp, pero podés descargarlo acá: ${attachment.url}`
        );
      }
    }
  } catch (err) {
    console.error("handleTextMessage error:", err);
    await sendText(groupJid, "Error procesando tu consulta: " + String(err));
  } finally {
    if (presenceInterval) clearInterval(presenceInterval);
    await sendPresence(groupJid, "paused");
  }
}
