(function initFivaStrictDobValidator(global) {
  "use strict";

  if (global.FIVA?.StrictDobValidator) {
    if (typeof module !== "undefined" && module.exports) module.exports = global.FIVA.StrictDobValidator;
    return;
  }

  const MONTHS = Object.freeze({
    JAN: "01",
    FEB: "02",
    MAR: "03",
    APR: "04",
    MAY: "05",
    JUN: "06",
    JUL: "07",
    AUG: "08",
    SEP: "09",
    SEPT: "09",
    OCT: "10",
    NOV: "11",
    DEC: "12"
  });

  const DATE_FIELDS = new Set(["dateOfBirth", "dob", "expectedArrivalDate", "arrivalDate", "passportIssueDate", "passportExpiryDate"]);

  function compact(value = "") {
    return String(value || "")
      .normalize("NFKC")
      .replace(/[\u0000-\u001F\u007F-\u009F\u00A0\u200B-\u200F\uFEFF]/g, " ")
      .replace(/\s+/g, " ")
      .trim();
  }

  function validCalendarDate(day, month, year) {
    const date = new Date(Date.UTC(year, month - 1, day));
    return year >= 1900
      && year <= 2100
      && date.getUTCFullYear() === year
      && date.getUTCMonth() === month - 1
      && date.getUTCDate() === day;
  }

  function format(day, month, year) {
    const dayNumber = Number(day);
    const monthNumber = Number(month);
    const yearNumber = Number(year);
    if (!validCalendarDate(dayNumber, monthNumber, yearNumber)) return "";
    return `${String(dayNumber).padStart(2, "0")}/${String(monthNumber).padStart(2, "0")}/${String(yearNumber).padStart(4, "0")}`;
  }

  function parseDate(value = "") {
    const source = compact(value).toUpperCase().replace(/[.]/g, "-");
    if (!source) return null;

    let match = source.match(/^(\d{1,2})[/-](\d{1,2})[/-](\d{4})$/);
    if (match) {
      const display = format(match[1], match[2], match[3]);
      return display ? { display, year: String(match[3]), source } : null;
    }

    match = source.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/);
    if (match) {
      const display = format(match[3], match[2], match[1]);
      return display ? { display, year: String(match[1]), source } : null;
    }

    match = source.match(/^(\d{1,2})[-/\s]([A-Z]{3,9})[-/\s](\d{4})$/);
    if (match) {
      const month = MONTHS[match[2].slice(0, 4)] || MONTHS[match[2].slice(0, 3)];
      if (!month) return null;
      const display = format(match[1], month, match[3]);
      return display ? { display, year: String(match[3]), source } : null;
    }

    return null;
  }

  function normalizeDate(value = "") {
    return parseDate(value)?.display || "";
  }

  function validateDob(value = "", options = {}) {
    const parsed = parseDate(value);
    if (!parsed) return { ok: false, value: "", reason: "invalid_dob" };

    const sourceValue = compact(options.sourceValue || value);
    const sourceYear = sourceValue.match(/\b(19\d{2}|20\d{2}|2100)\b/)?.[1] || "";
    if (sourceYear && sourceYear !== parsed.year) {
      return { ok: false, value: "", reason: "dob_year_mismatch" };
    }

    const confidence = Number(options.confidence || 0);
    if (confidence > 0 && confidence < 60 && options.verified !== true) {
      return { ok: false, value: "", reason: "low_confidence_dob" };
    }

    return { ok: true, value: parsed.display, year: parsed.year, reason: "" };
  }

  function isDateField(fieldKey = "") {
    return DATE_FIELDS.has(fieldKey);
  }

  function normalizeProfileDates(profile = {}, records = []) {
    const fieldRecords = new Map((records || []).filter((record) => record?.key).map((record) => [record.key, record]));
    const next = { ...profile };
    Object.keys(next).forEach((key) => {
      if (!isDateField(key)) return;
      const record = fieldRecords.get(key) || fieldRecords.get(key === "dob" ? "dateOfBirth" : key);
      const result = validateDob(next[key], {
        confidence: record?.confidence,
        verified: record?.verified,
        sourceValue: next[key]
      });
      if (result.ok) next[key] = result.value;
      else delete next[key];
    });
    return next;
  }

  const StrictDobValidator = Object.freeze({
    DATE_FIELDS,
    MONTHS,
    compact,
    isDateField,
    normalizeDate,
    normalizeProfileDates,
    parseDate,
    validateDob
  });

  global.FIVA = Object.assign(global.FIVA || {}, { StrictDobValidator });

  if (typeof module !== "undefined" && module.exports) {
    module.exports = StrictDobValidator;
  }
})(typeof globalThis !== "undefined" ? globalThis : this);
