import {
  cartLocalStorageKey,
  parseStoredCartLines,
  type CartLine,
} from "@/data/cart";

const CART_UPDATED_EVENT = "sasico-cart-updated";

export function persistCartLines(next: CartLine[]) {
  try {
    if (typeof globalThis.window === "undefined") return;
    globalThis.localStorage.setItem(cartLocalStorageKey, JSON.stringify(next));
    globalThis.window.dispatchEvent(new Event(CART_UPDATED_EVENT));
  } catch {
    /* ignore */
  }
}

/** Merges into the same persisted cart used on the shop and cart pages. */
export function addProductToCartById(productId: string) {
  let lines: CartLine[] = [];
  try {
    const raw = globalThis.localStorage.getItem(cartLocalStorageKey);
    if (raw) {
      const parsed = parseStoredCartLines(JSON.parse(raw) as unknown);
      if (parsed !== null) lines = parsed;
    }
  } catch {
    lines = [];
  }

  const idx = lines.findIndex((l) => l.productId === productId);
  if (idx >= 0) {
    const next = [...lines];
    next[idx] = {
      ...next[idx],
      quantity: Math.min(99, next[idx].quantity + 1),
    };
    persistCartLines(next);
  } else {
    persistCartLines([...lines, { productId, quantity: 1 }]);
  }
}

const CART_QTY_MAX = 99;

/**
 * Adds `quantity` units to the cart line for this product (merges with
 * existing quantity, capped at 99). Used on product detail "Add to cart".
 */
export function addProductQuantityToCart(productId: string, quantity: number) {
  const n = Math.floor(quantity);
  if (!Number.isFinite(n) || n < 1) return;
  const toAdd = Math.min(CART_QTY_MAX, n);

  let lines: CartLine[] = [];
  try {
    const raw = globalThis.localStorage.getItem(cartLocalStorageKey);
    if (raw) {
      const parsed = parseStoredCartLines(JSON.parse(raw) as unknown);
      if (parsed !== null) lines = parsed;
    }
  } catch {
    lines = [];
  }

  const idx = lines.findIndex((l) => l.productId === productId);
  if (idx >= 0) {
    const next = [...lines];
    next[idx] = {
      ...next[idx],
      quantity: Math.min(CART_QTY_MAX, next[idx].quantity + toAdd),
    };
    persistCartLines(next);
  } else {
    persistCartLines([...lines, { productId, quantity: toAdd }]);
  }
}

/**
 * Sets an exact quantity for a cart line (creates line if missing).
 */
export function setProductCartQuantity(productId: string, quantity: number) {
  const n = Math.floor(quantity);
  if (!Number.isFinite(n)) return;
  const nextQty = Math.min(CART_QTY_MAX, Math.max(1, n));

  let lines: CartLine[] = [];
  try {
    const raw = globalThis.localStorage.getItem(cartLocalStorageKey);
    if (raw) {
      const parsed = parseStoredCartLines(JSON.parse(raw) as unknown);
      if (parsed !== null) lines = parsed;
    }
  } catch {
    lines = [];
  }

  const idx = lines.findIndex((l) => l.productId === productId);
  if (idx >= 0) {
    const next = [...lines];
    next[idx] = { ...next[idx], quantity: nextQty };
    persistCartLines(next);
  } else {
    persistCartLines([...lines, { productId, quantity: nextQty }]);
  }
}

/**
 * Returns true when this product already exists in persisted cart lines.
 */
export function isProductInCart(productId: string): boolean {
  try {
    if (typeof globalThis.window === "undefined") return false;
    const raw = globalThis.localStorage.getItem(cartLocalStorageKey);
    if (!raw) return false;
    const parsed = parseStoredCartLines(JSON.parse(raw) as unknown);
    if (parsed === null) return false;
    return parsed.some((line) => line.productId === productId);
  } catch {
    return false;
  }
}

export function getProductCartQuantity(productId: string): number {
  try {
    if (typeof globalThis.window === "undefined") return 0;
    const raw = globalThis.localStorage.getItem(cartLocalStorageKey);
    if (!raw) return 0;
    const parsed = parseStoredCartLines(JSON.parse(raw) as unknown);
    if (parsed === null) return 0;
    const line = parsed.find((item) => item.productId === productId);
    return line?.quantity ?? 0;
  } catch {
    return 0;
  }
}

export function subscribeCartChanges(onStoreChange: () => void): () => void {
  if (typeof globalThis.window === "undefined") return () => {};
  const onStorage = (e: StorageEvent) => {
    if (e.key === null || e.key === cartLocalStorageKey) onStoreChange();
  };
  const onCartUpdated = () => onStoreChange();
  globalThis.window.addEventListener("storage", onStorage);
  globalThis.window.addEventListener(CART_UPDATED_EVENT, onCartUpdated);
  return () => {
    globalThis.window.removeEventListener("storage", onStorage);
    globalThis.window.removeEventListener(CART_UPDATED_EVENT, onCartUpdated);
  };
}
