(function registerPzuAutoPolicyParser(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 getPolicyHolderSection(lines) {
    const startIndex = lines.findIndex((line) => /^UBEZPIECZAJACY$/.test(normalizeForDetection(line)));
    if (startIndex < 0) return [];
    const endIndex = lines.findIndex((line, index) => (
      index > startIndex && /^WLASCICIEL POJAZDU$/.test(normalizeForDetection(line))
    ));
    return lines.slice(startIndex + 1, endIndex > startIndex ? endIndex : startIndex + 12);
  }

  function findClientName(holderLines) {
    const nameParts = [];
    for (const line of holderLines) {
      if (/^(PESEL|NIP|REGON|ADRES|E-?MAIL|TELEFON)\s*:/i.test(normalizeForDetection(line))) break;
      const candidate = normalizeLine(line);
      if (candidate) nameParts.push(candidate);
    }
    return nameParts.join(" ");
  }

  function findContact(holderText) {
    const email = firstMatch(holderText, [/e-?mail\s*:\s*([^\n]+)/i]);
    const phone = firstMatch(holderText, [/telefon\s*:\s*([^\n]+)/i]);
    const normalizedEmail = /@/.test(email) && !/NIE\s*USTALONO/i.test(email) ? email : "";
    const normalizedPhone = /[0-9]{7}/.test(phone.replace(/\D/g, ""))
      ? phone.replace(/[()\s-]+/g, "")
      : "";
    return [
      normalizedPhone ? `Telefon: ${normalizedPhone}` : "",
      normalizedEmail ? `E-mail: ${normalizedEmail}` : "",
    ].filter(Boolean).join("\n");
  }

  
  
  
  function parsePlnToGrosze(value) {
    const compact = String(value || "").replace(/[\s '.]+/g, "");
    const match = compact.match(/^(\d+)(?:,(\d{1,2}))?$/);
    if (!match) return null;
    return (Number(match[1]) * 100) + Number((match[2] || "0").padEnd(2, "0"));
  }

  function formatGroszeAsPremium(grosze) {
    return `${Math.floor(grosze / 100)},${String(grosze % 100).padStart(2, "0")}`;
  }

  function findPzuPremium(allText) {
    const totalLabelMatch = allText.match(
      /(?:sk[łl]adka\s+(?:[łl][ąa]czna|razem)|[łl][ąa]cznie\s+do\s+zap[łl]aty|razem\s+do\s+zap[łl]aty)\s*:?\s*([0-9][0-9 .,' ]*)\s*z[łl]/i,
    );
    if (totalLabelMatch) return cleanPremium(totalLabelMatch[1]);

    const installmentMatches = [...allText.matchAll(
      /rata\s*\d*\s*kwota\s*:\s*([0-9][0-9 .,' ]*)\s*z[łl]/gi,
    )];
    if (installmentMatches.length >= 2) {
      let totalGrosze = 0;
      for (const match of installmentMatches) {
        const grosze = parsePlnToGrosze(match[1]);
        if (grosze == null) { totalGrosze = null; break; }
        totalGrosze += grosze;
      }
      if (totalGrosze != null && totalGrosze > 0) return formatGroszeAsPremium(totalGrosze);
    }

    return cleanPremium(firstMatch(allText, [
      /Płatności[\s\S]{0,900}?kwota\s*:\s*([0-9][0-9 .,' ]*)\s*zł/i,
    ]));
  }

  function findInsurancePeriod(allText) {
    const match = allText.match(
      /okres ubezpieczenia\s*:\s*(\d{2}\.\d{2}\.\d{4})(?:\s*r\.)?(?:\s+godz\.\s*\d{1,2}:\d{2})?\s*[–—-]\s*(\d{2}\.\d{2}\.\d{4})(?:\s*r\.)?/i,
    );
    return match ? [toIsoDate(match[1]), toIsoDate(match[2])] : ["", ""];
  }

  function parsePzuPolicy({ lines, allText }) {
    const holderLines = getPolicyHolderSection(lines);
    const holderText = holderLines.join("\n");
    const insurancePeriod = findInsurancePeriod(allText);
    const policy = {
      clientName: findClientName(holderLines),
      identityNumber: firstMatch(holderText, [/(?:PESEL|NIP|REGON)\s*:\s*([0-9 .-]{8,18})/i]).replace(/\D/g, ""),
      contact: findContact(holderText),
      policyNumber: firstMatch(allText, [/numer polisy\s*:\s*([0-9A-Z/-]{6,})/i]),
      registration: firstMatch(allText, [/nr rejestracyjny\s*:\s*([A-Z0-9 -]{4,12})/i])
        .replace(/\s+/g, "")
        .toLocaleUpperCase("pl"),
      ...findVehicleMakeAndModel(allText),
      vin: normalizeVehicleIdentifier(firstMatch(allText, [
        /\bVIN\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: findPzuPremium(allText),
      riskSummary: helpers.findRiskSummary(allText),
    };
    
    
    const documentHasRegistrationField = /nr rejestracyjny\s*:/i.test(allText);
    const requiredFields = documentHasRegistrationField || !policy.vin
      ? ["clientName", "policyNumber", "registration", "validUntil"]
      : ["clientName", "policyNumber", "validUntil"];
    const missingRequiredFields = requiredFields.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 PZU.");
      error.code = "POLICY_FIELDS_MISSING";
      error.insurer = "PZU";
      error.missingFields = missingRequiredFields;
      throw error;
    }
    return {
      policy,
      missingOptionalFields: ["identityNumber", "validFrom", "premium", "registration"]
        .filter((fieldName) => !policy[fieldName]),
    };
  }

  registry.register({
    id: "pzu-auto",
    insurer: "PZU",
    product: "Komunikacja",
    detect: ({ detectionText }) => /\bPZU AUTO\b/.test(detectionText)
      && /(POWSZECHNY ZAKLAD UBEZPIECZEN|ODBIORCA: PZU SA)/.test(detectionText),
    parse: parsePzuPolicy,
  });
})(globalThis);
