(function registerGeneraliCommunicationPolicyParser(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,
    findVehicleMakeAndModel,
    findFirstRegistrationDate,
    findVehicleExtraDetails,
    findClientAddress,
    cleanPremium,
  } = helpers;

  function getPrimaryPolicyHolderSection(lines) {
    const startIndex = lines.findIndex((line) => (
      /^UBEZPIECZAJACY(?:\s+(?:NAZWA|IMIE))?\s*:/.test(normalizeForDetection(line))
    ));
    if (startIndex < 0) return [];
    const endIndex = lines.findIndex((line, index) => (
      index > startIndex && /^UBEZPIECZONY(?:\s+(?:NAZWA|IMIE))?\s*:/.test(normalizeForDetection(line))
    ));
    return lines.slice(startIndex, endIndex > startIndex ? endIndex : startIndex + 4);
  }

  function findClientName(holderText) {
    const personMatch = holderText.match(
      /Ubezpieczający\s+imię\s*:\s*([^,\n]{1,80})\s*,\s*nazwisko\s*:\s*([^,\n]{1,120})/i,
    );
    if (personMatch) return normalizeLine(`${personMatch[1]} ${personMatch[2]}`);
    return firstMatch(holderText, [
      /Ubezpieczający(?:\s+nazwa)?\s*:\s*([^\n]+?)(?=\s*,\s*(?:PESEL|NIP|REGON|adres|telefon|e-?mail|email)\s*:)/i,
      /Ubezpieczający(?:\s+nazwa)?\s*:\s*([^\n,]{3,180})/i,
    ]);
  }

  function findIdentityNumber(holderText) {
    const regon = firstMatch(holderText, [
      /REGON\s*:\s*([0-9][0-9 .-]{6,19})/i,
    ]).replace(/\D/g, "");
    if (regon) return regon;
    return firstMatch(holderText, [
      /(?:PESEL|NIP)\s*:\s*([0-9][0-9 .-]{7,18})/i,
    ]).replace(/\D/g, "");
  }

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

  function findInsurancePeriod(allText) {
    const match = allText.match(
      /OKRES UBEZPIECZENIA\s+od\s+(\d{2}\.\d{2}\.\d{4})(?:\s*\([^)]*\))?\s+do\s+(\d{2}\.\d{2}\.\d{4})(?:\s*\([^)]*\))?/i,
    );
    return match ? [toIsoDate(match[1]), toIsoDate(match[2])] : ["", ""];
  }

  function parseGeneraliCommunicationPolicy({ lines, allText }) {
    const holderText = getPrimaryPolicyHolderSection(lines).join("\n");
    const insurancePeriod = findInsurancePeriod(allText);
    const policy = {
      clientName: findClientName(holderText),
      identityNumber: findIdentityNumber(holderText),
      contact: findContact(holderText),
      policyNumber: firstMatch(allText, [
        /POLISA\s+NR\s+([0-9A-Z/-]{6,})\s+UBEZPIECZENIA KOMUNIKACYJNE/i,
      ]),
      registration: firstMatch(allText, [
        /Numer rejestracyjny\s*\/\s*VIN\s+([A-Z0-9 -]{4,12})\s*\//i,
        /Nr rejestracyjny\s*\/\s*Nr VIN\s+([A-Z0-9 -]{4,12})\s*\//i,
      ]).replace(/\s+/g, "").toLocaleUpperCase("pl"),
      ...findVehicleMakeAndModel(allText),
      vin: normalizeVehicleIdentifier(firstMatch(allText, [
        /Numer rejestracyjny\s*\/\s*VIN\s+[A-Z0-9 -]{4,12}\s*\/\s*([A-Z0-9]{4,24})/i,
        /Nr rejestracyjny\s*\/\s*Nr VIN\s+[A-Z0-9 -]{4,12}\s*\/\s*([A-Z0-9]{4,24})/i,
      ])),
      firstRegistrationDate: findFirstRegistrationDate(allText),
      ...findVehicleExtraDetails(allText),
      clientAddress: findClientAddress(holderText),
      validFrom: insurancePeriod[0],
      validUntil: insurancePeriod[1],
      premium: cleanPremium(firstMatch(allText, [
        /SKŁADKA I TERMINY PŁATNOŚCI\s+RAZEM\s+([0-9][0-9 .,'\u00a0]*)\s*zł/i,
        /Składka roczna\s*(?:\(Annual premium\))?\s+([0-9][0-9 .,'\u00a0]*)\s*zł/i,
      ])),
      riskSummary: helpers.findRiskSummary(allText),
    };
    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 pierwszego ubezpieczającego, numeru polisy, rejestracji lub okresu z polisy Generali Komunikacja.");
      error.code = "POLICY_FIELDS_MISSING";
      error.insurer = "Generali";
      error.missingFields = missingRequiredFields;
      throw error;
    }
    return {
      policy,
      missingOptionalFields: ["identityNumber", "validFrom", "premium"]
        .filter((fieldName) => !policy[fieldName]),
    };
  }

  registry.register({
    id: "generali-komunikacja",
    insurer: "Generali",
    product: "Komunikacja",
    detect: ({ detectionText }) => /POLISA NR\s+[0-9A-Z/-]+\s+UBEZPIECZENIA KOMUNIKACYJNE/.test(detectionText)
      && /GENERALI T\.U\./.test(detectionText),
    parse: parseGeneraliCommunicationPolicy,
  });
})(globalThis);
