export type PaymentReceiptPayload = {
  company?: {
    name?: string | null;
    document?: string | null;
    address?: string | null;
    phone?: string | null;
    email?: string | null;
    logoUrl?: string | null;
  } | null;
  client?: {
    name?: string | null;
    companyName?: string | null;
    document?: string | null;
    address?: string | null;
  } | null;
  order?: {
    number?: number | string | null;
    totalAmount?: number | string | null;
  } | null;
  payment?: {
    id?: string | null;
    amount?: number | string | null;
    paymentDate?: string | null;
    method?: string | null;
    notes?: string | null;
  } | null;
  receipt?: {
    issuedAt?: string | null;
    sequence?: number | null;
    paidBefore?: number | null;
    paidAfter?: number | null;
    label?: string | null;
  } | null;
};

type PaymentReceiptHtmlOptions = {
  autoPrint?: boolean;
  autoClose?: boolean;
};

const PAYMENT_METHOD_LABELS: Record<string, string> = {
  pix: "Pix",
  cash: "Dinheiro",
  credit_card: "Cartao de credito",
  debit_card: "Cartao de debito",
  transfer: "Transferencia",
};

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

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

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

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

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

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 "-";
  const date = new Date(value);
  if (!Number.isFinite(date.getTime())) return "-";
  return date.toLocaleDateString("pt-BR");
}

function joinWithAnd(parts: string[]) {
  if (parts.length <= 1) return parts[0] || "";
  if (parts.length === 2) return `${parts[0]} e ${parts[1]}`;
  return `${parts.slice(0, -1).join(", ")} e ${parts[parts.length - 1]}`;
}

function toWordsBelowThousand(value: number) {
  const units = [
    "zero",
    "um",
    "dois",
    "tres",
    "quatro",
    "cinco",
    "seis",
    "sete",
    "oito",
    "nove",
  ];
  const teens = [
    "dez",
    "onze",
    "doze",
    "treze",
    "quatorze",
    "quinze",
    "dezesseis",
    "dezessete",
    "dezoito",
    "dezenove",
  ];
  const tens = [
    "",
    "",
    "vinte",
    "trinta",
    "quarenta",
    "cinquenta",
    "sessenta",
    "setenta",
    "oitenta",
    "noventa",
  ];
  const hundreds = [
    "",
    "cento",
    "duzentos",
    "trezentos",
    "quatrocentos",
    "quinhentos",
    "seiscentos",
    "setecentos",
    "oitocentos",
    "novecentos",
  ];

  if (value === 0) return "zero";
  if (value === 100) return "cem";

  const c = Math.floor(value / 100);
  const d = Math.floor((value % 100) / 10);
  const u = value % 10;
  const result: string[] = [];

  if (c > 0) result.push(hundreds[c]);

  if (d === 1) {
    result.push(teens[u]);
  } else {
    if (d > 1) result.push(tens[d]);
    if (u > 0) result.push(units[u]);
  }

  return joinWithAnd(result);
}

function integerToWords(value: number) {
  const safe = Math.max(0, Math.floor(value));
  if (safe === 0) return "zero";

  const groups: number[] = [];
  let remainder = safe;
  while (remainder > 0) {
    groups.push(remainder % 1000);
    remainder = Math.floor(remainder / 1000);
  }

  const scaleSingular = ["", "mil", "milhao", "bilhao", "trilhao"];
  const scalePlural = ["", "mil", "milhoes", "bilhoes", "trilhoes"];
  const tokens: string[] = [];

  for (let i = groups.length - 1; i >= 0; i -= 1) {
    const group = groups[i];
    if (!group) continue;

    if (i === 0) {
      tokens.push(toWordsBelowThousand(group));
      continue;
    }

    if (i === 1) {
      if (group === 1) {
        tokens.push("mil");
      } else {
        tokens.push(`${toWordsBelowThousand(group)} mil`);
      }
      continue;
    }

    const scale = group === 1 ? scaleSingular[i] : scalePlural[i];
    if (group === 1) {
      tokens.push(`um ${scale}`);
    } else {
      tokens.push(`${toWordsBelowThousand(group)} ${scale}`);
    }
  }

  return joinWithAnd(tokens);
}

function moneyToWords(value: number) {
  const safe = Math.max(0, Number(value) || 0);
  let integer = Math.floor(safe + 1e-9);
  let cents = Math.round((safe - integer) * 100);
  if (cents >= 100) {
    integer += 1;
    cents -= 100;
  }

  const parts: string[] = [];

  if (integer > 0) {
    const integerWords = integerToWords(integer);
    parts.push(`${integerWords} ${integer === 1 ? "real" : "reais"}`);
  }

  if (cents > 0) {
    const centsWords = integerToWords(cents);
    parts.push(`${centsWords} ${cents === 1 ? "centavo" : "centavos"}`);
  }

  if (parts.length === 0) return "zero real";
  return joinWithAnd(parts);
}

function methodLabel(value: string | null | undefined) {
  const normalized = (value || "").trim();
  return PAYMENT_METHOD_LABELS[normalized] || normalized || "Nao informado";
}

export function buildPaymentReceiptFilename(payload: PaymentReceiptPayload) {
  const orderNumber = String(payload.order?.number || "0").trim();
  const clientName =
    payload.client?.companyName?.trim() ||
    payload.client?.name?.trim() ||
    "Cliente";

  const sanitize = (value: string) =>
    value
      .replace(/[\\/:*?"<>|]/g, "")
      .replace(/\s+/g, " ")
      .trim();

  return `Recibo - PED ${sanitize(orderNumber)} - ${sanitize(clientName)}.pdf`;
}

export function buildPaymentReceiptHtml(
  payload: PaymentReceiptPayload,
  options: PaymentReceiptHtmlOptions = {}
) {
  const autoPrint = options.autoPrint ?? true;
  const autoClose = options.autoClose ?? false;

  const companyName = payload.company?.name?.trim() || "Empresa emissora";
  const companyDocument = formatDocument(payload.company?.document) || "-";
  const companyAddress = payload.company?.address?.trim() || "-";
  const companyPhone = payload.company?.phone?.trim() || "-";
  const companyEmail = payload.company?.email?.trim() || "-";
  const companyLogo = payload.company?.logoUrl?.trim() || "";

  const clientName =
    payload.client?.companyName?.trim() ||
    payload.client?.name?.trim() ||
    "Cliente";
  const clientDocument = formatDocument(payload.client?.document) || "-";
  const clientAddress = payload.client?.address?.trim() || "-";

  const amount = toNumber(payload.payment?.amount);
  const orderTotal = toNumber(payload.order?.totalAmount);
  const paidBefore = toNumber(payload.receipt?.paidBefore);
  const paidAfter = toNumber(payload.receipt?.paidAfter);
  const remaining = Math.max(0, orderTotal - paidAfter);
  const isSettled = orderTotal > 0 && remaining <= 0.01;
  const amountWords = moneyToWords(amount);

  const receiptDate = formatDate(
    payload.receipt?.issuedAt || payload.payment?.paymentDate || new Date().toISOString()
  );
  const paymentDate = formatDate(payload.payment?.paymentDate);
  const orderNumber = payload.order?.number ? String(payload.order.number) : "-";
  const sequence = String(payload.receipt?.sequence || "1");
  const receiptBadgeLabel = (payload.receipt?.label || "").trim() || `Parcela ${sequence}`;
  const notes = (payload.payment?.notes || "").trim();
  const paymentMethod = methodLabel(payload.payment?.method);
  const printTitle = `Recibo - PED ${orderNumber} - ${clientName}`;

  const mainText = isSettled
    ? `Recebemos de ${clientName}, inscrito(a) no CPF/CNPJ ${clientDocument}, residente em ${clientAddress}, a importancia de ${formatMoney(amount)} (${amountWords}), referente ao pagamento do Pedido #${orderNumber}, declarando plena, rasa e irrevogavel quitacao do valor total.`
    : `Recebemos de ${clientName}, inscrito(a) no CPF/CNPJ ${clientDocument}, residente em ${clientAddress}, a importancia de ${formatMoney(amount)} (${amountWords}), referente ao pagamento parcial do Pedido #${orderNumber}. O saldo pendente apos este recebimento e de ${formatMoney(remaining)}.`;

  const extraText = notes
    ? `Observacao informada no pagamento: ${notes}.`
    : "Sem observacoes adicionais.";

  const autoPrintScript = autoPrint
    ? `
      window.addEventListener('load', function() {
        window.setTimeout(function() { window.print(); }, 220);
      });
    `
    : "";
  const autoCloseScript = autoClose
    ? `
      window.addEventListener('afterprint', function() {
        window.setTimeout(function() { window.close(); }, 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=Poppins:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
    <style>
      :root {
        --ink: #0f172a;
        --muted: #64748b;
        --line: #d4def2;
        --line-dark: #9fb0d8;
        --brand: #4425a7;
        --brand-2: #0ea5e9;
        --font-body: "Poppins", "Segoe UI", Arial, sans-serif;
        --font-display: "Poppins", "Segoe UI", Arial, sans-serif;
      }
      * { box-sizing: border-box; }
      body {
        margin: 0;
        background: #eef2ff;
        font-family: var(--font-body);
        color: var(--ink);
      }
      .page {
        width: 210mm;
        min-height: 297mm;
        margin: 0 auto;
        background: #fff;
        padding: 12mm;
      }
      .receipt {
        border: 1px solid #c4d0ea;
        background: #fff;
      }
      .header {
        display: grid;
        grid-template-columns: 1fr auto;
        gap: 14px;
        align-items: start;
        padding: 16px 18px;
        border-bottom: 1px solid #bed0f2;
        background: #fff;
        color: #111827;
      }
      .header-main {
        display: flex;
        gap: 12px;
        align-items: center;
      }
      .logo {
        display: flex;
        align-items: center;
        flex-shrink: 0;
      }
      .logo img {
        width: auto;
        height: auto;
        max-width: 130px;
        max-height: 56px;
        object-fit: contain;
        object-position: left center;
      }
      .title {
        margin: 0;
        font-size: 29px;
        line-height: 1.05;
        font-weight: 900;
        letter-spacing: 0.03em;
        text-transform: uppercase;
        font-family: var(--font-display);
      }
      .subtitle {
        margin: 4px 0 0;
        font-size: 11px;
        letter-spacing: 0.05em;
        text-transform: uppercase;
        color: #111827;
        font-family: var(--font-body);
      }
      .badge-block {
        text-align: right;
        display: flex;
        flex-direction: column;
        gap: 6px;
      }
      .badge {
        align-self: flex-end;
        border: 1px solid #cbd5e1;
        background: #fff;
        color: #111827;
        padding: 6px 10px;
        font-size: 10px;
        font-weight: 700;
        letter-spacing: 0.07em;
        text-transform: uppercase;
        font-family: var(--font-display);
      }
      .content {
        position: relative;
        padding: 16px 18px 18px;
      }
      .watermark {
        position: absolute;
        right: 20px;
        top: 54px;
        font-size: 70px;
        font-weight: 900;
        letter-spacing: 0.08em;
        color: rgba(68, 37, 167, 0.06);
        pointer-events: none;
        user-select: none;
      }
      .inline-grid {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 10px;
        margin-bottom: 14px;
      }
      .inline-cell {
        border: 1px solid var(--line);
        background: #f8faff;
        padding: 9px 10px;
        min-height: 62px;
      }
      .cell-label {
        margin: 0;
        font-size: 10px;
        font-weight: 700;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--muted);
        font-family: var(--font-display);
      }
      .cell-value {
        margin: 8px 0 0;
        font-size: 19px;
        line-height: 1.05;
        font-weight: 900;
        color: #0b1222;
        font-family: var(--font-display);
      }
      .section {
        border: 1px solid var(--line);
        margin-top: 10px;
      }
      .section-title {
        margin: 0;
        padding: 8px 10px;
        border-bottom: 1px solid var(--line);
        background: #f3f5ff;
        font-size: 10px;
        font-weight: 800;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: #2f3f73;
        font-family: var(--font-display);
      }
      .section-body {
        padding: 10px;
        font-family: var(--font-body);
      }
      .paragraph {
        margin: 0 0 8px;
        font-size: 12px;
        line-height: 1.7;
        text-align: justify;
      }
      .paragraph:last-child { margin-bottom: 0; }
      .summary-grid {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        border: 1px solid var(--line);
      }
      .summary-item {
        padding: 10px;
        min-height: 60px;
        border-right: 1px solid var(--line);
      }
      .summary-item:last-child { border-right: 0; }
      .summary-label {
        margin: 0;
        font-size: 10px;
        font-weight: 700;
        letter-spacing: 0.07em;
        text-transform: uppercase;
        color: var(--muted);
        font-family: var(--font-display);
      }
      .summary-value {
        margin: 6px 0 0;
        font-size: 17px;
        font-weight: 900;
        font-family: var(--font-display);
      }
      .signatures {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 12px;
        margin-top: 12px;
      }
      .signature-card {
        border: 1px dashed var(--line-dark);
        padding: 10px;
        min-height: 110px;
      }
      .signature-title {
        margin: 0;
        font-size: 10px;
        font-weight: 800;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--muted);
        font-family: var(--font-display);
      }
      .signature-line {
        margin-top: 48px;
        padding-top: 6px;
        border-top: 1px solid var(--line-dark);
        font-size: 12px;
        line-height: 1.45;
        font-family: var(--font-body);
      }
      .issuer-box {
        margin-top: 12px;
        border: 1px solid var(--line);
        background: #fafbff;
        padding: 10px;
        font-size: 12px;
        line-height: 1.65;
        font-family: var(--font-body);
      }
      .footer {
        margin-top: 12px;
        border-top: 1px solid var(--line);
        padding-top: 9px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 10px;
        font-size: 11px;
        color: var(--muted);
        font-family: var(--font-body);
      }
      .status {
        border: 1px solid #9ab2eb;
        background: #eef3ff;
        color: #3548a5;
        font-size: 10px;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        font-weight: 800;
        padding: 5px 9px;
        font-family: var(--font-display);
      }
      @media print {
        @page { size: A4; margin: 10mm; }
        body { background: #fff; }
        .page { width: 100%; min-height: auto; margin: 0; padding: 0; }
      }
    </style>
  </head>
  <body>
    <div class="page">
      <article class="receipt">
        <header class="header">
          <div class="header-main">
            <div class="logo">
              ${companyLogo ? `<img src="${escapeHtml(companyLogo)}" alt="Logo da empresa" />` : ""}
            </div>
            <div>
              <h1 class="title">Recibo de Pagamento</h1>
              <p class="subtitle">${safeText(companyName)}</p>
            </div>
          </div>
          <div class="badge-block">
            <span class="badge">Pedido #${escapeHtml(orderNumber)}</span>
            <span class="badge">${escapeHtml(receiptBadgeLabel)}</span>
          </div>
        </header>

        <div class="content">
          <div class="watermark">RECIBO</div>

          <div class="inline-grid">
            <div class="inline-cell">
              <p class="cell-label">Valor recebido</p>
              <p class="cell-value">${escapeHtml(formatMoney(amount))}</p>
            </div>
            <div class="inline-cell">
              <p class="cell-label">Data do pagamento</p>
              <p class="cell-value">${escapeHtml(paymentDate)}</p>
            </div>
            <div class="inline-cell">
              <p class="cell-label">Forma de pagamento</p>
              <p class="cell-value">${safeText(paymentMethod)}</p>
            </div>
          </div>

          <section class="section">
            <h2 class="section-title">Declaracao de recebimento</h2>
            <div class="section-body">
              <p class="paragraph">${safeText(mainText)}</p>
              <p class="paragraph">${safeText(extraText)}</p>
            </div>
          </section>

          <section class="section">
            <h2 class="section-title">Resumo financeiro do pedido</h2>
            <div class="section-body">
              <div class="summary-grid">
                <div class="summary-item">
                  <p class="summary-label">Total do pedido</p>
                  <p class="summary-value">${escapeHtml(formatMoney(orderTotal))}</p>
                </div>
                <div class="summary-item">
                  <p class="summary-label">Pago antes deste recibo</p>
                  <p class="summary-value">${escapeHtml(formatMoney(paidBefore))}</p>
                </div>
                <div class="summary-item">
                  <p class="summary-label">Saldo apos este recibo</p>
                  <p class="summary-value">${escapeHtml(formatMoney(remaining))}</p>
                </div>
              </div>
            </div>
          </section>

          <div class="signatures">
            <div class="signature-card">
              <p class="signature-title">Recebedor</p>
              <div class="signature-line">
                ${safeText(companyName)}<br/>
                CPF/CNPJ: ${safeText(companyDocument)}
              </div>
            </div>
            <div class="signature-card">
              <p class="signature-title">Pagador</p>
              <div class="signature-line">
                ${safeText(clientName)}<br/>
                CPF/CNPJ: ${safeText(clientDocument)}
              </div>
            </div>
          </div>

          <div class="issuer-box">
            <strong>Dados da empresa emissora:</strong><br/>
            ${safeText(companyName)} · CPF/CNPJ ${safeText(companyDocument)}<br/>
            Endereco: ${safeText(companyAddress)}<br/>
            Contato: ${safeText(companyPhone)} · ${safeText(companyEmail)}
          </div>

          <div class="footer">
            <span>Local/Data de emissao: ${escapeHtml(receiptDate)}</span>
            <span class="status">${isSettled ? "Quitacao total" : "Pagamento parcial"}</span>
          </div>
        </div>
      </article>
    </div>

    <script>
      ${autoPrintScript}
      ${autoCloseScript}
    </script>
  </body>
</html>`;
}
