/* global React, window, useAuth, api, findProduct */
const { createContext: createCtx, useContext: useCtx, useState: useS, useEffect: useEf, useCallback: useCb, useMemo: useMemoC, useRef: useRf } = React;

/*
 * Корзина и избранное.
 *  - Гость: хранение в localStorage (rh_cart / rh_fav).
 *  - Вошедший: хранение в БД через api.cart / api.favorites.
 *  - При входе гостевые данные сливаются на сервер, localStorage очищается.
 * Ключ товара: "<категория>:<id>" (см. findProduct в data.jsx).
 */

const LS_CART = "rh_cart";
const LS_FAV  = "rh_fav";

function readLS(key, fallback) {
  try {
    const raw = window.localStorage.getItem(key);
    return raw ? JSON.parse(raw) : fallback;
  } catch { return fallback; }
}
function writeLS(key, value) {
  try { window.localStorage.setItem(key, JSON.stringify(value)); } catch { /* приватный режим */ }
}
function clearLS() {
  try { window.localStorage.removeItem(LS_CART); window.localStorage.removeItem(LS_FAV); } catch { /* */ }
}

// Нормализуем корзину: [{key, qty}], qty 1..99, дубликаты схлопываем (берём первый).
function normalizeCart(arr) {
  const out = [];
  const seen = new Set();
  for (const it of arr || []) {
    if (!it || !it.key || seen.has(it.key)) continue;
    seen.add(it.key);
    out.push({ key: it.key, qty: Math.max(1, Math.min(99, parseInt(it.qty, 10) || 1)) });
  }
  return out;
}

const CartContext = createCtx(null);

function CartProvider({ children }) {
  const auth = useAuth();
  const [cart, setCart] = useS(() => normalizeCart(readLS(LS_CART, [])));
  const [favorites, setFavorites] = useS(() => readLS(LS_FAV, []).filter(Boolean));
  const prevAuthed = useRf(null);

  // Синхронизация хранилища при смене состояния авторизации.
  useEf(() => {
    if (auth.isLoading) return;
    let cancelled = false;

    async function sync() {
      if (auth.isAuthed) {
        // Переход гость -> вошёл: сольём локальные данные на сервер.
        const localCart = readLS(LS_CART, []);
        const localFav = readLS(LS_FAV, []);
        try {
          let cartRes, favRes;
          if (localCart.length) cartRes = await api.cart.merge(localCart);
          else cartRes = await api.cart.get();
          if (localFav.length) favRes = await api.favorites.merge(localFav);
          else favRes = await api.favorites.get();
          if (cancelled) return;
          setCart(normalizeCart(cartRes.items));
          setFavorites((favRes.keys || []).filter(Boolean));
          clearLS();
        } catch { /* сервер недоступен - оставляем что есть */ }
      } else if (prevAuthed.current) {
        // Только что вышли: показываем пустые локальные данные.
        setCart(normalizeCart(readLS(LS_CART, [])));
        setFavorites(readLS(LS_FAV, []).filter(Boolean));
      }
      prevAuthed.current = auth.isAuthed;
    }
    sync();
    return () => { cancelled = true; };
  }, [auth.isAuthed, auth.isLoading]);

  // Гостю пишем в localStorage при каждом изменении.
  useEf(() => { if (!auth.isAuthed) writeLS(LS_CART, cart); }, [cart, auth.isAuthed]);
  useEf(() => { if (!auth.isAuthed) writeLS(LS_FAV, favorites); }, [favorites, auth.isAuthed]);

  // --- Мутации корзины ---
  const addToCart = useCb((key, delta = 1) => {
    setCart(prev => {
      const found = prev.find(c => c.key === key);
      const nextQty = Math.max(1, Math.min(99, (found ? found.qty : 0) + delta));
      const next = found
        ? prev.map(c => c.key === key ? { ...c, qty: nextQty } : c)
        : [...prev, { key, qty: nextQty }];
      if (auth.isAuthed) api.cart.set(key, nextQty).catch(() => {});
      return next;
    });
  }, [auth.isAuthed]);

  const setQty = useCb((key, qty) => {
    const q = Math.max(0, Math.min(99, parseInt(qty, 10) || 0));
    if (q <= 0) { removeFromCart(key); return; }
    setCart(prev => {
      const next = prev.some(c => c.key === key)
        ? prev.map(c => c.key === key ? { ...c, qty: q } : c)
        : [...prev, { key, qty: q }];
      if (auth.isAuthed) api.cart.set(key, q).catch(() => {});
      return next;
    });
  }, [auth.isAuthed]);

  const removeFromCart = useCb((key) => {
    setCart(prev => prev.filter(c => c.key !== key));
    if (auth.isAuthed) api.cart.remove(key).catch(() => {});
  }, [auth.isAuthed]);

  const clearCart = useCb(() => {
    setCart([]);
    if (auth.isAuthed) api.cart.clear().catch(() => {});
  }, [auth.isAuthed]);

  // Удалить из корзины конкретный набор ключей (после оформления заявки/оплаты).
  const removeKeys = useCb((keys) => {
    const set = new Set(keys);
    setCart(prev => prev.filter(c => !set.has(c.key)));
    if (auth.isAuthed) keys.forEach(k => api.cart.remove(k).catch(() => {}));
  }, [auth.isAuthed]);

  // --- Избранное ---
  const isFav = useCb((key) => favorites.includes(key), [favorites]);
  const toggleFav = useCb((key) => {
    setFavorites(prev => {
      const has = prev.includes(key);
      const next = has ? prev.filter(k => k !== key) : [...prev, key];
      if (auth.isAuthed) {
        (has ? api.favorites.remove(key) : api.favorites.add(key)).catch(() => {});
      }
      return next;
    });
  }, [auth.isAuthed]);

  // --- Производные данные ---
  const cartItems = useMemoC(() =>
    cart.map(c => {
      const p = findProduct(c.key);
      return p ? { ...p, qty: c.qty } : null;
    }).filter(Boolean), [cart]);

  const favItems = useMemoC(() =>
    favorites.map(k => findProduct(k)).filter(Boolean), [favorites]);

  const cartCount = useMemoC(() => cart.reduce((s, c) => s + c.qty, 0), [cart]);

  const value = {
    cart, cartItems, cartCount,
    favorites, favItems, favCount: favorites.length,
    addToCart, setQty, removeFromCart, clearCart, removeKeys,
    isFav, toggleFav,
  };
  return <CartContext.Provider value={value}>{children}</CartContext.Provider>;
}

function useCart() {
  const ctx = useCtx(CartContext);
  if (!ctx) throw new Error("useCart must be used inside CartProvider");
  return ctx;
}

/* =========================================================
   Контролы карточек: сердечко (избранное) и «В корзину».
   stopPropagation - чтобы клик не уводил на навигацию карточки.
   ========================================================= */
function FavHeart({ keyId, style }) {
  const { isFav, toggleFav } = useCart();
  const active = isFav(keyId);
  const [hover, setHover] = useS(false);
  return (
    <button
      onClick={(e) => { e.stopPropagation(); toggleFav(keyId); }}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      aria-label={active ? "Убрать из избранного" : "В избранное"}
      title={active ? "В избранном" : "В избранное"}
      style={{
        all: "unset", cursor: "pointer",
        width: 38, height: 38, borderRadius: "50%",
        display: "flex", alignItems: "center", justifyContent: "center",
        background: "rgba(248,243,234,0.92)",
        boxShadow: "0 1px 6px rgba(0,0,0,0.12)",
        backdropFilter: "blur(6px)",
        transition: "transform 180ms ease",
        transform: hover ? "scale(1.08)" : "scale(1)",
        ...style,
      }}
    >
      <svg width="19" height="19" viewBox="0 0 24 24"
        fill={active ? "var(--accent)" : "none"}
        stroke={active ? "var(--accent)" : "rgba(0,0,0,0.55)"}
        strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
        <path d="M19.5 12.572l-7.5 7.428l-7.5 -7.428a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" />
      </svg>
    </button>
  );
}

function AddToCartButton({ keyId, full, style }) {
  const { addToCart, cart } = useCart();
  const inCart = cart.some(c => c.key === keyId);
  const [justAdded, setJustAdded] = useS(false);
  const [hover, setHover] = useS(false);
  const onClick = (e) => {
    e.stopPropagation();
    addToCart(keyId, 1);
    setJustAdded(true);
    setTimeout(() => setJustAdded(false), 1200);
  };
  const label = justAdded ? "Добавлено ✓" : inCart ? "Ещё одну" : "В корзину";
  return (
    <button
      onClick={onClick}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        all: "unset", cursor: "pointer", textAlign: "center",
        fontFamily: "'Manrope', sans-serif", fontSize: 11.5, letterSpacing: "0.16em",
        textTransform: "uppercase",
        padding: "11px 16px",
        border: "1px solid var(--ink)",
        color: hover || justAdded ? "var(--cream)" : "var(--ink)",
        background: hover || justAdded ? "var(--ink)" : "transparent",
        transition: "background 180ms ease, color 180ms ease",
        display: full ? "block" : "inline-block",
        width: full ? "100%" : "auto",
        boxSizing: "border-box",
        ...style,
      }}
    >{label}</button>
  );
}

Object.assign(window, { CartProvider, useCart, FavHeart, AddToCartButton });
