// Convert Laravel Resource responses to the UI shape used in this app.
// Laravel resources are like: { id, attributes: {...}, created_at, updated_at, positions: {data:[...] } }

export function toStrId(v) {
  if (v === null || v === undefined) return "";
  return String(v);
}

export function snakeToCamelKey(k) {
  return k.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
}

export function camelToSnakeKey(k) {
  return k.replace(/[A-Z]/g, (m) => `_${m.toLowerCase()}`);
}

export function mapAttributes(attrs, mapperKeyFn) {
  const out = {};
  Object.keys(attrs || {}).forEach((k) => {
    out[mapperKeyFn(k)] = attrs[k];
  });
  return out;
}

// ---- Materials ----
export function normalizeProfile(resource) {
  const a = resource?.attributes || {};
  return {
    id: toStrId(resource?.id),
    name: a.name ?? "",
    pricePerM: Number(a.price_per_m ?? a.pricePerM ?? 0),
  };
}

export function normalizeIron(resource) {
  const a = resource?.attributes || {};
  return {
    id: toStrId(resource?.id),
    name: a.name ?? "",
    pricePerM: Number(a.price_per_m ?? a.pricePerM ?? 0),
  };
}

export function normalizeGlassType(resource) {
  const a = resource?.attributes || {};
  return {
    id: toStrId(resource?.id),
    name: a.name ?? "",
    pricePerM2: Number(a.price_per_m2 ?? a.pricePerM2 ?? 0),
  };
}

export function normalizeAccessory(resource) {
  const a = resource?.attributes || {};
  return {
    id: toStrId(resource?.id),
    name: a.name ?? "",
    unit: a.unit ?? "pcs",
    price: Number(a.price ?? 0),
  };
}

export function denormalizeProfile(ui) {
  return {
    name: (ui?.name ?? "").trim(),
    price_per_m: Number(ui?.pricePerM ?? 0),
  };
}

export function denormalizeIron(ui) {
  return {
    name: (ui?.name ?? "").trim(),
    price_per_m: Number(ui?.pricePerM ?? 0),
  };
}

export function denormalizeGlassType(ui) {
  return {
    name: (ui?.name ?? "").trim(),
    price_per_m2: Number(ui?.pricePerM2 ?? 0),
  };
}

export function denormalizeAccessory(ui) {
  return {
    name: (ui?.name ?? "").trim(),
    unit: ui?.unit ?? "pcs",
    price: Number(ui?.price ?? 0),
  };
}

// ---- Offers ----
// Keep positions payload keys as-is (your DB columns must match keys you send).
export function normalizePosition(pos) {
  const a = pos?.attributes || {};
  // Keep attributes as-is, but add id as string
  return { id: toStrId(pos?.id), ...a };
}

export function normalizeOffer(resource) {
  const a = resource?.attributes || {};
  const positionsData =
    resource?.positions?.data ?? resource?.positions ?? resource?.positions_data ?? [];
  const positions = Array.isArray(positionsData) ? positionsData.map(normalizePosition) : [];

  // Map common columns to UI fields (if your offers table has these)
  const profileId = toStrId(a.profile_id ?? a.profileId ?? "");
  const ironId = toStrId(a.iron_id ?? a.ironId ?? "");

  return {
    id: toStrId(resource?.id),
    name: a.name ?? a.title ?? `Oferta #${toStrId(resource?.id)}`,
    description: a.description ?? "",
    margin: Number(a.margin ?? 20),
    color: a.color ?? "[BB] Bardhë-Bardhë",
    profileId,
    ironId,
    createdAt: resource?.created_at ?? new Date().toISOString(),
    updatedAt: resource?.updated_at ?? new Date().toISOString(),
    positions,
    // keep any extra attrs too (so you don't lose data)
    __attrs: a,
  };
}

export function denormalizeOffer(uiOffer) {
  // Convert UI offer to backend offer payload (snake_case for common fields).
  const offer = uiOffer || {};
  const out = {
    name: (offer.name ?? "").trim(),
    description: (offer.description ?? "").trim(),
    margin: Number(offer.margin ?? 0),
    color: offer.color ?? null,
    profile_id: offer.profileId ? Number(offer.profileId) || offer.profileId : null,
    iron_id: offer.ironId ? Number(offer.ironId) || offer.ironId : null,
  };

  // If you have additional offer fields stored in __attrs, preserve them (but don't overwrite the mapped keys).
  const extra = offer.__attrs || {};
  Object.keys(extra).forEach((k) => {
    if (!(k in out)) out[k] = extra[k];
  });

  // Remove nulls to avoid filtering issues on backend
  Object.keys(out).forEach((k) => {
    if (out[k] === null || out[k] === undefined || out[k] === "") delete out[k];
  });

  return out;
}

export function denormalizePositions(uiPositions) {
  const arr = Array.isArray(uiPositions) ? uiPositions : [];
  return arr.map((p) => {
    const copy = { ...p };
    // backend expects numeric id if present; ok to send string - Laravel will cast
    if (copy.id === "" || copy.id === null || copy.id === undefined) delete copy.id;
    return copy;
  });
}

// Helpers for Laravel paginate
export function unwrapCollection(respData) {
  // respData: {data:[], meta, links} or already array
  if (!respData) return [];
  if (Array.isArray(respData)) return respData;
  if (Array.isArray(respData.data)) return respData.data;
  return [];
}


export function normalizeDoorPanel(resource) {
  const a = resource?.attributes || {};
  return {
    id: toStrId(resource?.id),
    name: a.name ?? "",
    // EXTRA cost (not per-m)
    price: Number(a.price ?? 0),
    imagePath: a.image_path ?? a.imagePath ?? null,
    imageUrl: a.image_url ?? a.imageUrl ?? null,
  };
}
export function denormalizeDoorPanel(ui) {
  return {
    name: ui.name,
    price: Number(ui.price ?? 0),
  };
}