// Shared shop state — cart + view + filters + lang. Each variation calls

// Effective price helper: if product is today's daily deal, returns deal_price.
// Falls back to base price. Exposed on window so any variation can use it.
window.furyEffectivePrice = function (p) {
  if (!p) return 0;
  var deal = window.FURY_DAILY_DEAL;
  if (deal && deal.product_id === p.id && !deal.redeemed_today && typeof deal.deal_price === "number") {
    return deal.deal_price;
  }
  return p.price;
};
// Total for one cart line. Only the FIRST unit of today's deal product
// is discounted; subsequent units of the same product are charged at base.
// Once the user has already redeemed the deal today, no discount at all.
window.furyLineTotal = function (p, qty) {
  if (!p || !qty || qty < 1) return 0;
  var deal = window.FURY_DAILY_DEAL;
  if (deal && deal.product_id === p.id && !deal.redeemed_today && typeof deal.deal_price === "number") {
    return deal.deal_price + p.price * (qty - 1);
  }
  return p.price * qty;
};

// useShop() to get the same hook shape but renders its own visuals.

(function () {
  const { useState, useEffect, useMemo, useCallback } = React;

  // Force re-render when language flips (Tweaks panel posts an event), or
  // when fury-api.js swaps PROFILE / SERVERS / PRODUCTS with live backend data.
  function useLang() {
    const [, force] = useState(0);
    useEffect(() => {
      const onChange = () => force((x) => x + 1);
      window.addEventListener('fury:lang', onChange);
      window.addEventListener('fury:data', onChange);
      return () => {
        window.removeEventListener('fury:lang', onChange);
        window.removeEventListener('fury:data', onChange);
      };
    }, []);
    return window.FURY_lang();
  }

  function useShop(initialView) {
    const lang = useLang();
    // Bumped from useLang on every fury:data event. Used as a useMemo dep so
    // memoised lookups against window.FURY_PRODUCTS recompute after fury-api
    // swaps the array.
    const dataVer = window.__furyDataVersion || 0;
    const t = window.FURY_I18N[lang];
    // Запоминаем последний открытый view в localStorage — чтобы после Ctrl+R
    // не выкидывало в магазин. Если localStorage недоступен (приватный режим
    // и т.п.) — просто используем initialView.
    const VIEW_KEY = 'fury:view';
    const ALLOWED_VIEWS = ['shop', 'profile', 'servers', 'admin', 'mail'];
    const restoredView = (() => {
      try {
        const v = window.localStorage.getItem(VIEW_KEY);
        return v && ALLOWED_VIEWS.includes(v) ? v : null;
      } catch (_) { return null; }
    })();
    const [view, setViewRaw] = useState(restoredView || initialView || 'shop');
    const setView = useCallback((v) => {
      setViewRaw(v);
      try { window.localStorage.setItem(VIEW_KEY, v); } catch (_) {}
    }, []);
    const [cat, setCat] = useState('all');
    const [search, setSearch] = useState('');
    const [sort, setSort] = useState('popular');
    const [cart, setCart] = useState({}); // {id: qty}
    const [cartOpen, setCartOpen] = useState(false);
    const [serverId, setServerId] = useState('fury-1');
    const [selectedId, setSelectedId] = useState(null);
    const [buyQty, setBuyQty] = useState(1);
    const selected = selectedId ? window.FURY_PRODUCTS.find((p) => p.id === selectedId) : null;
    const select = useCallback((id) => { setSelectedId(id); setBuyQty(1); }, []);
    const closeSelected = useCallback(() => setSelectedId(null), []);

    const products = useMemo(() => {
      let list = window.FURY_PRODUCTS.slice();
      if (cat !== 'all') list = list.filter((p) => p.cat === cat);
      const q = search.trim().toLowerCase();
      if (q) {
        list = list.filter((p) =>
          window.FURY_pname(p).toLowerCase().includes(q) || p.id.includes(q)
        );
      }
      if (sort === 'price_asc') list.sort((a, b) => a.price - b.price);
      else if (sort === 'price_desc') list.sort((a, b) => b.price - a.price);
      else if (sort === 'new') list.sort((a, b) => (b.badge === 'new' ? 1 : 0) - (a.badge === 'new' ? 1 : 0));
      else if (sort === 'name_asc')  list.sort((a, b) => window.FURY_pname(a).localeCompare(window.FURY_pname(b), 'ru'));
      else if (sort === 'name_desc') list.sort((a, b) => window.FURY_pname(b).localeCompare(window.FURY_pname(a), 'ru'));
      return list;
    }, [cat, search, sort, lang, dataVer]);

    const add = useCallback((id) => {
      // Корзина работает только для авторизованных. Гость, нажав «купить»,
      // отправляется на Steam OpenID — после возврата он залогинен и может
      // добавлять снова. Покупка в БД на сервере и так гейтится requireAuth,
      // но логичнее не давать копить нелегитимную корзину в гостевой сессии.
      const loggedIn = window.FURY_PROFILE && window.FURY_PROFILE.loggedIn !== false;
      if (!loggedIn) {
        if (window.FURY_API && window.FURY_API.login) window.FURY_API.login();
        return;
      }
      setCart((c) => {
        const prod = window.FURY_PRODUCTS.find((x) => x.id === id);
        const isSlot = prod && prod.cat === 'slots';
        // Приоритетный/слот — строго 1 за операцию, количество не наращивается.
        return { ...c, [id]: isSlot ? 1 : (c[id] || 0) + 1 };
      });
    }, []);
    const remove = useCallback((id) => {
      setCart((c) => { const n = { ...c }; delete n[id]; return n; });
    }, []);
    const setQty = useCallback((id, q) => {
      setCart((c) => {
        const n = { ...c };
        const prod = window.FURY_PRODUCTS.find((x) => x.id === id);
        const isSlot = prod && prod.cat === 'slots';
        if (q <= 0) delete n[id]; else n[id] = isSlot ? 1 : q;
        return n;
      });
    }, []);

    const cartItems = useMemo(() =>
      Object.entries(cart)
        .map(([id, qty]) => ({ p: window.FURY_PRODUCTS.find((x) => x.id === id), qty }))
        .filter((x) => x.p),
      [cart, dataVer]
    );
    const subtotal = cartItems.reduce((s, x) => s + window.furyLineTotal(x.p, x.qty), 0);
    const cartCount = cartItems.reduce((s, x) => s + x.qty, 0);
    const discount = Math.min(window.FURY_PROFILE.bonus, Math.floor(subtotal * 0.1));
    const total = Math.max(0, subtotal - discount);

    return {
      lang, t,
      view, setView,
      cat, setCat,
      search, setSearch,
      sort, setSort,
      cart, cartItems, cartCount, subtotal, discount, total,
      cartOpen, setCartOpen,
      add, remove, setQty,
      serverId, setServerId,
      products,
      profile: window.FURY_PROFILE,
      servers: window.FURY_SERVERS,
      selected, select, closeSelected, buyQty, setBuyQty,
    };
  }

  // Format integer with thin spaces as group separator.
  function fmt(n) {
    return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, '\u202F');
  }

  // Tone → tonal palette used for image placeholders so each card has a
  // distinct silhouette without external assets. Variations reuse these
  // freely or override with their own gradient.
  const TONES = {
    olive:   ['#4a5238', '#2a2e1f', '#8a9472'],
    crimson: ['#5a1818', '#1f0a0a', '#a83232'],
    rust:    ['#6b3a1c', '#2a1408', '#b06038'],
    bone:    ['#7a7466', '#3a3528', '#bdb6a0'],
    frost:   ['#3a4a5a', '#16202b', '#8aa0b8'],
    iron:    ['#3a3d40', '#16181a', '#7c8086'],
    wood:    ['#5a3a1c', '#2a1a08', '#a8743a'],
    gold:    ['#7a5a18', '#2e220a', '#d4a83a'],
  };

  function toneGrad(tone) {
    const [mid, dark, light] = TONES[tone] || TONES.iron;
    return `radial-gradient(120% 90% at 30% 30%, ${light} 0%, ${mid} 35%, ${dark} 100%)`;
  }

  // Tiny SVG glyph per category — silhouette-style, monochrome.
  function CategoryGlyph({ cat, size = 60, color = 'currentColor', opacity = 0.85 }) {
    const s = { width: size, height: size, color, opacity, display: 'block' };
    const stroke = { fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round' };
    const fill = { fill: 'currentColor' };
    const paths = {
      kits: <g {...stroke}>
        <path d="M20 18 L32 12 L44 18 L44 36 L32 44 L20 36 Z" />
        <path d="M20 18 L32 24 L44 18" /><path d="M32 24 L32 44" />
        <circle cx="32" cy="32" r="3" {...fill} />
      </g>,
      build: <g {...stroke}>
        <path d="M14 46 L14 26 L32 14 L50 26 L50 46 Z" />
        <path d="M26 46 L26 34 L38 34 L38 46" />
        <path d="M14 26 L50 26" />
      </g>,
      vehicles: <g {...stroke}>
        <path d="M12 36 L12 28 L22 22 L40 22 L48 28 L52 28 L52 38 L48 38" />
        <path d="M12 38 L20 38" /><path d="M30 38 L40 38" />
        <circle cx="24" cy="40" r="4" /><circle cx="44" cy="40" r="4" />
      </g>,
      vip: <g {...stroke}>
        <path d="M14 22 L22 36 L32 18 L42 36 L50 22 L46 46 L18 46 Z" />
        <circle cx="32" cy="14" r="2" {...fill} />
      </g>,
      cosmetics: <g {...stroke}>
        <circle cx="32" cy="32" r="14" />
        <path d="M32 18 L32 46 M18 32 L46 32 M22 22 L42 42 M42 22 L22 42" />
      </g>,
      currency: <g {...stroke}>
        <circle cx="24" cy="28" r="10" />
        <circle cx="38" cy="36" r="10" />
        <path d="M22 25 L26 25 M22 28 L26 28 M22 31 L26 31" strokeWidth="1.2" />
      </g>,
      slots: <g {...stroke}>
        <rect x="16" y="16" width="32" height="32" rx="2" />
        <path d="M22 26 L42 26 M22 32 L42 32 M22 38 L34 38" />
      </g>,
    };
    return (
      <svg viewBox="0 0 64 64" style={s} aria-hidden="true">
        {paths[cat] || paths.kits}
      </svg>
    );
  }

  Object.assign(window, { useShop, useLang, furyFmt: fmt, furyTone: toneGrad, FuryGlyph: CategoryGlyph });
})();
