#!/usr/bin/env node
/* WIA Code conformance verifier
 * Usage: node verify.js [path-to-vectors-folder]   (default: ./conformance-vectors)
 *
 * Decodes every image listed in the folder's manifest.json with the bundled
 * reference engine (./engine/wiascan-core.js — same file that runs in
 * production on wiacode.com) and checks the recovered text matches
 * expectedPayload byte-for-byte. Prints a pass/fail table and an overall
 * conformance rate.
 *
 * Requires: Node 18+, and the "canvas" package (`npm install` in this
 * folder first — see package.json).
 */
const fs = require('fs');
const path = require('path');
const { createCanvas, loadImage } = require('canvas');

const dir = path.resolve(process.argv[2] || './conformance-vectors');
const manifestPath = path.join(dir, 'manifest.json');
if (!fs.existsSync(manifestPath)) {
  console.error(`manifest.json not found in ${dir}`);
  process.exit(2);
}
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));

global.window = global;
global.document = { createElement: (t) => { if (t === 'canvas') return createCanvas(1, 1); throw new Error('unsupported: ' + t); } };
require(path.join(__dirname, 'engine', 'wiascan-core.js'));

(async () => {
  let ok = 0, bad = 0;
  const rows = [];
  for (const v of manifest.vectors) {
    const file = path.join(dir, v.file);
    let text = null, err = null;
    try {
      const img = await loadImage(file);
      const cv = createCanvas(img.width, img.height);
      const cx = cv.getContext('2d');
      cx.drawImage(img, 0, 0);
      const id = cx.getImageData(0, 0, cv.width, cv.height);
      const r = window.WiaScan.detectAuto(id, { psf: true, deep: true });
      if (r && r.decoded) text = r.text;
    } catch (e) {
      err = e.message;
    }
    const pass = text !== null && text === v.expectedPayload;
    if (pass) ok++; else bad++;
    rows.push({ file: v.file, shape: v.shape, contentType: v.contentType, degradation: v.degradation, pass, got: text, err });
  }

  const w = Math.max(...rows.map((r) => r.file.length));
  console.log('file'.padEnd(w) + '  shape       type  degradation     result');
  for (const r of rows) {
    console.log(
      r.file.padEnd(w) + '  ' +
      r.shape.padEnd(10) + '  ' +
      r.contentType.padEnd(4) + '  ' +
      r.degradation.padEnd(14) + '  ' +
      (r.pass ? 'PASS' : 'FAIL' + (r.err ? ` (${r.err})` : ' (payload mismatch)'))
    );
  }
  const rate = ((ok / rows.length) * 100).toFixed(1);
  console.log(`\n${ok}/${rows.length} passed (${rate}%)`);
  if (bad > 0) {
    console.log('A conforming implementation must pass all vectors. See INTEGRATION-NOTES.md.');
    process.exit(1);
  }
})();
