(function registerAllianzCommunicationPolicyParser(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 {
    normalizeLine,
    normalizeForDetection,
    firstMatch,
    toIsoDate,
    normalizeVehicleIdentifier,
    splitVehicleMakeAndModel,
    findVehicleExtraDetails,
    cleanPremium,
  } = helpers;

  function buildRiskSummary(allText, premium) {
    const detectionText = normalizeForDetection(allText);
    const risks = [];
    if (/ODPOWIEDZIALNOSC CYWILNA POSIADACZY POJAZDOW|ODPOWIEDZIALNOSC\s+CYWILNA\s+POSIADACZY/.test(detectionText)) {
      risks.push(premium ? `OC ${premium} zł` : "OC");
    }
    if (/\bAUTOCASCO\b/.test(detectionText)) risks.push("AC");
    if (/\bNNW\b|NAST[EĘ]PSTW NIESZCZ[EĘ][ŚS]LIWYCH WYPADK[ÓO]W/.test(detectionText)) risks.push("NNW");
    if (/ASSISTANCE/.test(detectionText)) risks.push("Assistance");
    if (/OCHRONA PRAWNA/.test(detectionText)) risks.push("Ochrona prawna");
    return risks.join(" • ").slice(0, 400);
  }

  function findHolderText(allText) {
    const match = allText.match(
      /UBEZPIECZAJĄCY\/(?:WŁAŚCICIEL POJAZDU|UŻYTKOWNIK)\s*\n([\s\S]{0,1000}?)(?=\n[^\n]{0,40}WŁAŚCICIEL POJAZDU|\nZakres ubezpieczenia|\nDodatkowe informacje|$)/i,
    );
    return match ? match[1] : "";
  }

  function deduplicateRepeatedName(value) {
    const name = normalizeLine(value)
      .replace(/^(?:Rodzaj pojazdu|Rok produkcji|Pojemność silnika)\b[^\n]*/i, "")
      .replace(/,\s*(?:REGON|PESEL|NIP)\s*:.*$/i, "")
      .trim();
    const tokens = name.split(/\s+/).filter(Boolean);
    if (tokens.length >= 4 && tokens.length % 2 === 0) {
      const half = tokens.length / 2;
      const first = tokens.slice(0, half).join(" ");
      const second = tokens.slice(half).join(" ");
      if (normalizeForDetection(first) === normalizeForDetection(second)) return first;
    }
    return name;
  }

  function findHolderName(holderText) {
    const raw = firstMatch(holderText, [
      /(?:^|\n)([^\n]{3,180}?),\s*(?:REGON\s*:\s*[0-9 -]{7,20},\s*)?PESEL\s*:/i,
      /(?:^|\n)([^\n]{3,180}?),\s*(?:NIP|REGON)\s*:/i,
    ]);
    if (raw) return deduplicateRepeatedName(raw);
    return normalizeLine(holderText.split("\n").find((line) => (
      /[A-ZĄĆĘŁŃÓŚŹŻ]{2}/.test(line)
      && !/^(?:Rodzaj|Rok|Pojemność|Kod pocztowy|Data)/i.test(normalizeLine(line))
    )) || "");
  }

  function findContact(holderText) {
    const phone = firstMatch(holderText, [
      /tel\.\s*:\s*(\+?[0-9][0-9 ()-]{6,20})/i,
      /telefon\s*:\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 findInsurancePeriod(allText) {
    const periodMatch = allText.match(
      /(\d{2}\.\d{2}\.\d{4})\s*r\.\s*(?:\d{1,2}:\d{2}\s*)?-\s*\n?\s*(\d{2}\.\d{2}\.\d{4})\s*r\./i,
    );
    return periodMatch
      ? [toIsoDate(periodMatch[1]), toIsoDate(periodMatch[2])]
      : ["", ""];
  }

  function parseAllianzCommunicationPolicy({ allText }) {
    const holderText = findHolderText(allText);
    const period = findInsurancePeriod(allText);
    const premium = cleanPremium(firstMatch(allText, [
      /Razem\s+([0-9][0-9 .,'\u00a0]*)\s*zł/i,
    ]));
    const policy = {
      clientName: findHolderName(holderText),
      identityNumber: firstMatch(holderText, [/PESEL\s*:\s*([0-9]{11})/i]),
      contact: findContact(holderText),
      policyNumber: firstMatch(allText, [/Polisa nr\s+([0-9A-Z/-]{6,})/i]),
      registration: firstMatch(allText, [/NR REJESTRACYJNY\s+([A-Z0-9]{4,10})/i])
        .toLocaleUpperCase("pl"),
      ...splitVehicleMakeAndModel(firstMatch(allText, [
        /Marka\s*\/\s*model pojazdu\s+([^\n]{2,100})/i,
      ])),
      vin: normalizeVehicleIdentifier(firstMatch(allText, [
        /Nr nadwozia\s*\(VIN\)\s+([A-Z0-9]{11,17})/i,
      ])),
      firstRegistrationDate: "",
      ...findVehicleExtraDetails(allText),
      clientAddress: helpers.findClientAddress(holderText)
        || firstMatch(holderText, [
          /(?:^|\n)((?:ul\.|al\.|os\.|pl\.)\s*[^\n,]{2,100}\d[^\n]*,\s*\d{2}-\d{3}\s+[^\n,]+)/i,
        ]),
      validFrom: period[0],
      validUntil: period[1],
      premium,
      riskSummary: buildRiskSummary(allText, premium),
    };
    const missingRequiredFields = ["clientName", "policyNumber", "registration", "validUntil"]
      .filter((fieldName) => !policy[fieldName]);
    if (missingRequiredFields.length > 0) {
      const error = new Error("Nie udało się pewnie odczytać danych klienta, numeru polisy, rejestracji lub okresu z polisy Allianz.");
      error.code = "POLICY_FIELDS_MISSING";
      error.insurer = "Allianz";
      error.missingFields = missingRequiredFields;
      throw error;
    }
    return {
      policy,
      missingOptionalFields: ["identityNumber", "validFrom", "premium"]
        .filter((fieldName) => !policy[fieldName]),
    };
  }

  registry.register({
    id: "allianz-komunikacja",
    insurer: "Allianz",
    product: "Komunikacja",
    detect: ({ detectionText }) => /ALLIANZ POLSKA/.test(detectionText)
      && /POLISA NR\s+[0-9]/.test(detectionText)
      && /NR REJESTRACYJNY/.test(detectionText),
    parse: parseAllianzCommunicationPolicy,
  });
})(globalThis);
