(function registerAllianzTravelPolicyParser(globalScope) {
  "use strict";

  const registry = globalScope.PolicyPdfParserRegistry;
  const helpers = globalScope.PolicyPdfParserHelpers;
  if (!registry || !helpers) throw new Error("Najpierw wczytaj wspólny silnik importu polis PDF.");

  const {
    firstMatch,
    toIsoDate,
    cleanPremium,
    findClientAddress,
  } = helpers;

  function findPolicyNumber(allText) {
    const fullNumber = firstMatch(allText, [
      /Polisa Moja Podróż numer\s+([0-9-]{8,40})/i,
      /Policy My Journey No\.\s+([0-9-]{8,40})/i,
    ]);
    const segments = fullNumber.split("-").filter(Boolean);
    return segments.at(-1) || fullNumber;
  }

  function findPeriods(allText) {
    const matches = [...allText.matchAll(
      /Okres ubezpieczenia dla[\s\S]{0,180}?(\d{2}\.\d{2}\.\d{4})\s*r\.\s*-\s*(\d{2}\.\d{2}\.\d{4})\s*r\./gi,
    )];
    const periods = matches
      .map((match) => [toIsoDate(match[1]), toIsoDate(match[2])])
      .filter(([from, until]) => from && until);
    if (periods.length === 0) return ["", ""];
    return [
      periods.map(([from]) => from).sort()[0],
      periods.map(([, until]) => until).sort().at(-1),
    ];
  }

  function findContact(holderText) {
    const phone = firstMatch(holderText, [
      /Telefon\s*:\s*(\+?[0-9][0-9 ()-]{6,20})/i,
      /Telefon\s*:\s*\n\s*Phone\s*:\s*\n\s*(\+?[0-9][0-9 ()-]{6,20})/i,
    ]);
    const email = firstMatch(holderText, [
      /E-?mail\s*:\s*([^\s,;]+@[^\s,;]+)/i,
    ]);
    return [
      phone ? `Telefon: ${phone}` : "",
      email ? `E-mail: ${email}` : "",
    ].filter(Boolean).join("\n");
  }

  function findHolderAddress(holderText) {
    const bilingual = holderText.match(
      /Adres\s*:\s*\n\s*Address\s*:\s*\n\s*([^\n]{3,160})(?:\n\s*([0-9]{3}\s+\p{L}[^\n]{0,70}))?/iu,
    );
    if (bilingual) {
      return [bilingual[1], bilingual[2]]
        .filter(Boolean)
        .join(" ")
        .replace(/\b(\d{2})-\s+(\d{3})\b/, "$1-$2");
    }
    return findClientAddress(holderText)
      || firstMatch(holderText, [/Adres\s*:\s*([^\n]{3,180})/i]);
  }

  function parseAllianzTravelPolicy({ allText }) {
    const holderStart = allText.search(/DANE UBEZPIECZAJĄCEGO/i);
    const holderRemainder = holderStart >= 0 ? allText.slice(holderStart) : allText;
    const holderEnd = holderRemainder.search(/\nDANE UBEZPIECZONYCH/i);
    const holderText = holderEnd > 0
      ? holderRemainder.slice(0, holderEnd)
      : holderRemainder.slice(0, 2500);
    const period = findPeriods(allText);
    const scopes = [
      /Rezygnacja z podróży/i.test(allText) ? "Rezygnacja z podróży" : "",
      /Opóźnienie podróży/i.test(allText) ? "Opóźnienie podróży" : "",
      /Przerwanie podróży/i.test(allText) ? "Przerwanie podróży" : "",
    ].filter(Boolean);
    const policy = {
      clientName: firstMatch(holderText, [
        /Imię i nazwisko\s*:\s*\n\s*Name and surname\s*:\s*\n\s*([^\n]{3,160})/i,
        /Imię i nazwisko\s*:\s*([^\n]{3,160})/i,
      ]),
      identityNumber: firstMatch(holderText, [
        /PESEL\s*:\s*\n\s*Personal identity number\s*:\s*\n\s*([0-9]{11})/i,
        /PESEL\s*:\s*([0-9]{11})/i,
      ]),
      contact: findContact(holderText),
      policyNumber: findPolicyNumber(allText),
      registration: "Podróż",
      clientAddress: findHolderAddress(holderText),
      issueDate: toIsoDate(firstMatch(holderText, [
        /Data i czas zawarcia\s*:\s*\n\s*Date of issue\s*:\s*\n\s*(\d{4}-\d{2}-\d{2})/i,
        /Data i czas zawarcia\s*:\s*(\d{4}-\d{2}-\d{2})/i,
      ])),
      validFrom: period[0],
      validUntil: period[1],
      premium: cleanPremium(firstMatch(allText, [
        /Składka\s+([0-9][0-9 .,'\u00a0]*)\s*PLN/i,
      ])),
      riskSummary: scopes.join(" • ").slice(0, 400),
    };
    const missingRequiredFields = ["clientName", "policyNumber", "validUntil"]
      .filter((fieldName) => !policy[fieldName]);
    if (missingRequiredFields.length > 0) {
      const error = new Error("Nie udało się pewnie odczytać danych z polisy Allianz Moja Podróż.");
      error.code = "POLICY_FIELDS_MISSING";
      error.insurer = "Allianz";
      error.missingFields = missingRequiredFields;
      throw error;
    }
    return {
      policy,
      missingOptionalFields: ["identityNumber", "contact", "validFrom", "premium"]
        .filter((fieldName) => !policy[fieldName]),
    };
  }

  registry.register({
    id: "allianz-podroz",
    insurer: "Allianz",
    product: "Moja Podróż",
    detect: ({ detectionText }) => /POLISA MOJA PODROZ NUMER/.test(detectionText)
      && /UBEZPIECZENIE KOSZTOW ORGANIZACJI PODROZY/.test(detectionText),
    parse: parseAllianzTravelPolicy,
  });
})(globalThis);
