import type { TemplateFieldPlacement, TemplateLogoPlacement } from '@ema-platform/api';

/**
 * Client-side twin of the server's `certificate-layout.compiler`.
 *
 * The preview route renders whatever `hbsSource` it is handed, so a canvas
 * layout has to be compiled before it can be previewed — the server only
 * compiles on save, and previewing unsaved edits is the whole point of the
 * button. The two implementations must emit the same HTML; the server's copy
 * is authoritative for what is stored, this one only ever reaches a preview.
 */

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

function pct(value: number | undefined, fallback: number, min = 0): number {
  if (typeof value !== 'number' || Number.isNaN(value)) return fallback;
  return Math.min(100, Math.max(min, value));
}

const CORNER_STYLES: Record<string, (offset: number) => string> = {
  TOP_LEFT: (o) => `top:${o}%;left:${o}%;`,
  TOP_CENTER: (o) => `top:${o}%;left:50%;transform:translateX(-50%);`,
  TOP_RIGHT: (o) => `top:${o}%;right:${o}%;`,
  BOTTOM_LEFT: (o) => `bottom:${o}%;left:${o}%;`,
  BOTTOM_RIGHT: (o) => `bottom:${o}%;right:${o}%;`,
};

function logoHtml(logoUrl: string, placement: TemplateLogoPlacement): string {
  if (!logoUrl.trim()) return '';
  const corner = placement.corner ?? 'TOP_LEFT';
  const width = pct(placement.widthPct, 18);
  const offset = pct(placement.offsetPct, 5);
  const position = (CORNER_STYLES[corner] ?? CORNER_STYLES.TOP_LEFT)(offset);
  return `    <img class="ema-logo" src="${escapeHtml(logoUrl)}" alt="" style="position:absolute;${position}width:${width}%;" />\n`;
}

/**
 * Variable keys the renderer fills with a data URI — the fallback for a
 * block placed before `type` existed on it. Keep in sync with
 * `IMAGE_VARIABLE_KEYS` in the server's template-variables.ts; a new image
 * variable added there should be added here too.
 */
const IMAGE_VARIABLE_KEYS = new Set([
  'logo',
  'holderPhoto',
  'qrImage',
  'sealImage',
  'signatureImage',
  'seafarerSignature',
]);

function isImageBlock(block: TemplateFieldPlacement): boolean {
  if (block.type) return block.type === 'image';
  return !!block.variable && IMAGE_VARIABLE_KEYS.has(block.variable);
}

function blockHtml(block: TemplateFieldPlacement): string {
  const x = pct(block.xPct, 0);
  const y = pct(block.yPct, 0);
  // Minimum 1%, matching the server compiler: a zero-width block would render
  // as an invisible sliver rather than as the mistake it is.
  const width = pct(block.widthPct, 30, 1);

  if (isImageBlock(block) && block.variable) {
    // Triple-brace: the value is a data URI, not markup — escaping it turns
    // every "&" into "&amp;" and corrupts the src.
    const style = `position:absolute;left:${x}%;top:${y}%;width:${width}%;object-fit:contain;`;
    return `    <img class="ema-block" style="${style}" src="{{{${block.variable}}}}" alt="" />\n`;
  }

  const size = block.fontSize ?? 14;
  const weight = block.fontWeight === 'bold' ? 'bold' : 'normal';
  const style_ = block.fontStyle === 'italic' ? 'italic' : 'normal';
  const align = block.align ?? 'left';
  const color = escapeHtml(block.color ?? '#111111');

  const content = block.variable
    ? `{{${block.variable}}}`
    : escapeHtml(block.text ?? '');

  const style =
    `position:absolute;left:${x}%;top:${y}%;width:${width}%;` +
    `font-size:${size}px;font-weight:${weight};font-style:${style_};text-align:${align};color:${color};`;

  return `    <div class="ema-block" style="${style}">${content}</div>\n`;
}

export function compileLayoutToHbs(input: {
  backgroundUrl: string;
  logoUrl: string;
  logoPlacement: TemplateLogoPlacement;
  fieldPlacements: TemplateFieldPlacement[];
}): string {
  const background = input.backgroundUrl.trim()
    ? `    <img class="ema-background" src="${escapeHtml(input.backgroundUrl)}" alt="" />\n`
    : '';

  const blocks = input.fieldPlacements.map(blockHtml).join('');

  return `<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <style>
      @page { margin: 0; }
      html, body { margin: 0; padding: 0; height: 100%; }
      body { font-family: "Helvetica Neue", Arial, sans-serif; }
      .ema-page { position: relative; width: 100%; height: 100vh; overflow: hidden; }
      .ema-background {
        position: absolute; inset: 0;
        width: 100%; height: 100%;
        object-fit: cover;
      }
      .ema-block { box-sizing: border-box; line-height: 1.3; word-wrap: break-word; }
    </style>
  </head>
  <body>
    <div class="ema-page">
${background}${logoHtml(input.logoUrl, input.logoPlacement)}${blocks}    </div>
  </body>
</html>
`;
}
