import {
  normalizeAccessory,
  normalizeGlassType,
  normalizeIron,
  normalizeProfile,
  normalizeDoorPanel,
  unwrapCollection,
  denormalizeProfile,
  denormalizeIron,
  denormalizeGlassType,
  denormalizeAccessory,
  denormalizeDoorPanel,
} from "./apiNormalize";

import {
  AccessoriesApi,
  DoorPanelsApi,
  GlassTypesApi,
  IronsApi,
  ProfilesApi,
} from "../api/materials";

import { DEFAULT_MATERIALS } from "../constants/pvc";

/**
 * Fetch all materials from DB and convert to UI shape.
 */
export async function fetchAllMaterials() {
  const [p, i, g, a, d] = await Promise.all([
    ProfilesApi.list({ per_page: 200 }),
    IronsApi.list({ per_page: 200 }),
    GlassTypesApi.list({ per_page: 200 }),
    AccessoriesApi.list({ per_page: 200 }),
    DoorPanelsApi.list({ per_page: 200 }),
  ]);

  return {
    profiles: unwrapCollection(p.data).map(normalizeProfile),
    irons: unwrapCollection(i.data).map(normalizeIron),
    glassTypes: unwrapCollection(g.data).map(normalizeGlassType),
    accessories: unwrapCollection(a.data).map(normalizeAccessory),
    doorPanels: unwrapCollection(d.data).map(normalizeDoorPanel),
  };
}

/**
 * Seed default materials into DB if a category is empty.
 * Safe to call on startup.
 */
export async function ensureSeedMaterials(current) {
  const cur = current || { profiles: [], irons: [], glassTypes: [], accessories: [], doorPanels: [] };

  const jobs = [];

  if (!cur.profiles?.length) {
    for (const it of DEFAULT_MATERIALS.profiles) jobs.push(ProfilesApi.create(denormalizeProfile(it)));
  }
  if (!cur.irons?.length) {
    for (const it of DEFAULT_MATERIALS.irons) jobs.push(IronsApi.create(denormalizeIron(it)));
  }
  if (!cur.glassTypes?.length) {
    for (const it of DEFAULT_MATERIALS.glassTypes) jobs.push(GlassTypesApi.create(denormalizeGlassType(it)));
  }

  await Promise.allSettled(jobs);
  return fetchAllMaterials();
}

function toDoorPanelPayload(uiItem) {
  // If a file is present, send multipart.
  if (uiItem?.file instanceof File) {
    const fd = new FormData();
    fd.append("name", (uiItem?.name ?? "").trim());
    fd.append("price", String(Number(uiItem?.price ?? 0)));
    fd.append("image", uiItem.file);
    return fd;
  }
  return denormalizeDoorPanel(uiItem);
}

export async function createMaterial(kind, uiItem) {
  switch (kind) {
    case "profiles":
      await ProfilesApi.create(denormalizeProfile(uiItem));
      break;
    case "irons":
      await IronsApi.create(denormalizeIron(uiItem));
      break;
    case "glassTypes":
      await GlassTypesApi.create(denormalizeGlassType(uiItem));
      break;
    case "accessories":
      await AccessoriesApi.create(denormalizeAccessory(uiItem));
      break;
    case "doorPanels":
      await DoorPanelsApi.create(toDoorPanelPayload(uiItem));
      break;
    default:
      throw new Error("Unknown material kind: " + kind);
  }
  return fetchAllMaterials();
}

export async function updateMaterial(kind, id, uiItem) {
  switch (kind) {
    case "profiles":
      await ProfilesApi.update(id, denormalizeProfile(uiItem));
      break;
    case "irons":
      await IronsApi.update(id, denormalizeIron(uiItem));
      break;
    case "glassTypes":
      await GlassTypesApi.update(id, denormalizeGlassType(uiItem));
      break;
    case "accessories":
      await AccessoriesApi.update(id, denormalizeAccessory(uiItem));
      break;
    case "doorPanels":
      await DoorPanelsApi.update(id, toDoorPanelPayload(uiItem));
      break;
    default:
      throw new Error("Unknown material kind: " + kind);
  }
  return fetchAllMaterials();
}

export async function deleteMaterial(kind, id) {
  switch (kind) {
    case "profiles":
      await ProfilesApi.remove(id);
      break;
    case "irons":
      await IronsApi.remove(id);
      break;
    case "glassTypes":
      await GlassTypesApi.remove(id);
      break;
    case "accessories":
      await AccessoriesApi.remove(id);
      break;
    case "doorPanels":
      await DoorPanelsApi.remove(id);
      break;
    default:
      throw new Error("Unknown material kind: " + kind);
  }
  return fetchAllMaterials();
}
