/**
 * @license
 * SPDX-License-Identifier: Apache-2.0
 */

const API_BASE = import.meta.env.VITE_FIESTA_URL || "https://fiesta.nearle.app/live/api/v1/web";

export interface CatalogueProduct {
  id: number;
  brand: string;
  product_name: string;
  category?: string;
  images?: string[];
  size?: string;
  product_sku?: string;
  price_range?: string; // display only — never an exact price
}

export interface ImportedRef {
  brand: string;
  catalogueid: number;
}

export interface ImportCatalogueProductRequest {
  tenantid: number;
  locationid: number;
  brand: string;          // bridge key part 1
  catalogueid: number;    // bridge key part 2 — the catalogue row's `id`
  categoryid: number;     // this tenant's own category
  subcategoryid: number;  // this tenant's own subcategory
  quantity: number;
  stocktype: "in" | "out";
  status: string;
  retailprice: number;
  productcost: number;
  taxpercent: number;
}

async function apiGet<T>(url: URL): Promise<{ items: T[]; total: number }> {
  const res = await fetch(url, { headers: { Accept: 'application/json' } });
  if (!res.ok) {
    throw new Error(`Catalogue API failed: ${res.status} ${res.statusText}`);
  }
  const json = await res.json();
  if (Array.isArray(json)) return { items: json, total: json.length };
  if (json && typeof json === 'object' && 'details' in json) {
    const items = json.details || [];
    const total = typeof json.total === 'number' ? json.total : items.length;
    return { items, total };
  }
  return { items: [], total: 0 };
}

// brand omitted → the entire catalogue, all brands merged.
export async function getCatalogueProducts(opts: {
  brand?: string; keyword?: string; pageno?: number; pagesize?: number;
} = {}) {
  const { brand, keyword, pageno = 1, pagesize = 50 } = opts;
  const url = new URL(`${API_BASE}/catalogue/getproducts`);
  if (brand) url.searchParams.set("brand", brand);
  if (keyword) url.searchParams.set("keyword", keyword);
  url.searchParams.set("pageno", String(pageno));
  url.searchParams.set("pagesize", String(pagesize));

  const { items, total } = await apiGet<CatalogueProduct>(url);
  return { products: items, total };
}

// brand omitted → imported refs across every brand.
export async function getImportedCatalogueRefs(tenantid: number, brand?: string) {
  const url = new URL(`${API_BASE}/products/getimportedcatalogueproducts`);
  url.searchParams.set("tenantid", String(tenantid));
  if (brand) url.searchParams.set("brand", brand);

  const { items } = await apiGet<ImportedRef>(url);
  return new Set(items.map((r) => `${r.brand}:${r.catalogueid}`));
}

/**
 * Import one or more global-catalogue products into the tenant's own catalogue.
 *
 * There is deliberately no fallback path. The previous one called
 * `createproductlocation` directly with `productid: item.catalogueid` — but a
 * catalogue id is only unique within its brand table and is NOT the tenant's own
 * productid, so the row it wrote linked stock and price to an unrelated product.
 * It also sent `retailprice`, which models.Productlocations doesn't bind (the
 * column there is `price`), so it persisted no price either. Only the import
 * service can mint a tenant productid, so when it's unavailable the right answer
 * is to surface the failure rather than write a wrong row.
 */
export async function importCatalogueProducts(items: ImportCatalogueProductRequest[]) {
  const res = await fetch(`${API_BASE}/products/importcatalogueproduct`, {
    method: "POST",
    headers: { "Content-Type": "application/json", "Accept": "application/json" },
    body: JSON.stringify(items),
  });

  let json: any = null;
  try { json = await res.json(); } catch { /* non-JSON error body */ }

  if (!res.ok || (json && typeof json === 'object' && json.status === false)) {
    throw new Error(json?.message || `Failed to import product (${res.status})`);
  }
  return json;
}

export async function removeFromStoreCatalogue(tenantid: number, locationid: number, productid: number) {
  const res = await fetch(`${API_BASE}/products/deleteproductlocation`, {
    method: "DELETE",
    headers: { "Content-Type": "application/json", "Accept": "application/json" },
    body: JSON.stringify({ tenantid, locationid, productid }),
  });
  if (!res.ok) throw new Error("Failed to remove product from store");
  const json = await res.json();
  if (json && typeof json === 'object' && 'status' in json && !json.status) {
    throw new Error(json.message || "Failed to remove product from store");
  }
  return json;
}

export interface CatalogueBrand {
  brand: string;
  product_count: number;
}

export async function getBrands() {
  const url = new URL(`${API_BASE}/catalogue/getbrands`);
  const { items } = await apiGet<CatalogueBrand>(url);
  return items;
}

export async function getProductSubcategories(tenantid: number, categoryid?: number) {
  const url = new URL(`${API_BASE}/products/getproductsubcategories`);
  url.searchParams.set("tenantid", String(tenantid));
  if (categoryid) url.searchParams.set("categoryid", String(categoryid));
  const { items } = await apiGet<{ subcategoryid: number; subcategoryname: string }>(url);
  return items;
}

export interface TenantCategory {
  categoryid: number;
  categoryname: string;
}

// Categories this tenant's own products actually use — not the global
// productcategories list, which is missing categoryids that are nonetheless
// in real use (e.g. categoryid 2), which would make the picker unusable.
export async function getTenantCategories(tenantid: number) {
  const url = new URL(`${API_BASE}/products/gettenantcategories`);
  url.searchParams.set("tenantid", String(tenantid));
  const { items } = await apiGet<TenantCategory>(url);
  return items;
}
