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

  function getPrimaryPolicyHolderSection(lines) {
    const startIndex = lines.findIndex((line) => (
      /^UBEZPIECZAJACY\s*\/\s*UBEZPIECZONY\s*:?$/.test(normalizeForDetection(line))
    ));
    if (startIndex < 0) return [];

    const endIndex = lines.findIndex((line, index) => (
      index > startIndex
      && /^(UBEZPIECZONY[- ]LEASINGODAWCA|OKRES UBEZPIECZENIA)\b/.test(normalizeForDetection(line))
    ));
    return lines.slice(startIndex, endIndex > startIndex ? endIndex : startIndex + 8);
  }

  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, [
      /NIP\s*:\s*([0-9][0-9 .-]{8,15})/i,
    ]).replace(/\D/g, "");
  }

  function findInsurancePeriod(allText) {
    const validFrom = firstMatch(allText, [
      /(?:^|\n)Od\s+(\d{4}-\d{2}-\d{2})(?:\s+\d{1,2}:\d{2})?/i,
    ]);
    const validUntil = firstMatch(allText, [
      /(?:^|\n)Do\s+(\d{4}-\d{2}-\d{2})(?:\s+\d{1,2}:\d{2})?/i,
    ]);
    return [validFrom, validUntil];
  }

  function collapseRepeatedClientName(value) {
    const clientName = normalizeLine(value);
    if (!clientName) return "";

    const parts = clientName.split(/\s*[,;|/]\s*/).map(normalizeLine).filter(Boolean);
    if (
      parts.length > 1
      && parts.every((part) => normalizeForDetection(part) === normalizeForDetection(parts[0]))
    ) {
      return parts[0];
    }

    const words = clientName.replace(/[,;|/]+/g, " ").split(/\s+/).filter(Boolean);
    if (words.length >= 4 && words.length % 2 === 0) {
      const midpoint = words.length / 2;
      const firstHalf = words.slice(0, midpoint).join(" ");
      const secondHalf = words.slice(midpoint).join(" ");
      if (normalizeForDetection(firstHalf) === normalizeForDetection(secondHalf)) return firstHalf;
    }
    return clientName;
  }

  function parseHestiaPolicy({ lines, allText }) {
    const holderText = getPrimaryPolicyHolderSection(lines).join("\n");
    const insurancePeriod = findInsurancePeriod(allText);
    const clientName = collapseRepeatedClientName(firstMatch(holderText, [
      /Ubezpieczający\s*\/\s*Ubezpieczony\s*:\s*([^\n]+)/i,
      /Ubezpieczający\s*:\s*([^,\n]{3,180})/i,
    ]));
    const policy = {
      clientName,
      identityNumber: findIdentityNumber(holderText),
      contact: "",
      policyNumber: firstMatch(allText, [
        /Polisa ubezpieczenia komunikacyjnego ERGO Biznes\s+nr\s+([0-9A-Z/-]{6,})/i,
        /Tytuł przelewu\s*:\s*Polisa\s+([0-9A-Z/-]{6,})/i,
      ]),
      registration: firstMatch(allText, [
        /numer rejestracyjny\s*:\s*([A-Z0-9 -]{4,12})/i,
      ]).replace(/\s+/g, "").toLocaleUpperCase("pl"),
      ...findVehicleMakeAndModel(allText),
      vin: normalizeVehicleIdentifier(firstMatch(allText, [
        /(?:VIN|nr\s+VIN|numer\s+nadwozia|nr\s+nadwozia)(?:\s*\/\s*(?:nadwozia|podwozia))?\s*:\s*([A-Z0-9][A-Z0-9 -]{3,23})/i,
      ])),
      firstRegistrationDate: findFirstRegistrationDate(allText),
      ...findVehicleExtraDetails(allText),
      clientAddress: findClientAddress(holderText),
      validFrom: insurancePeriod[0],
      validUntil: insurancePeriod[1],
      premium: cleanPremium(firstMatch(allText, [
        /Do zapłaty\s*:\s*([0-9][0-9 .,'\u00a0]*)\s*PLN/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 klienta, numeru polisy, rejestracji lub okresu z polisy Hestii.");
      error.code = "POLICY_FIELDS_MISSING";
      error.insurer = "Hestia";
      error.missingFields = missingRequiredFields;
      throw error;
    }
    return {
      policy,
      missingOptionalFields: ["identityNumber", "validFrom", "premium"]
        .filter((fieldName) => !policy[fieldName]),
    };
  }

  registry.register({
    id: "hestia-komunikacja",
    insurer: "Hestia",
    product: "Komunikacja",
    detect: ({ detectionText }) => /ERGO HESTIA/.test(detectionText)
      && (
        /POLISA UBEZPIECZENIA KOMUNIKACYJNEGO ERGO BIZNES/.test(detectionText)
        || (/OKRES UBEZPIECZENIA UBEZPIECZONY POJAZD/.test(detectionText)
          && /TYTUL PRZELEWU\s*:\s*POLISA\s+922[0-9]+/.test(detectionText))
      ),
    parse: parseHestiaPolicy,
  });
})(globalThis);
