/* ============================================================
 * Copyright (c) 2026 RAVAPI Soluções. www.ravapi.com
 * Fase 4 — layout A4 em duas vias
 *
 * Uma função pura: recebe o documento selado, devolve HTML. Nada de
 * banco, nada de rede. O mesmo HTML serve para a tela e para o PDF, o
 * que elimina a divergência clássica entre o que o usuário vê e o que
 * sai na impressora.
 * ============================================================ */

import { valorPorExtenso, formatarBRL } from '../core/extenso.ts';

export type Direcao = 'RECEBIMENTO' | 'PAGAMENTO';

export interface ParteImpressa {
  nome: string;
  documento: string;
  tipo: 'PF' | 'PJ';
  endereco?: string | null;
}

export interface ReciboImpresso {
  direcao: Direcao;
  numeroFormatado: string;
  codigoVerificacao: string;
  valorCentavos: number;
  valorExtenso: string;
  descricao: string;
  formaPagamento: string;
  dataPagamento: string;           // YYYY-MM-DD
  localPagamento: string;
  referencia?: string | null;
  /** Sempre a empresa: é o talão dela, nas duas direções. */
  emitente: ParteImpressa & {
    nomeFantasia?: string | null;
    inscricaoMunicipal?: string | null;
    telefone?: string | null;
    email?: string | null;
    avisoRodape: string;
  };
  credor: ParteImpressa;
  devedor: ParteImpressa;
  signatarioNome?: string | null;
  signatarioDocumento?: string | null;
  /** data URL ou caminho embutível */
  logoDataUrl?: string | null;
  assinaturaDataUrl?: string | null;
  qrSvg: string;
  urlVerificacao: string;
  cancelamento?: { motivo: string; canceladoEm: string } | null;
}

/**
 * Escapa tudo que vem do usuário. A descrição do recibo é texto livre e
 * vira HTML que depois vira PDF — sem escapar, um "<script>" ou um
 * "</div>" na descrição quebraria o documento ou pior.
 */
export function escapar(texto: string): string {
  return String(texto)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

const MESES = ['janeiro','fevereiro','março','abril','maio','junho',
  'julho','agosto','setembro','outubro','novembro','dezembro'];

export function dataPorExtenso(iso: string): string {
  const [a, m, d] = iso.split('-').map(Number);
  return `${String(d).padStart(2, '0')} de ${MESES[m - 1]} de ${a}`;
}
export function dataCurta(iso: string): string {
  const [a, m, d] = iso.split('-');
  return `${d}/${m}/${a}`;
}

/** PJ dá quitação no plural, PF no singular. */
export function verboDeQuitacao(credor: ParteImpressa): 'Recebemos' | 'Recebi' {
  return credor.tipo === 'PJ' ? 'Recebemos' : 'Recebi';
}

export function tituloDoDocumento(direcao: Direcao): string {
  return direcao === 'RECEBIMENTO' ? 'RECIBO DE RECEBIMENTO' : 'RECIBO DE PAGAMENTO';
}

export function rotuloDoValor(direcao: Direcao): string {
  return direcao === 'RECEBIMENTO' ? 'Valor recebido' : 'Valor pago';
}

/**
 * Rótulo das vias. "Pagador" e "recebedor" estão corretos nas duas
 * direções sem nenhum condicional — o que muda é quem é cada um.
 * A primeira via fica com quem pagou, porque é quem precisa da prova.
 */
export function viasDoDocumento(r: ReciboImpresso) {
  return [
    { rotulo: 'Via do pagador', quem: r.devedor.nome },
    { rotulo: 'Via do recebedor', quem: r.credor.nome },
  ];
}

/** O comprimento a partir do qual a descrição arrisca estourar a meia folha. */
export const DESCRICAO_CONFORTAVEL = 260;

/**
 * Teto da descrição. Acima disto a via estoura mesmo em modo compacto.
 * Mora aqui, junto do layout, porque o limite existe por causa do papel —
 * não é regra de negócio, é o tamanho da meia folha A4.
 */
export const DESCRICAO_MAXIMA = 300;

export function descricaoLonga(descricao: string): boolean {
  return descricao.length > DESCRICAO_CONFORTAVEL;
}

function via(r: ReciboImpresso, indice: number): string {
  const v = viasDoDocumento(r)[indice];
  const e = r.emitente;
  const verbo = verboDeQuitacao(r.credor);
  const compacta = descricaoLonga(r.descricao);

  const logo = r.logoDataUrl
    ? `<img class="logo" src="${escapar(r.logoDataUrl)}" alt="">`
    : `<div class="logo logo-vazio">${escapar((e.nomeFantasia ?? e.nome).slice(0, 28))}</div>`;

  const assinatura = r.assinaturaDataUrl
    ? `<img class="rubrica" src="${escapar(r.assinaturaDataUrl)}" alt="">`
    : '';

  const linhaReferencia = r.referencia
    ? `<div><span class="k">Referência</span><span class="v">${escapar(r.referencia)}</span></div>`
    : '';

  const tarja = r.cancelamento
    ? `<div class="tarja" aria-label="documento cancelado">CANCELADO</div>`
    : '';

  const avisoCancelamento = r.cancelamento
    ? `<div class="cancel-nota">Cancelado em ${escapar(dataCurta(r.cancelamento.canceladoEm))}
         — ${escapar(r.cancelamento.motivo)}</div>`
    : '';

  return `
  <section class="via${compacta ? ' via-compacta' : ''}">
    ${tarja}
    <div class="flag">
      <b>${escapar(v.rotulo)}</b>
      <span>${escapar(v.quem)}</span>
    </div>

    <header class="cabecalho">
      ${logo}
      <div class="emitente">
        <h1>${escapar(e.nomeFantasia ?? e.nome)}</h1>
        <p>${escapar(e.nome)} — ${escapar(e.documento)}${
          e.inscricaoMunicipal ? ` · IM ${escapar(e.inscricaoMunicipal)}` : ''}</p>
        <p>${escapar(e.endereco ?? '')}</p>
        <p>${[e.telefone, e.email].filter((v): v is string => Boolean(v)).map(escapar).join(' · ')}</p>
      </div>
      <div class="carimbo">
        <div class="especie">${escapar(tituloDoDocumento(r.direcao))}</div>
        <div class="numero">${escapar(r.numeroFormatado)}</div>
      </div>
    </header>

    <div class="importancia">
      <span class="rotulo">${escapar(rotuloDoValor(r.direcao))}</span>
      <span class="cifra">${escapar(formatarBRL(r.valorCentavos))}</span>
    </div>

    <p class="corpo">
      ${verbo} de <strong>${escapar(r.devedor.nome)}</strong>,
      inscrito sob o nº ${escapar(r.devedor.documento)},
      a importância de <strong>${escapar(r.valorExtenso)}</strong>,
      referente a ${escapar(r.descricao)},
      dando plena e geral quitação do valor ora recebido.
    </p>

    <div class="detalhes">
      <div><span class="k">Forma de pagamento</span><span class="v">${escapar(r.formaPagamento)}</span></div>
      <div><span class="k">Data do pagamento</span><span class="v">${escapar(dataCurta(r.dataPagamento))}</span></div>
      <div><span class="k">Local</span><span class="v">${escapar(r.localPagamento)}</span></div>
      ${linhaReferencia}
    </div>

    <footer class="rodape">
      <div class="assinatura">
        <div class="linha">${assinatura}</div>
        <div class="quem">
          <b>${escapar(r.signatarioNome ?? r.credor.nome)}</b>
          ${escapar(r.credor.nome)}${r.credor.documento ? ` — ${escapar(r.credor.documento)}` : ''}
          <span class="papel">quem recebeu o valor e dá a quitação</span>
          <span class="lugar">${escapar(r.localPagamento)}, ${escapar(dataPorExtenso(r.dataPagamento))}</span>
        </div>
      </div>
      <div class="verificacao">
        ${r.qrSvg}
        <div class="codigo">${escapar(r.codigoVerificacao)}</div>
        <div class="url">${escapar(r.urlVerificacao)}</div>
      </div>
    </footer>

    ${avisoCancelamento}
    <div class="aviso">
      <span>${escapar(e.avisoRodape)}</span>
      <span>Emitido em ${escapar(dataCurta(r.dataPagamento))}</span>
    </div>
  </section>`;
}

export function renderizarRecibo(r: ReciboImpresso): string {
  return `<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8">
<title>${escapar(tituloDoDocumento(r.direcao))} ${escapar(r.numeroFormatado)}</title>
<style>
/* Copyright (c) 2026 RAVAPI Soluções. www.ravapi.com */
@page { size: A4 portrait; margin: 10mm; }

*  { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: "Libre Franklin", "Helvetica Neue", Arial, sans-serif;
  color: #1a2230;
  font-size: 10pt;
  line-height: 1.45;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

.folha { width: 190mm; height: 277mm; display: flex; flex-direction: column; }

/* Cada via ocupa metade da folha; o corte cai em 148,5mm da página. */
.via {
  height: 133mm;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
  padding-bottom: 3mm;
}
.corte {
  height: 11mm;
  display: flex; align-items: center; gap: 3mm;
  border-top: 0.4mm dashed #8f9aa6;
  color: #8f9aa6; font-size: 7pt; font-weight: 600;
  padding-top: 2mm;
}
.corte::before { content: "✂"; }
.corte::after  { content: "destaque aqui"; }

.flag { text-align: right; margin-bottom: 2mm; }
.flag b {
  display: inline-block; font-size: 7.5pt; font-weight: 700;
  border: 0.3mm solid #b9c2cc; border-radius: 1mm; padding: 0.6mm 2.4mm;
}
.flag span { display: block; font-size: 7pt; color: #6b7684; margin-top: 0.6mm; }

.cabecalho {
  display: flex; gap: 4mm; align-items: flex-start;
  padding-bottom: 2.5mm; border-bottom: 0.6mm solid #1a2230;
}
.logo { width: 18mm; height: 18mm; object-fit: contain; flex: none; }
.logo-vazio {
  background: #1a2230; color: #fff; border-radius: 1mm;
  display: flex; align-items: center; justify-content: center; text-align: center;
  font-size: 6pt; font-weight: 700; padding: 1.5mm; line-height: 1.2;
}
.emitente { flex: 1; min-width: 0; }
.emitente h1 { margin: 0 0 0.8mm; font-size: 13pt; font-weight: 700; letter-spacing: -0.01em; }
.emitente p  { margin: 0; font-size: 7.5pt; color: #4a5666; line-height: 1.5; }

.carimbo { text-align: right; flex: none; padding-left: 3mm; }
.carimbo .especie { font-size: 6.5pt; font-weight: 700; color: #4a5666; letter-spacing: 0.08em; }
.carimbo .numero  { font-size: 17pt; font-weight: 800; letter-spacing: -0.02em;
                    font-variant-numeric: tabular-nums; line-height: 1.15; }

.importancia {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 2.5mm 0; border-bottom: 0.3mm solid #b9c2cc;
}
.importancia .rotulo { font-size: 7.5pt; font-weight: 700; color: #4a5666; }
.importancia .cifra  { font-size: 19pt; font-weight: 800; letter-spacing: -0.02em;
                       font-variant-numeric: tabular-nums; }

.corpo {
  font-family: "Source Serif 4", Georgia, "Times New Roman", serif;
  font-size: 10.5pt; line-height: 1.65; margin: 3mm 0 0; flex: 1;
}
.via-compacta .corpo { font-size: 9.5pt; line-height: 1.5; }

.detalhes {
  display: flex; gap: 6mm; flex-wrap: wrap;
  border-top: 0.3mm solid #e2e6ea; border-bottom: 0.3mm solid #e2e6ea;
  padding: 2mm 0; margin-top: 2mm;
}
.detalhes .k { display: block; font-size: 6.5pt; font-weight: 700; color: #7d8896; letter-spacing: 0.03em; }
.detalhes .v { display: block; font-size: 8.5pt; font-weight: 600; }

.rodape { display: flex; gap: 6mm; align-items: flex-end; padding-top: 5mm; }
.assinatura { flex: 1; }
.assinatura .linha {
  border-bottom: 0.3mm solid #1a2230; height: 12mm;
  display: flex; align-items: flex-end; justify-content: center;
}
.rubrica { max-height: 11.5mm; max-width: 60mm; }
.assinatura .quem { text-align: center; font-size: 7.5pt; color: #4a5666; margin-top: 1.2mm; line-height: 1.4; }
.assinatura .quem b { display: block; font-size: 8pt; color: #1a2230; }
.assinatura .papel { display: block; font-size: 6.5pt; color: #7d8896; margin-top: 0.4mm; }
.assinatura .lugar { display: block; margin-top: 0.8mm; }

.verificacao { flex: none; width: 30mm; text-align: center; }
.verificacao svg { width: 19mm; height: 19mm; display: block; margin: 0 auto; }
.verificacao .codigo { font-size: 7pt; font-weight: 700; letter-spacing: 0.04em;
                       font-variant-numeric: tabular-nums; margin-top: 1mm; }
.verificacao .url { font-size: 5.8pt; color: #7d8896; word-break: break-all; }

.aviso {
  display: flex; justify-content: space-between; gap: 4mm;
  border-top: 0.3mm solid #e2e6ea; margin-top: 2.5mm; padding-top: 1.5mm;
  font-size: 6pt; color: #7d8896; line-height: 1.4;
}
.cancel-nota {
  margin-top: 2mm; font-size: 7pt; font-weight: 600; color: #b03636;
  border: 0.3mm solid #e0bcbc; border-radius: 1mm; padding: 1.2mm 2mm;
}
.tarja {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 46pt; font-weight: 800; color: rgba(176, 54, 54, 0.16);
  transform: rotate(-18deg); letter-spacing: 0.08em; pointer-events: none; z-index: 2;
}
</style>
</head>
<body>
  <div class="folha">
    ${via(r, 0)}
    <div class="corte"></div>
    ${via(r, 1)}
  </div>
</body>
</html>`;
}
