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

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

  function clean(text = "") {
    return global.FIVA?.CleanOCRText?.cleanOCRText
      ? global.FIVA.CleanOCRText.cleanOCRText(text)
      : String(text || "").replace(/\s+/g, " ").trim();
  }

  function compact(value = "") {
    return String(value || "").replace(/\s+/g, " ").trim();
  }

  function first(text = "", patterns = []) {
    for (const pattern of patterns) {
      const match = text.match(pattern);
      if (!match) continue;
      return compact(match[1] || match[0] || "");
    }
    return "";
  }

  function date(value = "") {
    const normalized = global.FIVA?.StrictDobValidator?.normalizeDate?.(value) || "";
    if (!normalized) return "";
    const [day, month, year] = normalized.split("/");
    return `${year}-${month}-${day}`;
  }

  function normalizeGender(value = "") {
    const source = compact(value).toLowerCase();
    if (source === "f" || /\bfemale\b/.test(source)) return "Female";
    if (source === "m" || /\bmale\b/.test(source)) return "Male";
    return "";
  }

  function meta(confidence = 94, source = "passport_text") {
    return { confidence, source, verified: confidence >= 90 };
  }

  function add(fields, field, value, confidence = 94) {
    if (!compact(value) || fields[field]) return;
    fields[field] = value;
    fields.__fieldMeta[field] = meta(confidence);
  }

  function extract(text = "") {
    const source = clean(text);
    const fields = { __fieldMeta: {} };
    const passport = global.FIVA?.PassportParser?.parse?.(source) || {};
    Object.entries(passport).forEach(([key, value]) => {
      if (key.startsWith("__") || !compact(value)) return;
      fields[key] = value;
    });
    Object.assign(fields.__fieldMeta, passport.__fieldMeta || {});

    add(fields, "fullName", first(source, [
      /(?:full\s*name|applicant\s*name|name\s*of\s*applicant|name)\s*[:\-]\s*([A-Z][A-Z\s.'-]{3,})(?=\n|$)/i
    ]));
    add(fields, "passportNumber", (first(source, [
      /(?:passport\s*(?:no|number))\s*[:\-]?\s*([A-Z0-9]{6,16})/i,
      /\b([A-Z]{1,3}[0-9]{5,10})\b/i
    ]) || "").toUpperCase().replace(/[^A-Z0-9]/g, ""));
    add(fields, "nationality", first(source, [
      /(?:nationality|citizenship|country\s*of\s*citizenship)\s*[:\-]\s*([A-Z][A-Z\s]{2,})(?=\n|$)/i
    ]));
    add(fields, "country", first(source, [
      /(?:country\/region\s*you\s*are\s*applying\s*visa\s*from|applying\s*from|application\s*country|country)\s*[:\-]\s*([A-Z][A-Z\s]{2,})(?=\n|$)/i
    ]));
    add(fields, "mission", first(source, [
      /(?:indian\s*mission\/office|indian\s*mission|mission\s*office|mission)\s*[:\-]\s*([A-Z][A-Z\s-]{2,})(?=\n|$)/i
    ]));
    add(fields, "dateOfBirth", date(first(source, [
      /(?:date\s*of\s*birth|dob|birth\s*date)\s*[:\-]\s*([0-9]{1,4}[\/\-. ][0-9]{1,2}[\/\-. ][0-9]{4}|[0-9]{1,2}[-\/\s][A-Z]{3,9}[-\/\s][0-9]{4})/i
    ])));
    add(fields, "gender", normalizeGender(first(source, [
      /(?:sex|gender)\s*[:\-]\s*(male|female|m|f)\b/i
    ])));
    add(fields, "email", first(source, [
      /\b([A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,})\b/i
    ]).toLowerCase());
    add(fields, "expectedArrivalDate", date(first(source, [
      /(?:expected\s*date\s*of\s*arrival|date\s*of\s*arrival|arrival\s*date)\s*[:\-]\s*([0-9]{1,4}[\/\-. ][0-9]{1,2}[\/\-. ][0-9]{4}|[0-9]{1,2}[-\/\s][A-Z]{3,9}[-\/\s][0-9]{4})/i
    ])));
    add(fields, "visaType", first(source, [
      /(?:visa\s*service|visa\s*type|type\s*of\s*visa)\s*[:\-]\s*([A-Z][A-Z\s-]{3,})(?=\n|$)/i
    ]));
    add(fields, "purpose", first(source, [
      /(?:purpose\s*of\s*visit|visa\s*purpose|purpose)\s*[:\-]\s*([A-Z][A-Z\s-]{3,})(?=\n|$)/i
    ]));
    add(fields, "passportIssueDate", date(first(source, [
      /(?:date\s*of\s*issue|issue\s*date|passport\s*issue)\s*[:\-]\s*([0-9]{1,4}[\/\-. ][0-9]{1,2}[\/\-. ][0-9]{4}|[0-9]{1,2}[-\/\s][A-Z]{3,9}[-\/\s][0-9]{4})/i
    ])));
    add(fields, "passportExpiryDate", date(first(source, [
      /(?:date\s*of\s*expiry|expiry\s*date|passport\s*expiry)\s*[:\-]\s*([0-9]{1,4}[\/\-. ][0-9]{1,2}[\/\-. ][0-9]{4}|[0-9]{1,2}[-\/\s][A-Z]{3,9}[-\/\s][0-9]{4})/i
    ])));

    return fields;
  }

  const PassportProfileExtractor = Object.freeze({
    clean,
    extract
  });

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

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