const { useState: useStateA, useEffect: useEffectA, useMemo: useMemoA, useRef: useRefA } = React;

// ── Order polling ──────────────────────────────────────────────────────────
// Runs outside React so it survives SPA navigation within the same tab.
// Started when the user clicks Proceed to Checkout; resolved when ORDER_KV
// confirms the purchase via the /api/order-webhook Cloudflare Function.
let _orderPollTimer = null;
let _orderPollVisibilityHandler = null;

function startOrderPolling(getNavigate) {
  if (_orderPollTimer) return; // already polling
  const session = localStorage.getItem('pvl-checkout-session');
  if (!session) return;
  let count = 0;

  async function poll() {
    count++;
    if (count > 120) { stopOrderPolling(); window._clearConfirming?.(); return; }
    const s = localStorage.getItem('pvl-checkout-session');
    if (!s) { stopOrderPolling(); window._clearConfirming?.(); return; }
    try {
      const res = await fetch(`/api/order-status?session=${encodeURIComponent(s)}`);
      const data = await res.json();
      if (data.confirmed) {
        stopOrderPolling();
        localStorage.removeItem('pvl-checkout-session');
        getNavigate()?.({ name: 'order-complete', friendlyId: data.friendlyId, orderId: data.orderId, placedAt: data.placedAt || null }, '/merch/order-complete');
      }
    } catch (_) {}
  }

  poll(); // check immediately on start — no wait for first interval
  _orderPollTimer = setInterval(poll, 3000);

  // Browsers throttle setInterval in background tabs — poll immediately when
  // the user switches back so confirmation feels instant.
  _orderPollVisibilityHandler = () => { if (document.visibilityState === 'visible') poll(); };
  document.addEventListener('visibilitychange', _orderPollVisibilityHandler);
}

function stopOrderPolling() {
  clearInterval(_orderPollTimer);
  _orderPollTimer = null;
  if (_orderPollVisibilityHandler) {
    document.removeEventListener('visibilitychange', _orderPollVisibilityHandler);
    _orderPollVisibilityHandler = null;
  }
}

const TWEAK_DEFAULTS = {
  theme: 'cream',
  gridLayout: 'dense',
  showNowPlaying: false,
  showGrain: true,
  accent: '#7a4020',
};

const CURRENCY_SYMBOLS = { EUR: '€', USD: '$', GBP: '£', AUD: 'A$', CAD: 'C$' };
const SUPPORTED_CURRENCIES = ['EUR', 'USD', 'GBP', 'AUD', 'CAD'];

function parseRoute(path) {
  if (!path || path === '/') return { name: 'landing' };
  if (path === '/merch' || path === '/merch/') return { name: 'home' };
  if (path === '/merch/cart') return { name: 'cart' };
  if (path === '/merch/order-complete') return { name: 'order-complete' };
  if (path === '/merch/checkout-pending') return { name: 'checkout-pending' };
  if (path === '/merch/shipping')   return { name: 'info', id: 'shipping' };
  if (path === '/merch/faq')        return { name: 'info', id: 'faq' };
  if (path === '/merch/size-guide') return { name: 'info', id: 'size-guide' };
  if (path === '/merch/contact')    return { name: 'info', id: 'contact' };
  if (path === '/merch/privacy')    return { name: 'info', id: 'privacy' };
  if (path === '/merch/terms')      return { name: 'info', id: 'terms' };
  if (path === '/merch/about')      return { name: 'about' };
  const pdpMatch = path.match(/^\/merch\/product\/(.+)$/);
  const colMatch = path.match(/^\/merch\/collection\/(.+)$/);
  if (pdpMatch) return { name: 'pdp',        id: pdpMatch[1] };
  if (colMatch) return { name: 'collection', id: colMatch[1] };
  return { name: 'landing' };
}

function parsePatreonFragment() {
  const hash = window.location.hash.slice(1);
  if (!hash.startsWith('patreon=')) return null;
  const params = Object.fromEntries(new URLSearchParams(hash));
  return params.patreon ? params : null;
}

// Process fragment synchronously before first render so localStorage is
// populated before any component reads it (fixes popup timing on OAuth return)
(function() {
  const p = parsePatreonFragment();
  if (!p) return;
  if (p.patreon && p.patreon !== 'error') {
    localStorage.setItem('pvl-patreon-tier', p.patreon);
    if (p.code) localStorage.setItem('pvl-patreon-code', decodeURIComponent(p.code));
  }
  history.replaceState(null, '', window.location.pathname);
})();

function App() {
  const t = TWEAK_DEFAULTS;
  const [route,    setRoute]    = useStateA(() => parseRoute(window.location.pathname));
  const [patreonTier, setPatreonTier] = useStateA(() => localStorage.getItem('pvl-patreon-tier') || null);
  const [cart,     setCart]     = useStateA(() => { try { return JSON.parse(localStorage.getItem('pvl-cart') || '[]'); } catch { return []; } });
  const [wish,     setWish]     = useStateA(() => { try { return new Set(JSON.parse(localStorage.getItem('pvl-wish') || '[]')); } catch { return new Set(); } });
  const [recent,   setRecent]   = useStateA(() => { try { return JSON.parse(localStorage.getItem('pvl-recent') || '[]'); } catch { return []; } });
  const [drawer,   setDrawer]   = useStateA(null);
  const [products, setProducts] = useStateA([]);
  const [loading,  setLoading]  = useStateA(true);
  const [currency, setCurrency] = useStateA(() => {
    const cached = localStorage.getItem('pvl-currency');
    return (cached && SUPPORTED_CURRENCIES.includes(cached)) ? cached : 'USD';
  });

  // Prices come from Fourthwall already in the visitor's currency — just format.
  window.fmt = (price) => {
    if (price == null) return '';
    const symbol = CURRENCY_SYMBOLS[currency] || currency;
    return `${symbol}${price.toFixed(2)}`;
  };
  window.shopCurrency = currency;

  useCursor();

  // Handle Patreon OAuth callback — read tier from URL fragment
  useEffectA(() => {
    const p = parsePatreonFragment();
    if (!p) return;
    if (p.patreon && p.patreon !== 'error') {
      localStorage.setItem('pvl-patreon-tier', p.patreon);
      if (p.code) localStorage.setItem('pvl-patreon-code', decodeURIComponent(p.code));
      setPatreonTier(p.patreon);
    }
    // Clean the fragment from the URL without triggering a navigation
    history.replaceState(null, '', window.location.pathname);
  }, []);

  // Quick-add from product cards
  useEffectA(() => {
    const handler = (e) => {
      const { product, colorway, shirtColor, size, variantType } = e.detail;
      onAdd(product, colorway, shirtColor, size, variantType);
    };
    window.addEventListener('peripheral:quick-add', handler);
    return () => window.removeEventListener('peripheral:quick-add', handler);
  }, []);

  // Persist cart, wishlist and recent across page refreshes
  useEffectA(() => { localStorage.setItem('pvl-cart',   JSON.stringify(cart));           }, [cart]);
  useEffectA(() => { localStorage.setItem('pvl-wish',   JSON.stringify([...wish]));      }, [wish]);
  useEffectA(() => { localStorage.setItem('pvl-recent', JSON.stringify(recent));         }, [recent]);

  // Fetch products using cached currency immediately, then detect live currency
  // and re-fetch only if it differs — so a failed detection never drops to USD
  useEffectA(() => {
    const cached = localStorage.getItem('pvl-currency');
    const initial = (cached && SUPPORTED_CURRENCIES.includes(cached)) ? cached : null;

    const loadProducts = (code) =>
      fetchFourthwallProducts(code)
        .then(ps => { setProducts(ps); window.PRODUCTS = ps; })
        .catch(err => console.error('Failed to load products:', err));

    if (initial) {
      // Start product fetch immediately with cached currency
      loadProducts(initial).finally(() => setLoading(false));
      // Refresh detection in background; re-fetch if currency changed
      fetch('/api/currency')
        .then(r => r.text())
        .then(code => SUPPORTED_CURRENCIES.includes(code) ? code : initial)
        .catch(() => initial)
        .then(code => {
          localStorage.setItem('pvl-currency', code);
          if (code !== initial) { setCurrency(code); loadProducts(code); }
        });
    } else {
      // First ever visit — must detect before fetching
      fetch('/api/currency')
        .then(r => r.text())
        .then(code => SUPPORTED_CURRENCIES.includes(code) ? code : 'USD')
        .catch(() => 'USD')
        .then(code => {
          localStorage.setItem('pvl-currency', code);
          setCurrency(code);
          return loadProducts(code);
        })
        .finally(() => setLoading(false));
    }
  }, []);

  // Apply theme
  useEffectA(() => {
    document.documentElement.dataset.theme = t.theme;
    document.documentElement.dataset.grid  = t.gridLayout;
    document.documentElement.style.setProperty('--accent', t.accent);
  }, [t.theme, t.gridLayout, t.accent]);

  // Hide grain overlay
  useEffectA(() => {
    const g = document.querySelector('.grain');
    if (g) g.style.display = t.showGrain ? 'block' : 'none';
  }, [t.showGrain]);

  // Scroll to top on route change + update page title
  useEffectA(() => {
    window.scrollTo({ top: 0, behavior: 'instant' });
    document.title = route.name === 'landing' ? 'Peripheral' : 'Peripheral — Shop';
  }, [route]);

  // History: push URL on forward nav, listen for browser back/forward
  const navigate = (newRoute, url) => {
    history.pushState(newRoute, '', url);
    setRoute(newRoute);
  };

  useEffectA(() => {
    const route = parseRoute(window.location.pathname);
    history.replaceState(route, '', window.location.pathname);
    const onPop = (e) => setRoute(e.state || { name: 'landing' });
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, []);

  // Keep a ref to navigate so the polling closure always has the latest version
  const navigateRef = useRefA(null);
  navigateRef.current = navigate;

  useEffectA(() => {
    startOrderPolling(() => navigateRef.current);
    window._startOrderPolling = () => startOrderPolling(() => navigateRef.current);
    window._stopOrderPolling  = stopOrderPolling;
    return () => stopOrderPolling();
  }, []);

  const openProduct = (p, init) => {
    setRecent(prev => [p.id, ...prev.filter(id => id !== p.id)].slice(0, 8));
    const urls = new Set();
    ['printed','embroidered'].forEach(vt => {
      (p[vt]||[]).forEach(cw => {
        (cw.images||[]).forEach(u => urls.add(u));
        (cw.shirtColors||[]).forEach(sc => (sc.images||[]).forEach(u => urls.add(u)));
      });
    });
    urls.forEach(u => { const img = new Image(); img.crossOrigin = 'anonymous'; img.src = u; });
    navigate({ name: 'pdp', id: p.id, variantType: init?.variantType, cwIdx: init?.cwIdx, shirtColorIdx: init?.shirtColorIdx }, `/merch/product/${p.id}`);
  };
  const openCollection = (id) => navigate({ name: 'collection', id }, `/merch/collection/${id}`);

  const onWish = (id) => {
    setWish(prev => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });
  };

  const onAdd = (product, colorway, shirtColor, size, variantType, openCart = true) => {
    const key = `${product.id}:${colorway.name}:${shirtColor?.name || ''}:${size}`;
    setCart(prev => {
      const existing = prev.find(l => l.key === key);
      if (existing) return prev.map(l => l.key === key ? { ...l, qty: l.qty + 1 } : l);
      return [...prev, {
        key,
        id:          product.id,
        name:        product.name,
        type:        product.type,
        variantType: variantType || 'printed',
        price:       colorway.price,
        silhouette:  product.silhouette,
        colorway, shirtColor, size, qty: 1,
      }];
    });
    if (openCart) setDrawer('cart');
  };

  const product   = route.name === 'pdp' ? products.find(p => p.id === route.id) : null;
  const cartCount = cart.reduce((s, l) => s + l.qty, 0);

  return (
    <>
      {route.name !== 'landing' && (
        <Nav route={route} setRoute={setRoute} navigate={navigate}
             cartCount={cartCount}
             wishCount={wish.size}
             onOpenCart={() => setDrawer('cart')}
             onOpenSearch={() => setDrawer('search')}
             onOpenWish={() => setDrawer('wish')}
             openCollection={openCollection}
             transparent={route.name === 'home'}/>
      )}

      <div key={route.name === 'collection' ? 'collection' : (route.name + (route.id || ''))} className="page-fade">
        {route.name === 'landing' && (
          <LandingPage navigate={navigate}/>
        )}
        {route.name === 'home' && (
          <HomePage products={products} loading={loading}
                    openProduct={openProduct} wish={wish} onWish={onWish}
                    openCollection={openCollection}
                    onShop={() => openCollection('all')}/>
        )}
        {route.name === 'collection' && (
          <CollectionPage id={route.id} products={products}
                          openProduct={openProduct} wish={wish} onWish={onWish}
                          openCollection={openCollection}
                          onBack={() => history.back()}/>
        )}
        {route.name === 'cart' && (
          <CartPage cart={cart} setCart={setCart} navigate={navigate} openProduct={openProduct}/>
        )}
        {route.name === 'order-complete' && (
          <OrderCompletePage setCart={setCart} navigate={navigate} friendlyId={route.friendlyId} orderId={route.orderId} placedAt={route.placedAt}/>
        )}
        {route.name === 'checkout-pending' && (
          <CheckoutPendingPage navigate={navigate}/>
        )}
        {route.name === 'info' && (
          <InfoPage id={route.id} navigate={navigate}/>
        )}
        {route.name === 'about' && (
          <AboutComingSoon navigate={navigate}/>
        )}
        {route.name === 'pdp' && product && (
          <PDP product={product} products={products}
               onClose={() => history.back()}
               onAdd={onAdd} wish={wish} onWish={onWish}
               cart={cart} setCart={setCart}
               recentlyViewed={recent} openProduct={openProduct}
               navigate={navigate}
               initialVariantType={route.variantType}
               initialCwIdx={route.cwIdx}
               initialShirtColorIdx={route.shirtColorIdx}/>
        )}
        {route.name === 'pdp' && !product && (
          <main style={{ paddingTop:80, minHeight:'80vh', display:'flex', alignItems:'center', justifyContent:'center' }}>
            {loading ? (
              <div style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:20 }}>
                <div style={{ width:28, height:28, borderRadius:'50%', border:'1px solid var(--accent)', borderTopColor:'transparent', animation:'spin 0.9s linear infinite' }}/>
                <div style={{ fontFamily:'var(--mono)', fontSize:11, letterSpacing:'0.14em', textTransform:'uppercase', color:'var(--fg-mute)' }}>Loading</div>
              </div>
            ) : (
              <div style={{ textAlign:'center', display:'flex', flexDirection:'column', alignItems:'center', gap:20 }}>
                <div style={{ fontFamily:'var(--mono)', fontSize:11, letterSpacing:'0.14em', textTransform:'uppercase', color:'var(--fg-mute)' }}>Product not found</div>
                <button onClick={() => navigate({ name:'home' }, '/merch')}
                        style={{ fontFamily:'var(--mono)', fontSize:11, letterSpacing:'0.14em', textTransform:'uppercase', color:'var(--accent)', cursor:'none', textDecoration:'underline', textUnderlineOffset:4 }}
                        onMouseEnter={() => onCursor('hover')} onMouseLeave={() => onCursor('default')}>
                  Back to shop
                </button>
              </div>
            )}
          </main>
        )}
      </div>

      {route.name !== 'landing' && <Footer setRoute={setRoute} openCollection={openCollection} navigate={navigate}/>}

      {t.showNowPlaying && <NowPlaying/>}

      <Drawer mode={drawer} onClose={() => setDrawer(null)}
              cart={cart} setCart={setCart}
              wish={wish} onWish={onWish}
              openProduct={openProduct}
              navigate={navigate}/>

      {route.name !== 'landing' && <EmailPopupController/>}

    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
