import { localDateCzStr } from "./date";

/**
 * Shared helpers for the four PDF routes (offers-pdf, issued-orders-pdf,
 * invoices-pdf, orders-pdf). These used to be near-verbatim copies in each
 * route file; the canonical variants live here:
 *
 * - `cleanQuillHtml` is the STRICT variant (strips javascript:/data:/vbscript:
 *   in BOTH href and src — defense-in-depth, DOMPurify runs first).
 * - `formatNum` uses the NBSP (U+00A0) thousands separator so amounts never
 *   line-wrap inside the number.
 * - `formatCurrency` is the per-currency-symbol variant from offers
 *   (€ / $ / Kč / £, anything else falls back to "<num> <code>").
 */

/** dd.MM.yyyy in Europe/Prague; invalid input echoes back as-is. */
export function formatDate(date: Date | string | null | undefined): string {
  if (!date) return "";
  const d = new Date(date);
  if (isNaN(d.getTime())) return String(date);
  return localDateCzStr(d);
}

/** Format number with comma decimal separator and NBSP thousands separator. */
export function formatNum(n: number, decimals = 2): string {
  const abs = Math.abs(n);
  const fixed = abs.toFixed(decimals);
  const [intPart, decPart] = fixed.split(".");
  const withSep = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, " ");
  const result = decPart ? `${withSep},${decPart}` : withSep;
  return n < 0 ? `-${result}` : result;
}

/** Per-currency symbol formatting (offers variant). */
export function formatCurrency(amount: number, currency: string): string {
  const n = Number(amount) || 0;
  switch (currency) {
    case "EUR":
      return `${formatNum(n, 2)} €`;
    case "USD":
      return `$${Math.abs(n)
        .toFixed(2)
        .replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`;
    case "CZK":
      return `${formatNum(n, 2)} Kč`;
    case "GBP":
      return `£${Math.abs(n)
        .toFixed(2)
        .replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`;
    default:
      return `${formatNum(n, 2)} ${currency}`;
  }
}

export function escapeHtml(str: string | null | undefined): string {
  if (!str) return "";
  return str
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;");
}

/**
 * Sanitize Quill HTML for the PDF templates: remove dangerous tags, event
 * handlers, javascript:/data:/vbscript: URLs (href AND src), inline styles,
 * and merge adjacent identical spans. Runs AFTER DOMPurify at every call site
 * (regex pass = defense-in-depth, not the primary sanitizer).
 */
export function cleanQuillHtml(html: string | null | undefined): string {
  if (!html) return "";
  let s = html;
  // Remove dangerous tags with content
  s = s.replace(
    /<(script|iframe|object|embed|style|link|meta|base|form|input|textarea|button|select|svg|math)[^>]*>[\s\S]*?<\/\1>/gi,
    "",
  );
  s = s.replace(
    /<(script|iframe|object|embed|style|link|meta|base|form|input|textarea|button|select|svg|math)[^>]*\/?>/gi,
    "",
  );
  // Strip event handlers
  s = s.replace(/\s+on\w+\s*=\s*("[^"]*"|'[^']*'|[^\s>]*)/gi, "");
  s = s.replace(/\s+on\w+\s*=\s*[^\s>]*/gi, "");
  // Strip javascript:/data:/vbscript: in href and src
  s = s.replace(
    /href\s*=\s*["']?\s*(javascript|data|vbscript)\s*:[^"'>\s]*/gi,
    'href="#"',
  );
  s = s.replace(
    /src\s*=\s*["']?\s*(javascript|data|vbscript)\s*:[^"'>\s]*/gi,
    'src=""',
  );
  // Replace &nbsp; with regular space (outside of tags)
  s = s.replace(/(&nbsp;)/g, " ");
  s = s.replace(/\s+style\s*=\s*("[^"]*"|'[^']*'|[^\s>]*)/gi, "");
  // Merge adjacent spans with same attributes
  let prev = "";
  while (prev !== s) {
    prev = s;
    s = s.replace(/<span([^>]*)>(.*?)<\/span>\s*<span\1>/gs, "<span$1>$2");
  }
  return s;
}

/** CSS rules for Quill's .ql-indent-1..9 classes (identical in all templates). */
export function buildQuillIndentCss(): string {
  let indentCSS = "";
  for (let n = 1; n <= 9; n++) {
    const pad = n * 3;
    const liPad = n * 3 + 1.5;
    indentCSS += `  .ql-indent-${n} { padding-left: ${pad}em; }\n`;
    indentCSS += `  li.ql-indent-${n} { padding-left: ${liPad}em; }\n`;
  }
  return indentCSS;
}
