// PepLab Co — Cart store
// External store consumed via React.useSyncExternalStore (React 18).
// State persists to localStorage under key `peplab-cart-v1`.

const CART_KEY = "peplab-cart-v1";
const MAX_QTY = 10;

// ─── Shipping config ──────────────────────────────────────────────────────────
// Keep in sync with backend (api/checkout.js)
const PEPLAB_SHIPPING = {
  regions: [
    { id: "vina-del-mar", label: "Viña del Mar", cost: 0 },
    { id: "rm", label: "Región Metropolitana", cost: 5000 },
    { id: "valparaiso-otra", label: "Valparaíso (resto)", cost: 5000 },
    { id: "norte", label: "Norte de Chile", cost: 5000 },
    { id: "centro", label: "Centro de Chile", cost: 5000 },
    { id: "sur", label: "Sur de Chile", cost: 5000 },
    { id: "extremo", label: "Aysén / Magallanes", cost: 5000 },
  ],
  defaultRegion: null, // null = sin elegir aún
  freeShippingRegion: "vina-del-mar",
  freeShippingPromo: {
    // promo: at least one peptide + at least one water-bact
    peptideSlugs: ["ghk-cu", "tirzepatida", "retatruide"],
    requiresSlug: "agua-bacteriostatica",
  },
};

// ─── Helpers ──────────────────────────────────────────────────────────────────
function getProduct(slug) {
  return (window.PEPLAB_PRODUCTS || []).find((p) => p.slug === slug);
}

function loadFromStorage() {
  try {
    const raw = window.localStorage && localStorage.getItem(CART_KEY);
    if (!raw) return { items: [], region: PEPLAB_SHIPPING.defaultRegion, lastAdded: null };
    const parsed = JSON.parse(raw);
    return {
      items: Array.isArray(parsed.items) ? parsed.items : [],
      region: typeof parsed.region === "string" ? parsed.region : null,
      // lastAdded is in-memory only — don't restore from storage (avoid stale toast on reload)
      lastAdded: null,
    };
  } catch (e) {
    return { items: [], region: null, lastAdded: null };
  }
}

function persist(state) {
  try {
    // Persist only items + region, NOT lastAdded (it's UI-event-only)
    const { items, region } = state;
    localStorage.setItem(CART_KEY, JSON.stringify({ items, region }));
  } catch (e) {
    /* storage may be full or disabled */
  }
}

// ─── Pure shipping calculation ────────────────────────────────────────────────
// Same algorithm should run server-side in api/checkout.js
function hasFreeShippingPromo(items) {
  const slugs = new Set(items.map((i) => i.slug));
  const hasPeptide = PEPLAB_SHIPPING.freeShippingPromo.peptideSlugs.some((s) =>
    slugs.has(s)
  );
  const hasWater = slugs.has(PEPLAB_SHIPPING.freeShippingPromo.requiresSlug);
  return hasPeptide && hasWater;
}

function calcShipping(items, region) {
  if (!items || items.length === 0) return 0;
  if (region === PEPLAB_SHIPPING.freeShippingRegion) return 0;
  if (hasFreeShippingPromo(items)) return 0;
  if (!region) return null; // unknown — UI shows "selecciona región"
  const r = PEPLAB_SHIPPING.regions.find((x) => x.id === region);
  return r ? r.cost : 5000;
}

// ─── Store ────────────────────────────────────────────────────────────────────
let state = loadFromStorage();
const subscribers = new Set();

function setState(updater) {
  const next = typeof updater === "function" ? updater(state) : updater;
  // Immutable update — always new reference
  state = { items: next.items, region: next.region, lastAdded: next.lastAdded ?? null };
  persist(state);
  subscribers.forEach((fn) => fn());
}

const cart = {
  getSnapshot: () => state,
  subscribe(fn) {
    subscribers.add(fn);
    return () => subscribers.delete(fn);
  },

  addItem(slug, qty = 1) {
    if (!slug) return;
    const product = getProduct(slug);
    if (!product || !product.available) return;
    setState((s) => {
      const existing = s.items.find((i) => i.slug === slug);
      const newItems = existing
        ? s.items.map((i) =>
            i.slug === slug
              ? { ...i, quantity: Math.min(MAX_QTY, i.quantity + qty) }
              : i
          )
        : [...s.items, { slug, quantity: Math.min(MAX_QTY, Math.max(1, qty)) }];
      return {
        ...s,
        items: newItems,
        // Trigger Toast — unique ts ensures repeated adds of same slug still fire
        lastAdded: { slug, ts: Date.now() },
      };
    });
  },

  // Manually dismiss the toast (called by Toast when CTA is clicked or auto-dismiss fires)
  clearLastAdded() {
    setState((s) => ({ ...s, lastAdded: null }));
  },

  removeItem(slug) {
    setState((s) => ({ ...s, items: s.items.filter((i) => i.slug !== slug) }));
  },

  setQuantity(slug, qty) {
    const q = parseInt(qty, 10);
    if (isNaN(q) || q <= 0) return cart.removeItem(slug);
    setState((s) => ({
      ...s,
      items: s.items.map((i) =>
        i.slug === slug ? { ...i, quantity: Math.min(MAX_QTY, q) } : i
      ),
    }));
  },

  incrementItem(slug) {
    setState((s) => ({
      ...s,
      items: s.items.map((i) =>
        i.slug === slug ? { ...i, quantity: Math.min(MAX_QTY, i.quantity + 1) } : i
      ),
    }));
  },

  decrementItem(slug) {
    setState((s) => {
      const existing = s.items.find((i) => i.slug === slug);
      if (!existing) return s;
      if (existing.quantity <= 1) {
        return { ...s, items: s.items.filter((i) => i.slug !== slug) };
      }
      return {
        ...s,
        items: s.items.map((i) =>
          i.slug === slug ? { ...i, quantity: i.quantity - 1 } : i
        ),
      };
    });
  },

  setRegion(region) {
    setState((s) => ({ ...s, region: region || null }));
  },

  clear() {
    setState({ items: [], region: null });
  },

  // ─── Selectors (compute from state, no caching) ─────────────────────────────
  getTotalCount() {
    return state.items.reduce((acc, i) => acc + i.quantity, 0);
  },

  getSubtotal() {
    return state.items.reduce((acc, i) => {
      const product = getProduct(i.slug);
      return acc + (product?.priceNum || 0) * i.quantity;
    }, 0);
  },

  getShipping() {
    return calcShipping(state.items, state.region);
  },

  getTotal() {
    const shipping = cart.getShipping();
    return cart.getSubtotal() + (shipping || 0);
  },

  hasFreeShippingPromo() {
    return hasFreeShippingPromo(state.items);
  },

  isEligibleForPromoUpsell() {
    // True when cart has a peptide but is MISSING the water-bact item
    const slugs = new Set(state.items.map((i) => i.slug));
    const hasPeptide = PEPLAB_SHIPPING.freeShippingPromo.peptideSlugs.some((s) =>
      slugs.has(s)
    );
    const hasWater = slugs.has(PEPLAB_SHIPPING.freeShippingPromo.requiresSlug);
    return hasPeptide && !hasWater;
  },
};

// ─── React hook (useSyncExternalStore) ────────────────────────────────────────
function useCart() {
  return React.useSyncExternalStore(cart.subscribe, cart.getSnapshot, cart.getSnapshot);
}

// Format CLP nicely
function formatCLP(n) {
  if (n == null) return "—";
  return "$" + Number(n).toLocaleString("es-CL");
}

window.PEPLAB_CART = cart;
window.PEPLAB_SHIPPING = PEPLAB_SHIPPING;
window.useCart = useCart;
window.calcShipping = calcShipping;
window.hasFreeShippingPromo = hasFreeShippingPromo;
window.formatCLP = formatCLP;
