



const VEHICLE_DATA_FIELDS = new Set([
  "vin",
  "mileage",
  "engineCapacity",
  "enginePower",
  "firstRegistrationDate",
  "productionYear",
  "fuelType",
  "seats",
  "grossWeight",
  "vehicleMake",
  "vehicleModel",
  "vehicleType",
]);

function normalizeLabel(value) {
  return String(value ?? "")
    .toLocaleLowerCase("pl")
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .replace(/ł/g, "l")
    .replace(/[^a-z0-9]+/g, " ")
    .replace(/\s+/g, " ")
    .trim();
}

function resolveAnsweredValue(field, rawAnswer) {
  if (rawAnswer === null || rawAnswer === undefined || field?.kind === "checkbox") return "";
  const rawValue = typeof rawAnswer === "object"
    ? String(rawAnswer.value ?? "")
    : String(rawAnswer);
  if (["select", "radio", "combobox"].includes(field?.kind) && Array.isArray(field?.options)) {
    const option = field.options.find((candidate) => String(candidate?.value ?? "") === rawValue);
    const optionText = String(option?.text ?? "").replace(/\s+/g, " ").trim();
    if (optionText) return optionText;
  }
  return rawValue.replace(/\s+/g, " ").trim();
}

function recognizeVehicleField(label) {
  if (!label) return "";
  if (/(^| )(vin|nr vin|numer vin)( |$)/.test(label) || /(numer|nr) (nadwozia|podwozia)/.test(label)) {
    return "vin";
  }
  if (/przebieg/.test(label) && /(roczny|deklarowany|planowany|szacowany)/.test(label)) return "";
  if (/(^| )(przebieg|stan licznika)( |$)/.test(label)) return "mileage";
  if (/pojemnosc/.test(label) && !/(zbiornika|bagaznika|ladunkowa)/.test(label)) return "engineCapacity";
  if (/(^| )moc( silnika)?( |$)/.test(label) || /moc.*(kw|km|kon mechan)/.test(label)) return "enginePower";
  if (/pierwsz/.test(label) && /rejestrac/.test(label) && !/(w polsce|krajowej)/.test(label)) {
    return "firstRegistrationDate";
  }
  if (/rok produkcji/.test(label)) return "productionYear";
  if (/(^| )(rodzaj paliwa|paliwo)( |$)/.test(label)) return "fuelType";
  if (/liczba miejsc/.test(label) && !/(dla dzieci|dzieci)/.test(label)) return "seats";
  if (/(^| )dmc( |$)/.test(label) || /dopuszczalna masa calkowita/.test(label)) return "grossWeight";
  if (/(^| )marka( |$)/.test(label) && /(^| )model( |$)/.test(label)) return "";
  if (/(^| )marka( pojazdu| samochodu)?( |$)/.test(label)) return "vehicleMake";
  if (/(^| )model( pojazdu| samochodu)?( |$)/.test(label)) return "vehicleModel";
  if (/(rodzaj|typ) pojazdu/.test(label)) return "vehicleType";
  return "";
}

function normalizeVehicleValue(fieldName, value, label) {
  const cleanValue = String(value ?? "").replace(/\s+/g, " ").trim().slice(0, 120);
  if (!cleanValue) return "";
  if (fieldName === "vin") {
    const vin = cleanValue.toUpperCase().replace(/[^A-Z0-9]/g, "");
    return vin.length >= 5 && vin.length <= 24 ? vin : "";
  }
  if (fieldName === "productionYear") {
    return cleanValue.match(/(?:19|20)\d{2}/)?.[0] || "";
  }
  if (fieldName === "firstRegistrationDate") {
    const iso = cleanValue.match(/^((?:19|20)\d{2})-(\d{1,2})-(\d{1,2})$/);
    const polish = cleanValue.match(/^(\d{1,2})[./-](\d{1,2})[./-]((?:19|20)\d{2})$/);
    const parts = iso
      ? [iso[1], iso[2], iso[3]]
      : polish
        ? [polish[3], polish[2], polish[1]]
        : null;
    if (!parts) return "";
    const [year, month, day] = parts.map((part) => Number(part));
    const date = new Date(Date.UTC(year, month - 1, day));
    if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) {
      return "";
    }
    return `${String(year).padStart(4, "0")}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
  }
  if (fieldName === "enginePower") {
    const number = cleanValue.match(/\d+(?:[.,]\d+)?/)?.[0] || "";
    if (!number) return "";
    if (/\bkw\b/i.test(cleanValue) || /(^| )kw( |$)/.test(label)) return `${number} kW`;
    if (/\bkm\b/i.test(cleanValue) || /(^| )km( |$)/.test(label) || /kon mechan/.test(label)) {
      return `${number} KM`;
    }
  }
  if (["mileage", "engineCapacity", "grossWeight", "seats"].includes(fieldName)) {
    if (/\d\s*[-–]\s*\d|[<>]/.test(cleanValue)) return "";
    const leadingNumber = cleanValue.match(/^\s*(\d(?:[\d\s\u00a0\u202f.,']*\d)?)/)?.[1] || "";
    const digits = leadingNumber.replace(/\D/g, "");
    return digits || "";
  }
  return cleanValue;
}

export function extractVehicleDataFromFormAnswers({
  registration,
  fields,
  values,
} = {}) {
  if (!values || typeof values !== "object") return null;
  const result = {};
  const candidates = new Map();
  const ambiguousFields = new Set();
  for (const field of Array.isArray(fields) ? fields : []) {
    if (!field?.id) continue;
    const normalizedLabel = normalizeLabel(field.label);
    const fieldName = recognizeVehicleField(normalizedLabel);
    if (!VEHICLE_DATA_FIELDS.has(fieldName)) continue;
    const answeredValue = resolveAnsweredValue(field, values[field.id]);
    const cleanValue = normalizeVehicleValue(fieldName, answeredValue, normalizedLabel);
    if (!cleanValue) continue;
    if (candidates.has(fieldName) && candidates.get(fieldName) !== cleanValue) {
      ambiguousFields.add(fieldName);
    } else {
      candidates.set(fieldName, cleanValue);
    }
  }
  for (const [fieldName, cleanValue] of candidates) {
    if (!ambiguousFields.has(fieldName)) result[fieldName] = cleanValue;
  }
  const normalizedRegistration = String(registration ?? "").toUpperCase().replace(/[^A-Z0-9]/g, "");
  if (normalizedRegistration.length >= 4) result.registration = normalizedRegistration;
  return Object.keys(result).some((fieldName) => fieldName !== "registration") ? result : null;
}

export function mergeVehicleDataWithSource(currentData, discoveredData, source) {
  if (!discoveredData || typeof discoveredData !== "object") return currentData || null;
  const current = currentData && typeof currentData === "object" ? currentData : {};
  const next = { ...current };
  const fieldSources = current.fieldSources && typeof current.fieldSources === "object"
    ? { ...current.fieldSources }
    : {};
  for (const [fieldName, rawValue] of Object.entries(discoveredData)) {
    if (fieldName === "fieldSources") continue;
    const value = String(rawValue ?? "").replace(/\s+/g, " ").trim();
    if (!value) continue;
    next[fieldName] = value;
    if (fieldName !== "registration") fieldSources[fieldName] = String(source || "calculator-input");
  }
  if (Object.keys(fieldSources).length > 0) next.fieldSources = fieldSources;
  return next;
}
