import { InputError } from './validation';

interface FontCoverage { hasGlyphForCodePoint(codePoint: number): boolean }
const coverage = new WeakMap<Uint8Array, FontCoverage>();

/** Fail visibly rather than silently replacing business text with empty glyphs. */
export async function assertPdfTextSupported(texts: string[], bytes: Uint8Array): Promise<void> {
  let font = coverage.get(bytes);
  if (!font) {
    // fontkit 2.0.4 is the same reviewed font engine used by pdfme; it ships no TS declarations.
    // @ts-expect-error Upstream fontkit has no bundled declaration file.
    const fontkit = await import('fontkit') as { create(data: Uint8Array): FontCoverage };
    font = fontkit.create(bytes);
    coverage.set(bytes, font);
  }
  const unsupported = new Set<number>();
  for (const text of texts) for (const character of text) {
    if (/^[\n\r\t]$/.test(character)) continue;
    const point = character.codePointAt(0)!;
    if (!font.hasGlyphForCodePoint(point)) unsupported.add(point);
    if (unsupported.size >= 6) break;
  }
  if (unsupported.size) {
    const points = [...unsupported].map(point => `U+${point.toString(16).toUpperCase().padStart(4, '0')}`).join(', ');
    throw new InputError(`The PDF font cannot display some characters (${points}). Replace those characters for PDF export, or save JSON to keep the original text. Your draft has not changed.`);
  }
}
