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

/**
 * The shared "store catalogue" — the products the **admin** has selected from the
 * global catalogue (each with a quantity). This curated list is what **store
 * users** see and pick from. It's the design-stage bridge between the admin
 * catalogue page (InventoryView) and the user catalogue page (StoreCatalogView).
 *
 * Backed entirely by the database — there is no localStorage here (an earlier
 * revision of this comment described a localStorage bridge that no longer
 * exists). Every read and write goes to Fiesta, scoped by tenant + outlet:
 *   • read   → GET    /products/getlocationproducts    (useFiestaProductLocations)
 *   • add / update qty / update price
 *            → POST   /products/createproductlocation
 *   • remove → DELETE /products/deleteproductlocation
 *
 * Mutations invalidate the React Query cache, so admin edits show up on the
 * store user's catalogue on its next fetch.
 */

import {
  useFiestaProductLocations,
  useFiestaCreateProductLocation,
  useFiestaCreateProductLocations,
  useFiestaDeleteProductLocation,
} from './fiestaQueries';
import { FIESTA_TENANT_ID, FIESTA_PRIMARY_LOCATION_ID } from './fiestaApi';

export interface StoreCatalogueItem {
  productid: string;
  name: string;
  image: string;
  category: string;
  sku?: string;
  price: number;
  unit: string;
  /** Quantity the admin intends to stock for this product. */
  qty: number;
  /**
   * The row's status as the backend reports it — NOT a publish/unpublish flag.
   *
   * This field is overloaded. We write 'Active' when publishing, but the
   * backend later overwrites it with a stock-availability value ('available',
   * 'outofstock'), so a published product does not stay 'Active'. Membership of
   * this list IS publication; treat status as display metadata only and never
   * as a visibility gate. Use `isPublishedItem` / `isRemovedStatus` instead.
   */
  status: string;
}

/**
 * Statuses that mean the row is no longer part of the store catalogue.
 *
 * Deliberately a small deny-list rather than an 'Active' allow-list: the
 * backend mixes lifecycle values ('Active') with availability values
 * ('available', 'outofstock') in the same field, so anything not explicitly
 * removed is still catalogued — an out-of-stock product is still on the menu.
 */
const REMOVED_STATUSES = new Set(['inactive', 'deleted', 'removed', 'archived']);

export function isRemovedStatus(status: unknown): boolean {
  return REMOVED_STATUSES.has(String(status ?? '').trim().toLowerCase());
}

/**
 * Is this product published to the store catalogue? A product-location row
 * exists for it and has not been removed — that is the whole test. It stays
 * published, whatever its stock level, until the admin deletes it.
 */
export function isPublishedItem(item: StoreCatalogueItem | undefined | null): boolean {
  return Boolean(item) && !isRemovedStatus(item!.status);
}

/**
 * Set one product's selling price at EVERY outlet of a tenant.
 *
 * The price lives on `productlocations`, which is keyed per outlet, so a single
 * write only ever priced one branch — and the admin catalogue was hardwired to
 * `locations[0]`, meaning branches 2..N stayed at ₹0 and their staff (and the
 * customer app) saw no price at all. Pricing is a business-level decision here:
 * the admin sets it once and every store carries it.
 *
 * One request for all outlets, not N — `createproductlocation` accepts an array
 * and upserts each row. Outlets that don't stock the product yet get a row at
 * quantity 0, which lists it without inventing stock.
 */
export function usePriceEverywhere(tenantid: number = FIESTA_TENANT_ID) {
  const mutation = useFiestaCreateProductLocations();

  const priceEverywhere = (
    productid: number | string,
    price: number,
    locationIds: number[],
    opts?: { status?: string; onSuccess?: () => void; onError?: (e: Error) => void },
  ) => {
    const outlets = [...new Set(locationIds.filter((id) => id > 0))];
    if (!outlets.length || !Number(productid)) return;
    mutation.mutate(
      outlets.map((locationid) => ({
        tenantid,
        locationid,
        productid: Number(productid),
        price,
        status: opts?.status || 'Active',
      })),
      { onSuccess: () => opts?.onSuccess?.(), onError: (e: any) => opts?.onError?.(e) },
    );
  };

  return { priceEverywhere, isPending: mutation.isPending };
}

/**
 * Live view of the store catalogue + curation helpers. Re-renders whenever the
 * catalogue changes via React Query invalidation.
 */
export function useStoreCatalogue(tenantid: number = FIESTA_TENANT_ID, locationid: number = FIESTA_PRIMARY_LOCATION_ID) {
  const q = useFiestaProductLocations({
    tenantid,
    locationid,
    pagesize: 500,
  });

  const items: StoreCatalogueItem[] = (q.data || []).filter((r: any) => !isRemovedStatus(r.status)).map((r: any) => ({
    productid: String(r.productid),
    name: String(r.name || r.productname || ''),
    image: String(r.image || r.productimage || ''),
    category: String(r.category || r.categoryname || 'General'),
    // The row's columns are `productsku` / `productunit` — the bare `sku` /
    // `unit` names don't exist on it, so a real SKU "PEPSIC-CHE-100-002"
    // rendered as "SKU-7075" and a 100g unit rendered as "Pc".
    sku: String(r.productsku || r.sku || ''),
    // Per-store price (productlocations.price) wins; `retailprice` is the
    // master price on the products row and is the fallback for an outlet that
    // hasn't set its own.
    price: Number(r.price || r.retailprice || 0),
    unit: String(r.productunit || r.unit || ''),
    qty: Number(r.quantity ?? r.qty ?? 0),
    status: String(r.status || 'Draft').charAt(0).toUpperCase() + String(r.status || 'Draft').slice(1).toLowerCase(),
  }));

  const mutation = useFiestaCreateProductLocation();
  const deleteMutation = useFiestaDeleteProductLocation();

  const has = (id: string) => items.some((i) => i.productid === id);
  const getQty = (id: string) => items.find((i) => i.productid === id)?.qty ?? 0;
  
  const add = (item: StoreCatalogueItem) => {
    mutation.mutate({
      tenantid,
      locationid,
      productid: Number(item.productid),
      qty: item.qty,
      price: item.price,
      status: item.status || 'Active'
    });
  };
  
  const remove = (id: string) => {
    const item = items.find(i => i.productid === id);
    if (!item) return;
    deleteMutation.mutate({
      tenantid,
      locationid,
      productid: Number(id)
    });
  };
  
  const setQty = (id: string, qty: number) => {
    const item = items.find(i => i.productid === id);
    if (!item) return;
    const safeQty = Math.max(1, Math.round(qty) || 1);
    mutation.mutate({
      tenantid,
      locationid,
      productid: Number(id),
      qty: safeQty,
      price: item.price,
      status: item.status || 'Active'
    });
  };
  
  const setPrice = (id: string, price: number) => {
    const item = items.find(i => i.productid === id);
    if (!item) return;
    mutation.mutate({
      tenantid,
      locationid,
      productid: Number(id),
      qty: item.qty || 0,
      price: price,
      status: 'Active' // Setting a price activates it
    });
  };

  return { items, has, getQty, add, remove, setQty, setPrice, isLoading: q.isLoading };
}
