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

  
  
  const CLIENT_ROLE_PATTERN = /^(?:Właściciel|Współwłaściciel|Leasingobiorca|Kredytobiorca|Użytkownik|Zastawnik|Posiadacz)\s+(.+)$/i;
  const CLIENT_FIELD_PATTERN = /^(?:Pesel|REGON|NIP|PKD|Dane adresowe|Adres korespondencyjny|Oddział|Telefon|E-?mail)\s*:/i;

  function splitLines(allText) {
    return String(allText ?? "")
      .split(/\r?\n/)
      .map((line) => line.replace(/ /g, " ").replace(/\s+/g, " ").trim());
  }

   
  function findCompensaClient(allText) {
    const lines = splitLines(allText);
    const startIndex = lines.findIndex((line) => /^UBEZPIECZAJĄCY$/i.test(line));
    if (startIndex < 0) return { clientName: "", identityNumber: "" };

    const roleMatch = (lines[startIndex + 1] || "").match(CLIENT_ROLE_PATTERN);
    const nameParts = roleMatch ? [roleMatch[1].trim()] : [];
    for (let index = startIndex + 2; index < Math.min(lines.length, startIndex + 7); index += 1) {
      const line = lines[index];
      if (!line || CLIENT_FIELD_PATTERN.test(line) || /^UBEZPIECZONY$/i.test(line)) break;
      nameParts.push(line);
    }

    
    let identityNumber = "";
    for (let index = startIndex + 1; index < Math.min(lines.length, startIndex + 10); index += 1) {
      const line = lines[index];
      if (/^UBEZPIECZONY$/i.test(line)) break;
      const match = line.match(/^(?:Pesel\s*:\s*(\d{11})|REGON\s*:\s*(\d{9}(?:\d{5})?)|NIP\s*:\s*(\d{10}))/i);
      if (match) {
        identityNumber = match[1] || match[2] || match[3] || "";
        break;
      }
    }

    return {
      clientName: nameParts.join(" ").replace(/\s+/g, " ").trim().slice(0, 160),
      identityNumber,
    };
  }

  
  
  
  const COMPENSA_RISK_LABELS = [
    { label: "Assistance Szyby", pattern: /^Assistance Szyby\b/i },
    { label: "NNW Mój Pupil", pattern: /^NNW M[óo]j Pupil\b/i },
    { label: "Powrót do zdrowia", pattern: /^Powr[óo]t do zdrowia\b/i },
    { label: "Asysta prawna", pattern: /^Asysta prawna\b/i },
    { label: "Zielona karta", pattern: /^Zielona karta\b/i },
    { label: "Szyby", pattern: /^Szyby\b/i },
    { label: "OC", pattern: /^OC\b/ },
    { label: "AC", pattern: /^AC\b/ },
    { label: "NNW", pattern: /^NNW\b/ },
    { label: "Assistance", pattern: /^Assistance\b/i },
    { label: "BLS", pattern: /^BLS\b/ },
    { label: "OUZ", pattern: /^OUZ\b/ },
    { label: "GAP", pattern: /^GAP\b/ },
    { label: "Bagaż", pattern: /^Baga[żz]\b/i },
    { label: "UTO", pattern: /^UTO\b/ },
    { label: "WD", pattern: /^WD\b/ },
  ];

  function labelCompensaRisk(line) {
    const known = COMPENSA_RISK_LABELS.find(({ pattern }) => pattern.test(line));
    if (known) return known.label;
    
    const fallback = line.match(/^([\p{L}][\p{L}\s/-]{1,40}?)(?=\s+[0-9]|\s*$)/u);
    return fallback ? fallback[1].replace(/\s+/g, " ").trim() : "";
  }

   
  function findCompensaRiskSummary(allText) {
    const lines = splitLines(allText).filter(Boolean);
    const startIndex = lines.findIndex((line) => /^ZAKRES UBEZPIECZENIA\b/i.test(line));
    if (startIndex < 0) return "";
    const endIndex = lines.findIndex((line, index) => (
      index > startIndex && /^SKŁADKA OGÓŁEM\b/i.test(line)
    ));
    const sectionEnd = endIndex > startIndex ? endIndex : Math.min(lines.length, startIndex + 60);

    const rows = [];
    let current = "";
    for (let index = startIndex + 1; index < sectionEnd; index += 1) {
      const line = lines[index];
      
      if (/^Ubezpieczenie\s+Zakres ochrony/i.test(line) || /^Suma$/i.test(line) || /^ubezpieczenia$/i.test(line)) continue;
      current = current ? `${current} ${line}` : line;
      if (/(?:zł|-)\s*$/i.test(line)) {
        rows.push(current);
        current = "";
      }
    }
    if (current) rows.push(current);

    const risks = new Map();
    for (const row of rows) {
      const label = labelCompensaRisk(row);
      if (!label) continue;
      const amounts = [...row.matchAll(/([0-9][0-9\s ]*(?:[.,][0-9]{1,2})?)\s*zł(?!\p{L})/giu)];
      const amount = amounts.length > 0
        ? `${amounts.at(-1)[1].replace(/\s+/g, " ").trim()} zł`
        : "";
      
      
      if (!risks.has(label) || (!risks.get(label) && amount)) {
        risks.set(label, amount);
      }
    }
    return [...risks]
      .map(([label, amount]) => (amount ? `${label} ${amount}` : label))
      .join(" • ")
      .slice(0, 400);
  }


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

  function parseCompensaCommunicationPolicy({ allText }) {
    const insurancePeriod = findInsurancePeriod(allText);
    const client = findCompensaClient(allText);
    const policy = {
      clientName: client.clientName || firstMatch(allText, [
        /UBEZPIECZAJĄCY\s+Właściciel\s+([^\n]{3,120})/i,
        /Dane Ubezpieczającego\s*\/\s*Policyholder\s+([^\n]{3,120})/i,
      ]),
      identityNumber: client.identityNumber || firstMatch(allText, [
        /Pesel\s*:\s*(\d{11})/i,
      ]),
      contact: "",
      policyNumber: firstMatch(allText, [
        /Typ polisy\s*:\s*[0-9A-Z/-]+\s+Numer\s*:\s*([0-9A-Z/-]{4,})/i,
        /numer\s*:\s*\/no\.\s*:\s*([0-9A-Z/-]{4,})/i,
      ]),
      registration: firstMatch(allText, [
        /Numer rejestracyjny\s*:\s*([A-Z0-9][A-Z0-9 -]{3,11})/i,
      ]).replace(/\s+/g, "").toLocaleUpperCase("pl"),
      ...findVehicleMakeAndModel(allText),
      vin: normalizeVehicleIdentifier(firstMatch(allText, [
        /Numer VIN\s*:\s*([A-Z0-9][A-Z0-9 -]{3,23})/i,
        /Numer nadwozia\s*:\s*([A-Z0-9][A-Z0-9 -]{3,23})/i,
      ])),
      firstRegistrationDate: findFirstRegistrationDate(allText),
      ...findVehicleExtraDetails(allText),
      clientAddress: findClientAddress(allText),
      validFrom: insurancePeriod[0],
      validUntil: insurancePeriod[1],
      premium: cleanPremium(firstMatch(allText, [
        /SKŁADKA OGÓŁEM\s+([0-9][0-9 .,' ]*)\s*zł/i,
      ])),
      riskSummary: findCompensaRiskSummary(allText),
    };
    
    
    
    const missingRequiredFields = ["clientName", "policyNumber", "validUntil"]
      .filter((fieldName) => !policy[fieldName]);
    if (!policy.registration && !policy.vin) missingRequiredFields.push("registration");
    if (missingRequiredFields.length > 0) {
      const error = new Error("Nie udało się pewnie odczytać danych klienta, numeru polisy, pojazdu lub okresu z polisy Compensa Komunikacja.");
      error.code = "POLICY_FIELDS_MISSING";
      error.insurer = "Compensa";
      error.missingFields = missingRequiredFields;
      throw error;
    }
    return {
      policy,
      missingOptionalFields: ["identityNumber", "validFrom", "premium", "registration"]
        .filter((fieldName) => !policy[fieldName]),
    };
  }

  registry.register({
    id: "compensa-komunikacja",
    insurer: "Compensa",
    product: "Komunikacja",
    detect: ({ detectionText }) => /POLISA COMPENSA KOMUNIKACJA/.test(detectionText)
      && /TYP POLISY\s*:\s*[0-9A-Z/-]+\s+NUMER\s*:/.test(detectionText),
    parse: parseCompensaCommunicationPolicy,
  });
})(globalThis);
