'use strict';
/* ──────────────────────────────────────────────────────────────────
   Answer normalization + correctness check.
   Same algorithm runs on user input and stored canonical answer
   (from /tasks endpoint), then compared.

   Canonical answer forms (produced by backend/scripts/import-exam-tasks.js):
     MC:        single Cyrillic letter:  "а" | "б" | "в" | "г" | "д"
     open NUM:  decimal:                 "-2"  "7500"  "1.5"  "0.25"
     open FRAC: fraction:                "9/4"  "-104/9"  (sign on numerator)
     open PAIR: two values, ";" sep:     "-2;4"
   The user can type the answer in many equivalent forms — the normalizer
   accepts any form and decides equivalence numerically.
   ────────────────────────────────────────────────────────────────── */

(function () {
  const EPS = 1e-6;

  // Try to coerce a string to a number; returns NaN on failure.
  function toNumber(s) {
    if (s == null) return NaN;
    let t = String(s).trim().replace(/\$/g, '').replace(/\s+/g, '').replace(',', '.');
    // Fraction "a/b" → a/b
    const f = t.match(/^(-?\d+(?:\.\d+)?)\s*\/\s*(-?\d+(?:\.\d+)?)$/);
    if (f) {
      const num = Number(f[1]);
      const den = Number(f[2]);
      if (!Number.isFinite(num) || !Number.isFinite(den) || den === 0) return NaN;
      return num / den;
    }
    const n = Number(t);
    return Number.isFinite(n) ? n : NaN;
  }

  // Parse a "pair" answer "A;B" — accepts ";" or "," or " и " or whitespace
  function toPair(s) {
    if (s == null) return null;
    const t = String(s).trim().replace(/\$/g, '').replace(/\s+и\s+/g, ';');
    const parts = t.split(/[;,]/).map(p => p.trim()).filter(Boolean);
    if (parts.length !== 2) return null;
    const a = toNumber(parts[0]);
    const b = toNumber(parts[1]);
    if (Number.isNaN(a) || Number.isNaN(b)) return null;
    // Order-insensitive comparison: return sorted pair
    return a <= b ? [a, b] : [b, a];
  }

  /* Detect form of the canonical answer.
     Returns: 'mc' | 'pair' | 'numeric' */
  function detectForm(canonical) {
    if (canonical == null) return 'numeric';
    const t = String(canonical).trim();
    if (/^[а-д]$/.test(t)) return 'mc';
    if (/^[^;]+;[^;]+$/.test(t)) return 'pair';
    return 'numeric';
  }

  /* Main check. Returns true iff user input matches canonical answer.
     False if either side can't be normalized.

     Both inputs are strings as returned by the form or stored in DB. */
  function check(userInput, canonical) {
    if (userInput == null || canonical == null) return false;

    const form = detectForm(canonical);

    if (form === 'mc') {
      const u = String(userInput).trim().toLowerCase();
      return u === String(canonical).trim().toLowerCase();
    }

    if (form === 'pair') {
      const cp = toPair(canonical);
      const up = toPair(userInput);
      if (!cp || !up) return false;
      return Math.abs(cp[0] - up[0]) < EPS && Math.abs(cp[1] - up[1]) < EPS;
    }

    // Numeric (integer / decimal / fraction)
    const c = toNumber(canonical);
    const u = toNumber(userInput);
    if (Number.isNaN(c) || Number.isNaN(u)) return false;
    return Math.abs(c - u) < EPS;
  }

  window.EP = window.EP || {};
  window.EP.answer = { check, detectForm, toNumber, toPair };
})();
