import QRCode from "qrcode";
import { formatDateBr } from "@/utils/formatters";

export type OrderLabelPayload = {
  company?: {
    name?: string | null;
    logoUrl?: string | null;
    phone?: string | null;
    whatsapp?: string | null;
    address?: string | null;
    cnpj?: string | null;
  } | null;
  order: {
    id: string;
    number?: number | string | null;
    createdAt?: string | null;
    totalAmount?: number | string | null;
    paidAmount?: number | string | null;
    financialStatus?: string | null;
    status?: string | null;
    notes?: string | null;
  };
  client?: {
    name?: string | null;
    companyName?: string | null;
    phone?: string | null;
    whatsapp?: string | null;
    document?: string | null;
    addressStreet?: string | null;
    addressNumber?: string | null;
    addressComplement?: string | null;
    addressNeighborhood?: string | null;
    addressCity?: string | null;
    addressState?: string | null;
    addressZip?: string | null;
    notes?: string | null;
  } | null;
  quote?: {
    notes?: string | null;
    deliveryDate?: string | null;
  } | null;
};

type OrderLabelHtmlOptions = {
  autoPrint?: boolean;
  autoClose?: boolean;
  variant?: "sheet" | "thermal";
  copies?: number;
};

function escapeHtml(value: string) {
  return value
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;");
}

function toNumber(value: number | string | null | undefined) {
  const parsed = Number(value);
  return Number.isFinite(parsed) ? parsed : 0;
}

function formatMoney(value: number | string | null | undefined) {
  return new Intl.NumberFormat("pt-BR", {
    style: "currency",
    currency: "BRL",
  }).format(toNumber(value));
}

function formatDate(value: string | null | undefined) {
  if (!value) return "-";
  return formatDateBr(value) || "-";
}

function onlyDigits(value: string | null | undefined) {
  return (value || "").replace(/\D/g, "");
}

function formatPhone(value: string | null | undefined) {
  const digits = onlyDigits(value);
  if (digits.length === 11) return digits.replace(/(\d{2})(\d{5})(\d{4})/, "($1) $2-$3");
  if (digits.length === 10) return digits.replace(/(\d{2})(\d{4})(\d{4})/, "($1) $2-$3");
  return (value || "").trim();
}

function safeText(value: string | null | undefined, fallback = "-") {
  const normalized = (value || "").trim();
  return normalized ? escapeHtml(normalized) : fallback;
}

function normalizeText(value: string | null | undefined) {
  return (value || "").replace(/\s+/g, " ").trim();
}

function firstNonEmpty(...values: Array<string | null | undefined>) {
  for (const value of values) {
    const normalized = normalizeText(value);
    if (normalized) return normalized;
  }
  return "";
}

function buildAddress(client?: OrderLabelPayload["client"]) {
  if (!client) return "";
  const line1 = [client.addressStreet, client.addressNumber, client.addressComplement]
    .map((value) => normalizeText(value))
    .filter(Boolean)
    .join(", ");
  const line2 = [client.addressNeighborhood, client.addressCity, client.addressState]
    .map((value) => normalizeText(value))
    .filter(Boolean)
    .join(" - ");
  const zip = normalizeText(client.addressZip);
  return [line1, line2, zip ? `CEP ${zip}` : ""].filter(Boolean).join(" | ");
}

function safeFileNamePart(value: string) {
  return value
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .replace(/[^a-zA-Z0-9_-]+/g, "-")
    .replace(/^-+|-+$/g, "")
    .toLowerCase();
}

function financialStatusLabel(value: string | null | undefined) {
  const normalized = String(value || "").toLowerCase();
  if (normalized === "paid") return "Pago";
  if (normalized === "partially_paid") return "Parcial";
  if (normalized === "unpaid") return "Nao pago";
  return "Aberto";
}

function paymentSummary(payload: OrderLabelPayload) {
  const total = toNumber(payload.order.totalAmount);
  const paid = toNumber(payload.order.paidAmount);
  if (total <= 0) return financialStatusLabel(payload.order.financialStatus);
  const percent = Math.max(0, Math.min(100, Math.round((paid / total) * 100)));
  return `${percent}% pago - ${financialStatusLabel(payload.order.financialStatus)}`;
}

function buildPrintTitle(payload: OrderLabelPayload) {
  const orderNumber = String(payload.order.number || payload.order.id.slice(0, 8)).trim();
  const clientName = firstNonEmpty(
    payload.client?.companyName,
    payload.client?.name,
    "cliente"
  );
  return `Etiqueta do Pedido ${orderNumber} - ${clientName}`;
}

export function buildQrText(payload: OrderLabelPayload) {
  const orderNumber = String(payload.order.number || payload.order.id.slice(0, 8)).trim();
  const clientName = firstNonEmpty(payload.client?.companyName, payload.client?.name, "Cliente");
  const total = formatMoney(payload.order.totalAmount);
  const payment = paymentSummary(payload);
  const phone = firstNonEmpty(formatPhone(payload.client?.whatsapp), formatPhone(payload.client?.phone));
  return [
    `Pedido #${orderNumber}`,
    `Cliente: ${clientName}`,
    `Telefone: ${phone || "-"}`,
    `Total: ${total}`,
    `Pagamento: ${payment}`,
  ].join("\n");
}

function buildLabelCardHtml(params: {
  payload: OrderLabelPayload;
  qrCodeDataUrl: string;
  variant: "sheet" | "thermal";
}) {
  const { payload, qrCodeDataUrl, variant } = params;
  const companyName = firstNonEmpty(payload.company?.name, "Empresa");
  const clientPrimaryName = firstNonEmpty(payload.client?.companyName, payload.client?.name, "Cliente");
  const clientSecondaryName =
    payload.client?.companyName && payload.client?.name && payload.client.name !== payload.client.companyName
      ? normalizeText(payload.client.name)
      : normalizeText(payload.client?.document);
  const phone = firstNonEmpty(
    formatPhone(payload.client?.whatsapp),
    formatPhone(payload.client?.phone),
    formatPhone(payload.company?.whatsapp),
    formatPhone(payload.company?.phone)
  );
  const address = buildAddress(payload.client);
  const observations = firstNonEmpty(
    payload.order.notes,
    payload.quote?.notes,
    payload.client?.notes,
    "Sem observacoes"
  );
  const orderNumber = String(payload.order.number || payload.order.id.slice(0, 8)).trim();
  const orderDate = formatDate(payload.order.createdAt);
  const payment = paymentSummary(payload);
  const totalText = formatMoney(payload.order.totalAmount);
  const logoUrl = normalizeText(payload.company?.logoUrl);
  const compact = variant === "thermal";

  return `
    <article class="label ${compact ? "label-thermal" : ""}">
      <div class="strip-brand">
        <span>${escapeHtml(companyName)}</span>
      </div>
      <div class="pedido-strip">
        <span>Pedido</span>
      </div>
      <div class="content">
        <div class="content-top">
          <div class="qr-hero">
            <img src="${qrCodeDataUrl}" alt="QR Code do pedido" />
          </div>
          <div class="content-top-copy">
            <div class="order-kicker">Pedido #${safeText(orderNumber)}</div>
            <div class="company-kicker">${safeText(companyName)}</div>
          </div>
        </div>

        <div class="box">
          <div class="box-label">Nome</div>
          <p class="name-main">${safeText(clientPrimaryName)}</p>
          <div class="name-sub">${safeText(clientSecondaryName, "")}</div>
        </div>

        <div class="line-row">
          <div class="line-title">Telefone</div>
          <div class="line-value">${safeText(phone)}</div>
        </div>

        <div class="line-row">
          <div class="line-title">Endereco</div>
          <div class="line-value multi">${safeText(address)}</div>
        </div>

        <div class="line-row line-row-obs">
          <div class="line-title">Obs.</div>
          <div class="line-value multi">${safeText(observations)}</div>
        </div>

        <div class="footer-row">
          <div class="payment-flow">
            <span class="payment-label">Pagamento</span>
            <span class="payment-value">${safeText(payment)}</span>
          </div>
          <div class="payment-flow">
            <span class="payment-label">Total</span>
            <span class="payment-value">${safeText(totalText)}</span>
          </div>
          <div class="payment-flow">
            <span class="payment-label">Data</span>
            <span class="payment-value">${safeText(orderDate)}</span>
          </div>
        </div>
      </div>
      <div class="strip-side">
        <div class="side-order">#${safeText(orderNumber)}</div>
        ${
          logoUrl
            ? `<img src="${escapeHtml(logoUrl)}" alt="Logo da empresa" class="side-logo" />`
            : `<div class="side-logo-text">${safeText(companyName)}</div>`
        }
      </div>
    </article>
  `;
}

export async function buildOrderLabelHtml(
  payload: OrderLabelPayload,
  options: OrderLabelHtmlOptions = {}
) {
  const autoPrint = options.autoPrint ?? false;
  const autoClose = options.autoClose ?? false;
  const variant = options.variant ?? "sheet";
  const copies = Math.max(1, options.copies ?? (variant === "sheet" ? 8 : 1));
  const printTitle = buildPrintTitle(payload);
  const qrCodeDataUrl = await QRCode.toDataURL(buildQrText(payload), {
    margin: 0,
    width: variant === "sheet" ? 160 : 140,
    color: {
      dark: "#4425A7",
      light: "#0000",
    },
  });
  const labelsMarkup = Array.from({ length: copies }, () =>
    buildLabelCardHtml({ payload, qrCodeDataUrl, variant })
  ).join("");

  const autoPrintScript = autoPrint
    ? `
      window.addEventListener("load", function() {
        setTimeout(function() {
          window.focus();
          window.print();
          ${autoClose ? "setTimeout(function() { window.close(); }, 180);" : ""}
        }, 120);
      });
    `
    : "";

  return `<!doctype html>
<html lang="pt-BR">
  <head>
    <meta charset="utf-8" />
    <title>${escapeHtml(printTitle)}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
    <style>
      :root {
        --brand: #4425a7;
        --brand-strong: #2e176d;
        --brand-soft: #efeaff;
        --ink: #1d1d1f;
        --muted: #5f6675;
        --line: #cfc8ea;
        --line-strong: #bfb4ee;
        --paper: #ffffff;
        --surface: #f4f1ff;
      }
      * { box-sizing: border-box; }
      body {
        margin: 0;
        background: #ececf8;
        font-family: "Montserrat", Arial, sans-serif;
        color: var(--ink);
      }
      .page {
        padding: 8mm;
      }
      .sheet-grid {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 3mm;
        width: 100%;
      }
      .sheet-grid .label {
        min-height: 65.5mm;
      }
      .thermal-wrap {
        width: 100mm;
        margin: 0 auto;
      }
      .label {
        display: grid;
        grid-template-columns: 7mm 9mm minmax(0, 1fr) 16mm;
        background: var(--paper);
        border: 1.4px solid var(--brand-strong);
        overflow: hidden;
        break-inside: avoid;
      }
      .strip-brand {
        background:
          linear-gradient(180deg, rgba(255,255,255,0.08), rgba(255,255,255,0) 30%),
          var(--brand);
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 1.2mm 0;
      }
      .strip-brand span {
        writing-mode: vertical-rl;
        transform: rotate(180deg);
        font-size: 2.4mm;
        font-weight: 700;
        letter-spacing: 0.08em;
        text-transform: uppercase;
      }
      .pedido-strip {
        display: flex;
        align-items: center;
        justify-content: center;
        background: #ececf0;
        border-right: 1px solid var(--line);
      }
      .pedido-strip span {
        writing-mode: vertical-rl;
        transform: rotate(180deg);
        color: var(--brand);
        font-size: 4.8mm;
        font-weight: 700;
        letter-spacing: 0.2em;
        text-transform: uppercase;
      }
      .content {
        padding: 2.8mm 3mm 2.6mm;
      }
      .content-top {
        display: grid;
        grid-template-columns: 22mm minmax(0, 1fr);
        gap: 3mm;
        align-items: center;
        margin-bottom: 2.2mm;
      }
      .qr-hero {
        width: 22mm;
        height: 22mm;
        border: 1px solid rgba(68,37,167,0.18);
        background: #fff;
        padding: 0.9mm;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      .qr-hero img {
        width: 100%;
        height: 100%;
        object-fit: contain;
      }
      .content-top-copy {
        min-width: 0;
      }
      .order-kicker {
        font-size: 2.6mm;
        font-weight: 800;
        letter-spacing: 0.12em;
        text-transform: uppercase;
        color: var(--brand);
      }
      .company-kicker {
        margin-top: 0.9mm;
        font-size: 2.35mm;
        font-weight: 600;
        color: var(--muted);
      }
      .box {
        border: 0;
        border-bottom: 1.4px solid var(--line-strong);
        background: transparent;
        min-height: 14.2mm;
        padding: 0 0 1.6mm;
        margin-bottom: 2.5mm;
      }
      .box-label {
        color: var(--brand);
        font-size: 2.4mm;
        font-weight: 700;
        line-height: 1;
        margin-bottom: 0.8mm;
        text-transform: uppercase;
        letter-spacing: 0.1em;
      }
      .name-main {
        margin: 0;
        font-size: 6.2mm;
        font-weight: 800;
        line-height: 1.05;
        color: var(--ink);
      }
      .name-sub {
        margin-top: 0.9mm;
        min-height: 2.8mm;
        font-size: 2.35mm;
        color: #3f4553;
      }
      .line-row {
        display: grid;
        grid-template-columns: 17mm 1fr;
        gap: 2.1mm;
        align-items: start;
        border-bottom: 1px solid var(--line);
        padding-bottom: 1.1mm;
        margin-bottom: 2mm;
      }
      .line-title {
        color: var(--brand);
        font-size: 3.6mm;
        font-weight: 700;
        line-height: 1.1;
      }
      .line-value {
        font-size: 2.75mm;
        line-height: 1.38;
        min-height: 4.1mm;
      }
      .line-value.multi {
        min-height: 7.2mm;
      }
      .line-row-obs {
        margin-bottom: 1.8mm;
      }
      .footer-row {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 1.8mm;
        margin-top: 0.4mm;
      }
      .payment-flow {
        min-height: 8.5mm;
        padding: 0.4mm 0.6mm 0.4mm 0;
      }
      .payment-flow:not(:last-child) {
        border-right: 1px solid var(--line);
      }
      .payment-label {
        display: block;
        font-size: 2.15mm;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.08em;
        color: var(--brand);
      }
      .payment-value {
        display: block;
        margin-top: 0.8mm;
        font-size: 2.95mm;
        line-height: 1.25;
        color: var(--brand-strong);
        font-weight: 700;
      }
      .strip-side {
        border-left: 1px solid var(--line);
        background: linear-gradient(180deg, rgba(68,37,167,0.06), rgba(68,37,167,0.12));
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 2.3mm;
        padding: 1.6mm 1mm;
      }
      .side-order {
        writing-mode: vertical-rl;
        transform: rotate(180deg);
        font-size: 2.45mm;
        font-weight: 700;
        color: var(--brand);
        text-transform: uppercase;
        letter-spacing: 0.1em;
      }
      .side-logo {
        max-width: 100%;
        max-height: 11mm;
        object-fit: contain;
      }
      .side-logo-text {
        text-align: center;
        font-size: 2.1mm;
        font-weight: 700;
        color: var(--brand-strong);
      }
      .label-thermal {
        width: 100mm;
        min-height: auto;
        grid-template-columns: 7mm 10mm minmax(0, 1fr) 16mm;
      }
      .label-thermal .content {
        padding: 2.8mm 3.1mm 2.6mm;
      }
      .label-thermal .content-top {
        grid-template-columns: 20mm minmax(0, 1fr);
        gap: 2.5mm;
      }
      .label-thermal .qr-hero {
        width: 20mm;
        height: 20mm;
      }
      .label-thermal .name-main {
        font-size: 5.8mm;
      }
      .label-thermal .line-row {
        grid-template-columns: 17mm 1fr;
      }
      @media print {
        @page { size: ${variant === "thermal" ? "100mm auto" : "A4 portrait"}; margin: ${variant === "thermal" ? "4mm" : "8mm"}; }
        body { background: #fff; }
        .page { padding: 0; }
        .label { box-shadow: none; }
      }
    </style>
  </head>
  <body>
    <div class="page">
      ${
        variant === "sheet"
          ? `<section class="sheet-grid">${labelsMarkup}</section>`
          : `<section class="thermal-wrap">${labelsMarkup}</section>`
      }
    </div>
    <script>
      ${autoPrintScript}
    </script>
  </body>
</html>`;
}

export async function printOrderLabel(
  payload: OrderLabelPayload,
  options: Pick<OrderLabelHtmlOptions, "variant" | "copies"> = {}
) {
  const iframe = document.createElement("iframe");
  iframe.setAttribute("aria-hidden", "true");
  iframe.style.position = "fixed";
  iframe.style.right = "0";
  iframe.style.bottom = "0";
  iframe.style.width = "0";
  iframe.style.height = "0";
  iframe.style.border = "0";
  iframe.style.opacity = "0";
  iframe.style.pointerEvents = "none";

  const cleanup = () => {
    iframe.onload = null;
    if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
  };

  iframe.onload = () => {
    const frameWindow = iframe.contentWindow;
    if (!frameWindow) {
      cleanup();
      return;
    }
    const onAfterPrint = () => {
      frameWindow.removeEventListener("afterprint", onAfterPrint);
      cleanup();
    };
    frameWindow.addEventListener("afterprint", onAfterPrint);
    window.setTimeout(() => {
      frameWindow.focus();
      frameWindow.print();
    }, 120);
    window.setTimeout(cleanup, 15000);
  };

  iframe.srcdoc = await buildOrderLabelHtml(payload, {
    autoPrint: false,
    autoClose: false,
    variant: options.variant ?? "sheet",
    copies: options.copies,
  });
  document.body.appendChild(iframe);
}

export async function printOrderThermalLabel(payload: OrderLabelPayload) {
  return printOrderLabel(payload, { variant: "thermal", copies: 1 });
}

export function buildOrderLabelFilename(payload: OrderLabelPayload, variant: "sheet" | "thermal" = "sheet") {
  const orderNumber = String(payload.order.number || payload.order.id.slice(0, 8)).trim();
  const clientName = firstNonEmpty(payload.client?.companyName, payload.client?.name, "cliente");
  return `${variant === "thermal" ? "etiqueta-termica" : "etiqueta-pedido"}-${safeFileNamePart(orderNumber)}-${safeFileNamePart(clientName)}.html`;
}
