










import { createPortfolioIssueIdentityHash } from "./xombeztlyiegtybxtzkg.mjs";

const WARTA_VIEW360_HOST = "eagent.warta.pl";
const WARTA_API_BASE = "/view360/api/rest";
const WARTA_API_PAGE_SIZE = 500;
const WARTA_API_MAX_PAGES = 40;
export const WARTA_PORTFOLIO_COMPLETENESS_ERROR = "PORTFOLIO_COMPLETENESS_FAILED";

function throwWartaCompletenessError(reason) {
  const error = new Error("Nie można potwierdzić kompletności portfela Warty. Import został przerwany.");
  error.code = WARTA_PORTFOLIO_COMPLETENESS_ERROR;
  error.reason = reason;
  throw error;
}

function compactText(value) {
  return String(value == null ? "" : value).replace(/\s+/g, " ").trim();
}

function getPageHostname(page) {
  try {
    return new URL(page.url()).hostname.toLowerCase();
  } catch {
    return "";
  }
}

export function isOnWartaView360(page) {
  return getPageHostname(page) === WARTA_VIEW360_HOST;
}


function buildAgreementLabel(agreement) {
  const name = compactText(agreement?.name);
  const role = compactText(agreement?.roleId);
  const branch = agreement?.hasBranchLife && !agreement?.hasBranchProperty ? "Życie" : "Majątek";
  const label = [name, role, branch].filter(Boolean).join(" · ") || compactText(agreement?.agreementId);
  return label.slice(0, 160);
}


export async function fetchWartaAgreements(page) {
  const result = await page.evaluate(async ({ base }) => {
    const token = decodeURIComponent((document.cookie.match(/(?:^|;\s*)XSRF-TOKEN=([^;]+)/) || [])[1] || "");
    try {
      const response = await fetch(`${base}/config/initial`, {
        credentials: "include",
        headers: { Accept: "application/json", "X-XSRF-TOKEN": token },
      });
      if (!response.ok) return { ok: false, status: response.status, agreements: [] };
      const data = await response.json().catch(() => null);
      const agreements = data && data.value && data.value.user && Array.isArray(data.value.user.agreements)
        ? data.value.user.agreements
        : [];
      return { ok: true, status: response.status, agreements };
    } catch (error) {
      return { ok: false, status: 0, agreements: [], error: String(error && error.message || error) };
    }
  }, { base: WARTA_API_BASE });

  if (!result.ok) {
    console.error(`Import Warty: pobranie listy rekordów nie powiodło się (status ${result.status || "sieciowy"}${result.error ? `: ${result.error}` : ""}).`);
    throw new Error("Nie udało się pobrać listy rekordów. Spróbuj ponownie za chwilę.");
  }
  return result.agreements
    .map((agreement) => ({
      agreementId: compactText(agreement?.agreementId),
      label: buildAgreementLabel(agreement),
      hasProperty: Boolean(agreement?.hasBranchProperty),
      hasLife: Boolean(agreement?.hasBranchLife),
    }))
    .filter((agreement) => agreement.agreementId);
}


async function fetchWartaPoliciesPage(page, agreementId, pageNumber, pageSize) {
  return page.evaluate(async ({ base, aid, pageNumber: pn, pageSize: ps }) => {
    const token = decodeURIComponent((document.cookie.match(/(?:^|;\s*)XSRF-TOKEN=([^;]+)/) || [])[1] || "");
    try {
      const response = await fetch(`${base}/producer/policies?aid=${encodeURIComponent(aid)}`, {
        method: "POST",
        credentials: "include",
        headers: { "Content-Type": "application/json", Accept: "application/json", "X-XSRF-TOKEN": token },
        body: JSON.stringify({
          visibilityScope: "OWN",
          paging: { pageNumber: pn, pageSize: ps, sorter: { rules: [{ fieldName: "signingDate", direction: "DESCENDING" }] } },
          listingType: "ALL",
          allAggregateCriteria: false,
          ownAggregateCriteria: false,
          spAggregateCriteria: false,
        }),
      });
      if (!response.ok) return { ok: false, status: response.status, rows: [], paging: null };
      const data = await response.json().catch(() => null);
      const value = data && data.value ? data.value : null;
      const rows = value && value.gridData && Array.isArray(value.gridData.gridRows) ? value.gridData.gridRows : [];
      return { ok: true, status: response.status, rows, paging: value ? value.gridPaging : null };
    } catch (error) {
      return { ok: false, status: 0, rows: [], paging: null, error: String(error && error.message || error) };
    }
  }, { base: WARTA_API_BASE, aid: agreementId, pageNumber, pageSize });
}


function wartaRowDateYmd(row, field) {
  return compactText(row?.[field]).slice(0, 10);
}




export function filterWartaRowsSince(rows, sinceDate) {
  const list = Array.isArray(rows) ? rows : [];
  if (!sinceDate) return list;
  return list.filter((row) => {
    const signingDate = wartaRowDateYmd(row, "signingDate");
    if (signingDate) return signingDate >= sinceDate;
    const startDate = wartaRowDateYmd(row, "startDate");
    if (startDate) return startDate >= sinceDate;
    return true;
  });
}



function addUniqueWartaRows(rows, seenPolicyPeriods) {
  for (const row of rows) {
    const policyNumber = compactText(row?.policyId?.number)
      .replace(/[^0-9A-Za-z]/g, "")
      .toUpperCase();
    const periodKey = [
      policyNumber,
      wartaRowDateYmd(row, "startDate"),
      wartaRowDateYmd(row, "endDate"),
    ].join("\0");
    if (!policyNumber || seenPolicyPeriods.has(periodKey)) {
      throwWartaCompletenessError(policyNumber ? "duplicate_item" : "missing_item_id");
    }
    seenPolicyPeriods.add(periodKey);
  }
}

function validateWartaPage(slice, pageNumber, expectedTotal = null, expectedPages = null) {
  if (!Array.isArray(slice.rows) || !slice.paging || typeof slice.paging !== "object") {
    throwWartaCompletenessError("invalid_page");
  }
  const rawTotal = slice.paging.quantity;
  const rawPageQuantity = slice.paging.pageQuantity;
  if (rawTotal === null || rawTotal === undefined || compactText(rawTotal) === "") {
    throwWartaCompletenessError("invalid_total");
  }
  if (rawPageQuantity === null || rawPageQuantity === undefined || compactText(rawPageQuantity) === "") {
    throwWartaCompletenessError("invalid_page_count");
  }
  const total = Number(rawTotal);
  const declaredPageQuantity = Number(rawPageQuantity);
  if (!Number.isSafeInteger(total) || total < 0) throwWartaCompletenessError("invalid_total");
  if (!Number.isSafeInteger(declaredPageQuantity) || declaredPageQuantity < 0) {
    throwWartaCompletenessError("invalid_page_count");
  }
  const calculatedPages = Math.max(1, Math.ceil(total / WARTA_API_PAGE_SIZE));
  if (
    declaredPageQuantity !== calculatedPages
    && !(total === 0 && declaredPageQuantity === 0)
  ) throwWartaCompletenessError("page_count_mismatch");
  const pageQuantity = calculatedPages;
  if (pageQuantity > WARTA_API_MAX_PAGES) throwWartaCompletenessError("page_limit");
  if (expectedTotal !== null && total !== expectedTotal) throwWartaCompletenessError("total_changed");
  if (expectedPages !== null && pageQuantity !== expectedPages) throwWartaCompletenessError("page_count_changed");
  const expectedRows = Math.min(
    WARTA_API_PAGE_SIZE,
    Math.max(0, total - (pageNumber * WARTA_API_PAGE_SIZE)),
  );
  if (slice.rows.length !== expectedRows) throwWartaCompletenessError("short_page");
  return { total, pageQuantity };
}



export async function fetchWartaPolicyRows(page, agreementId, { onProgress = () => {} } = {}) {
  const normalizedAid = compactText(agreementId);
  if (!normalizedAid) throw new Error("Brak identyfikatora rekordu Warty (agreementId).");

  const first = await fetchWartaPoliciesPage(page, normalizedAid, 0, WARTA_API_PAGE_SIZE);
  if (!first.ok) {
    console.error(`Import Warty: API polis odpowiedziało błędem (status ${first.status || "sieciowy"}${first.error ? `: ${first.error}` : ""}).`);
    throw new Error("Nie udało się pobrać polis. Spróbuj ponownie za chwilę.");
  }
  const firstPage = validateWartaPage(first, 0);
  const rows = [...first.rows];
  const totalQuantity = firstPage.total;
  const pageQuantity = firstPage.pageQuantity;
  const seenPolicyPeriods = new Set();
  addUniqueWartaRows(first.rows, seenPolicyPeriods);
  onProgress({ collected: rows.length, total: totalQuantity, page: 1, pageQuantity });

  for (let pageNumber = 1; pageNumber < pageQuantity; pageNumber += 1) {
    const slice = await fetchWartaPoliciesPage(page, normalizedAid, pageNumber, WARTA_API_PAGE_SIZE);
    if (!slice.ok) {
      console.error(`Import Warty: pobieranie przerwane na stronie ${pageNumber + 1} (status ${slice.status || "sieciowy"}).`);
      throw new Error("Pobieranie polis zostało przerwane. Spróbuj ponownie za chwilę.");
    }
    validateWartaPage(slice, pageNumber, totalQuantity, pageQuantity);
    addUniqueWartaRows(slice.rows, seenPolicyPeriods);
    rows.push(...slice.rows);
    onProgress({ collected: rows.length, total: totalQuantity, page: pageNumber + 1, pageQuantity });
  }
  if (rows.length !== totalQuantity) throwWartaCompletenessError("count_mismatch");
  return rows;
}




export function pickWartaPolicyImageFile(files) {
  const list = Array.isArray(files)
    ? files.filter((file) => file && normalizeWartaPolicyFileId(file.id))
    : [];
  const byType = list.find((file) => compactText(file.type).toLowerCase() === "obraz polisy");
  if (byType) return byType;
  return list.find((file) => {
    const name = compactText(file.fileName).toLowerCase();
    return name.startsWith("polisa") && name.endsWith(".pdf");
  }) || null;
}

function normalizeWartaPolicyFileId(value) {
  let normalized = "";
  if (typeof value === "string") {
    normalized = value.trim();
  } else if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) {
    normalized = String(value);
  }
  if (!normalized || normalized.length > 512 || normalized.includes("\0")) return "";
  return normalized;
}



function classifyWartaPdfListHttpFailure(status) {
  const normalizedStatus = Number(status);
  if (normalizedStatus === 401) return { type: "global_failure", code: "session_expired" };
  if (normalizedStatus === 403) return { type: "global_failure", code: "authorization" };
  if (normalizedStatus === 408) return { type: "global_failure", code: "timeout" };
  if (normalizedStatus === 429) return { type: "global_failure", code: "rate_limited" };
  if (normalizedStatus >= 500 && normalizedStatus <= 599) {
    return { type: "global_failure", code: "portal_unavailable" };
  }
  return { type: "global_failure", code: "unknown" };
}

function classifyWartaPdfDownloadHttpFailure(status) {
  const normalizedStatus = Number(status);
  if (normalizedStatus === 401) return { type: "global_failure", code: "session_expired" };
  if (normalizedStatus === 403) return { type: "global_failure", code: "authorization" };
  if (normalizedStatus === 408) return { type: "global_failure", code: "timeout" };
  if (normalizedStatus === 429) return { type: "global_failure", code: "rate_limited" };
  if (normalizedStatus >= 500 && normalizedStatus <= 599) {
    return { type: "global_failure", code: "portal_unavailable" };
  }
  if (normalizedStatus === 404) return { type: "document_failure", code: "not_found" };
  return { type: "global_failure", code: "unknown" };
}

export async function fetchWartaPolicyFilesResult(page, policyCtxId) {
  const normalizedCtx = compactText(policyCtxId);
  if (!normalizedCtx) return { type: "document_failure", code: "not_found" };
  let result;
  try {
    result = await page.evaluate(async ({ base, ctx }) => {
      const token = decodeURIComponent((document.cookie.match(/(?:^|;\s*)XSRF-TOKEN=([^;]+)/) || [])[1] || "");
      let response;
      try {
        response = await fetch(`${base}/policy/attachments/duplicate/${encodeURIComponent(ctx)}/files`, {
          credentials: "include",
          headers: { Accept: "application/json", "X-XSRF-TOKEN": token },
        });
      } catch {
        return { kind: "network" };
      }
      if (response.redirected) return { kind: "redirected" };
      if (!response.ok) return { kind: "http", status: response.status };
      const contentType = String(response.headers?.get?.("content-type") || "")
        .split(";", 1)[0]
        .trim()
        .toLowerCase();
      const isJson = contentType === "application/json"
        || (
          contentType.includes("/")
          && /^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+\+json$/.test(contentType)
        );
      if (!isJson) return { kind: "unexpected_content_type" };
      let data;
      try {
        data = await response.json();
      } catch {
        return { kind: "invalid_response" };
      }
      if (!data || !Array.isArray(data.value)) return { kind: "invalid_response" };
      return { kind: "success", files: data.value };
    }, { base: WARTA_API_BASE, ctx: normalizedCtx });
  } catch {
    return { type: "global_failure", code: "navigation" };
  }

  if (result?.kind === "success" && Array.isArray(result.files)) {
    return { type: "success", files: result.files };
  }
  if (result?.kind === "network") return { type: "global_failure", code: "network" };
  if (result?.kind === "redirected") {
    return { type: "global_failure", code: "session_expired" };
  }
  if (result?.kind === "http") return classifyWartaPdfListHttpFailure(result.status);
  if (result?.kind === "unexpected_content_type" || result?.kind === "invalid_response") {
    return { type: "global_failure", code: "portal_unavailable" };
  }
  return { type: "global_failure", code: "unknown" };
}


export async function fetchWartaPolicyFiles(page, policyCtxId) {
  const result = await fetchWartaPolicyFilesResult(page, policyCtxId);
  return result.type === "success" ? result.files : [];
}




export async function downloadWartaPolicyPdfBase64(page, { policyCtxId, login, agreementId }) {
  const filesResult = await fetchWartaPolicyFilesResult(page, policyCtxId);
  if (filesResult.type !== "success") return filesResult;
  const file = pickWartaPolicyImageFile(filesResult.files);
  if (!file && filesResult.files.length === 0) {
    return { type: "document_failure", code: "not_found" };
  }
  if (!file) return { type: "global_failure", code: "unknown" };
  const normalizedFileId = normalizeWartaPolicyFileId(file.id);
  if (!normalizedFileId) return { type: "global_failure", code: "unknown" };

  let result;
  try {
    result = await page.evaluate(async ({ base, fileId, login: user, aid }) => {
      const token = decodeURIComponent((document.cookie.match(/(?:^|;\s*)XSRF-TOKEN=([^;]+)/) || [])[1] || "");
      const suffix = user && aid ? `?iv-user=${encodeURIComponent(user)}&aid=${encodeURIComponent(aid)}` : "";
      let response;
      try {
        response = await fetch(`${base}/wartarepo/download/${encodeURIComponent(fileId)}${suffix}`, {
          credentials: "include",
          headers: { Accept: "application/pdf", "X-XSRF-TOKEN": token },
        });
      } catch {
        return { kind: "network" };
      }
      if (response.redirected) return { kind: "redirected" };
      if (!response.ok) return { kind: "http", status: response.status };
      const contentType = String(response.headers?.get?.("content-type") || "")
        .split(";", 1)[0]
        .trim()
        .toLowerCase();
      if (contentType === "text/html" || contentType === "application/xhtml+xml") {
        return { kind: "session_content" };
      }
      const isJson = contentType === "application/json"
        || (
          contentType.includes("/")
          && /^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+\+json$/.test(contentType)
        );
      if (isJson) return { kind: "unexpected_content_type" };
      if (
        contentType
        && contentType !== "application/pdf"
        && contentType !== "application/octet-stream"
      ) {
        return { kind: "unexpected_content_type" };
      }
      let buffer;
      try {
        buffer = await response.arrayBuffer();
      } catch {
        return { kind: "network" };
      }
      if (!buffer || buffer.byteLength < 1000) return { kind: "invalid_pdf" };
      const bytes = new Uint8Array(buffer);
      if (!(
        bytes[0] === 0x25
        && bytes[1] === 0x50
        && bytes[2] === 0x44
        && bytes[3] === 0x46
        && bytes[4] === 0x2d
      )) return { kind: "invalid_pdf" };
      let binary = "";
      const chunk = 0x8000;
      try {
        for (let i = 0; i < bytes.length; i += chunk) {
          binary += String.fromCharCode.apply(null, bytes.subarray(i, i + chunk));
        }
        return { kind: "success", base64: btoa(binary), size: bytes.length };
      } catch {
        return { kind: "download_failure" };
      }
    }, {
      base: WARTA_API_BASE,
      fileId: normalizedFileId,
      login: compactText(login),
      aid: compactText(agreementId),
    });
  } catch {
    return { type: "global_failure", code: "navigation" };
  }

  if (result?.kind === "success" && typeof result.base64 === "string") {
    return { type: "success", base64: result.base64, size: result.size };
  }
  if (result?.kind === "network") return { type: "global_failure", code: "network" };
  if (result?.kind === "redirected") {
    return { type: "global_failure", code: "session_expired" };
  }
  if (result?.kind === "session_content") {
    return { type: "global_failure", code: "session_expired" };
  }
  if (result?.kind === "unexpected_content_type") {
    return { type: "global_failure", code: "portal_unavailable" };
  }
  if (result?.kind === "http") return classifyWartaPdfDownloadHttpFailure(result.status);
  if (result?.kind === "invalid_pdf") {
    return { type: "document_failure", code: "invalid_pdf" };
  }
  if (result?.kind === "download_failure") {
    return { type: "document_failure", code: "download_failed" };
  }
  return { type: "global_failure", code: "unknown" };
}

const WARTA_PRODUCT_LINE_LABELS = {
  HOME: "Mieszkanie",
  PROPERTY: "Mieszkanie",
  BUSINESS: "Firma",
  AGRICULTURAL: "Rolne",
  PERSONAL: "NNW",
  SMALL_FLEET: "Flota",
};

function normalizeWartaRegistration(value) {
  return compactText(value).replace(/[^A-Za-z0-9]/g, "").toUpperCase();
}

function normalizeWartaProductName(value) {
  return compactText(value)
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toUpperCase();
}

function isWartaTravelProduct(products) {
  return products.some((product) => /\bWARTA\s+TRAVEL\b/.test(normalizeWartaProductName(product)));
}

function resolveWartaRegistration(productLine, registrationPlate, products) {
  if (isWartaTravelProduct(products)) return "Podróż";
  if (registrationPlate.length >= 4 && registrationPlate.length <= 10) return registrationPlate;
  return WARTA_PRODUCT_LINE_LABELS[productLine] || "Inne";
}

function resolveWartaRiskSummary(products) {
  return products
    
    
    .map((product) => compactText(product).replace(/^eAgent\s+/i, ""))
    .filter(Boolean)
    .join(", ")
    .slice(0, 400);
}



function resolveWartaIdentity(item) {
  const pesel = compactText(item?.insurer?.pesel).replace(/\D/g, "");
  if (/^\d{11}$/.test(pesel)) return pesel;
  const nip = compactText(item?.insurerNip).replace(/\D/g, "");
  if (/^\d{10}$/.test(nip)) return nip;
  const regon = compactText(item?.insurerPeselRegon).replace(/\D/g, "");
  if (/^\d{9}$/.test(regon) || /^\d{14}$/.test(regon)) return regon;
  return pesel || nip || regon;
}

function resolveWartaClientName(item) {
  const full = compactText(item?.insurer?.fullName);
  if (full) return full;
  return [compactText(item?.insurer?.lastName), compactText(item?.insurer?.firstName)].filter(Boolean).join(" ");
}

function formatWartaPremium(amount) {
  const value = Number(amount?.amount ?? amount);
  if (!Number.isFinite(value) || value <= 0) return "";
  const fixed = value.toFixed(2);
  return fixed.endsWith(".00") ? fixed.slice(0, -3) : fixed.replace(".", ",");
}




export function mapWartaPolicyRows(rows, {
  minEndDate = "",
  mappingCollector = null,
} = {}) {
  const records = [];
  const seen = new Set();
  for (const item of Array.isArray(rows) ? rows : []) {
    const policyNumber = compactText(item?.policyId?.number);
    const clientName = resolveWartaClientName(item);
    const status = compactText(item?.status).slice(0, 80);
    const validFrom = compactText(item?.startDate).slice(0, 10);
    const endDate = compactText(item?.endDate).slice(0, 10);
    if (/anulowan|storn|odst[aą]pien/i.test(status)) {
      mappingCollector?.recordFiltered("CANCELLED_POLICY");
      continue;
    }
    const normalizedPolicyNumber = policyNumber.replace(/[^0-9A-Za-z]/g, "").toLowerCase();
    if (!normalizedPolicyNumber || !clientName) {
      let identityHash = "";
      try {
        identityHash = createPortfolioIssueIdentityHash({
          insurer: "Warta",
          sourceId: compactText(item?.policyId?.policyCtxId ?? item?.policyId?.id),
          policyNumber,
          validFrom,
          validUntil: endDate,
        });
      } catch {
      }
      mappingCollector?.recordRejected("MISSING_REQUIRED_FIELDS", { identityHash });
      continue;
    }
    if (minEndDate && endDate && endDate < minEndDate) {
      mappingCollector?.recordFiltered("OUTSIDE_DATE_RANGE");
      continue;
    }
    const key = `${normalizedPolicyNumber}\0${validFrom}\0${endDate}`;
    if (seen.has(key)) {
      mappingCollector?.recordDuplicate();
      continue;
    }
    seen.add(key);

    const products = (Array.isArray(item?.products) ? item.products : []).map(compactText).filter(Boolean);
    const productLine = compactText(item?.productLine);
    const registrationPlate = normalizeWartaRegistration(item?.registerNumber);
    const registration = resolveWartaRegistration(productLine, registrationPlate, products);
    const phone = compactText(item?.phone);
    const email = compactText(item?.email);
    const contactParts = [];
    if (phone) contactParts.push(`Telefon: ${phone}`);
    if (email) contactParts.push(`E-mail: ${email}`);

    records.push({
      insurer: "Warta",
      policyNumber,
      policyCtxId: compactText(item?.policyId?.policyCtxId),
      clientName: clientName.slice(0, 160),
      identityNumber: resolveWartaIdentity(item),
      contact: contactParts.join("\n"),
      registration,
      vehicleMake: "",
      vehicleModel: "",
      vin: "",
      validFrom,
      validUntil: endDate,
      issueDate: compactText(item?.signingDate).slice(0, 10),
      premium: formatWartaPremium(item?.premiumAmount),
      status,
      product: productLine,
      riskSummary: resolveWartaRiskSummary(products),
      pdfAvailable: false,
    });
    mappingCollector?.recordMapped();
  }
  return records;
}
