// app.jsx — Root app: navigation, cart state, dispense simulation, tweaks

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "brand": "elektrobee",
  "loggedIn": true,
  "accent": "var(--eb-amber)",
  "navy": "var(--eb-navy)",
  "startScreen": "home",
  "showWallMap": true,
  "locationOn": true,
  "productImageSlots": false
}/*EDITMODE-END*/;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // Brand swap — call applyBrand once on mount + whenever brand tweak changes.
  // We also bump a "brandSeq" counter to force descendants to re-evaluate.
  const [brandSeq, setBrandSeq] = React.useState(0);
  React.useEffect(() => {
    window.applyBrand(t.brand || 'elektrobee');
    setBrandSeq(s => s + 1);
  }, [t.brand]);

  // Navigation state
  const [stack, setStack] = React.useState([t.startScreen || 'home']);
  const cur = stack[stack.length - 1];
  const go = (screen) => setStack(s => [...s, screen]);
  const back = () => setStack(s => {
    if (s.length > 1) return s.slice(0, -1);
    // Safety fallback — if user landed deep via debug/tweak nav with no history,
    // back goes to home rather than no-op'ing.
    if (s[0] !== 'home') return ['home'];
    return s;
  });
  const reset = (screen = 'home') => setStack([screen]);

  // User state — controlled by tweak
  const [loggedIn, setLoggedIn] = React.useState(t.loggedIn);
  React.useEffect(() => { setLoggedIn(t.loggedIn); }, [t.loggedIn]);
  // Demo flag — overrides verifiedAge on the mock user so the KTP flow has a
  // reachable "not verified" state without a separate fake user.
  const [verifiedAgeOverride, setVerifiedAgeOverride] = React.useState(null);
  const user = loggedIn
    ? { ...MOCK_USER.loggedIn,
        verifiedAge: verifiedAgeOverride == null ? MOCK_USER.loggedIn.verifiedAge : verifiedAgeOverride }
    : null;

  // Cart: { productId: qty }
  const [cart, setCart] = React.useState({});
  const cartCount = Object.values(cart).reduce((s, v) => s + v, 0);

  // Reservation timer (counts down while items in cart)
  const [reservation, setReservation] = React.useState(180);
  React.useEffect(() => {
    if (cartCount === 0) { setReservation(180); return; }
    const t = setInterval(() => setReservation(r => Math.max(0, r - 1)), 1000);
    return () => clearInterval(t);
  }, [cartCount]);

  // Current scanned machine (single machine after scan)
  const [machine, setMachine] = React.useState(MOCK_MACHINES[0]);

  // Selected product (for product sheet — used in Cluster context)
  const [selectedProduct, setSelectedProduct] = React.useState(null);
  // Product for full-screen detail (from Cari)
  const [detailProduct, setDetailProduct] = React.useState(null);
  // Machine for full-screen detail (from map / from product detail)
  const [detailMachine, setDetailMachine] = React.useState(null);
  // Optional: which machine to focus on when opening the map
  const [focusMachineId, setFocusMachineId] = React.useState(null);

  // Age gate
  const [ageGateProduct, setAgeGateProduct] = React.useState(null);

  // Voucher picker
  const [voucherPickerOpen, setVoucherPickerOpen] = React.useState(false);
  const [useVoucher, setUseVoucher] = React.useState(null);

  // Dispense state
  const [pendingTotal, setPendingTotal] = React.useState(0);
  const [dispenseResults, setDispenseResults] = React.useState({});

  // Cart actions
  const addToCart = (product) => {
    setCart(c => ({ ...c, [product.id]: Math.min((c[product.id] || 0) + 1, product.stock) }));
    setReservation(180); // refresh timer on activity
  };
  const removeFromCart = (product) => {
    setCart(c => {
      const cur = c[product.id] || 0;
      if (cur <= 1) {
        const { [product.id]: _, ...rest } = c;
        return rest;
      }
      return { ...c, [product.id]: cur - 1 };
    });
  };
  const clearCart = () => { setCart({}); setUseVoucher(null); };

  // Flow handlers
  const handleScan = () => go('scan');
  const handleDetected = (m) => { setMachine(m); clearCart(); reset('machine'); };
  const handleOpenMachine = (m) => { setMachine(m); go('machine'); };
  const handleSwitchMachine = () => {};
  const handleOpenProduct = (p) => setSelectedProduct(p);
  const handleCloseProduct = () => setSelectedProduct(null);
  // From Cari → full screen detail (no buy buttons; wayfinder)
  const handleOpenFromCari = (p) => { setDetailProduct(p); go('product-detail'); };
  const handleBuyNow = (p) => {
    addToCart(p);
    setSelectedProduct(null);
    setTimeout(() => go('cart'), 60);
  };
  const handleOpenCart = () => go('cart');
  const handleCheckout = (total) => { setPendingTotal(total); go('qris'); };
  const handlePaid = () => go('dispense');
  const handleDispenseFinish = (results) => {
    setDispenseResults(results);
    go('result');
  };
  const handleDone = () => { clearCart(); reset('home'); };
  const handleScanAgain = () => { clearCart(); reset('scan'); };
  const handleAgeGate = (p) => { setSelectedProduct(null); setAgeGateProduct(p); };
  const handleAgeGateRegister = () => { setAgeGateProduct(null); if (loggedIn) { go('ktp'); } else { go('login'); } };
  const handleLogin = () => go('login');
  const handleLoggedIn = () => {
    setTweak('loggedIn', true);
    setLoggedIn(true);
    back();
  };
  const handleLogout = () => {
    setTweak('loggedIn', false);
    setLoggedIn(false);
    back();
  };
  const handleReorder = (p) => {
    addToCart(p);
    handleOpenMachine(MOCK_MACHINES[0]);
  };

  // Expose the productImageSlots tweak globally so ProductThumb can read it
  // without prop-drilling through every screen.
  React.useEffect(() => {
    window.__EB_ALLOW_PRODUCT_DROP = !!t.productImageSlots;
  }, [t.productImageSlots]);

  // Render current screen
  React.useEffect(() => {
    window.__nav = (s) => { setSelectedProduct(null); setAgeGateProduct(null); setVoucherPickerOpen(false); if (s === 'machine-detail' && !detailMachine) setDetailMachine(MOCK_MACHINES[0]); reset(s); };
    window.__fillCart = () => { setCart({'C1-0': 2, 'C3-1': 1, 'C4-0': 1, 'C2-0': 1}); setReservation(180); setPendingTotal(27500); };
    window.__setLoggedIn = (v) => { setTweak('loggedIn', v); setLoggedIn(v); };
    window.__openProduct = (id = 'C1-0') => {
      const p = MOCK_PRODUCTS.find(x => x.id === id);
      reset('machine');
      setTimeout(() => setSelectedProduct(p), 100);
    };
    window.__showResult = () => {
      setCart({'C1-0': 2, 'C3-1': 1, 'C4-0': 1, 'C2-0': 1});
      setPendingTotal(27500);
      setDispenseResults({
        'C1-0': { success: 2, failed: 0, total: 2 },
        'C3-1': { success: 1, failed: 0, total: 1 },
        'C4-0': { success: 1, failed: 0, total: 1 },
        'C2-0': { success: 0, failed: 1, total: 1 },
      });
      reset('result');
    };
  });

  // Tab navbar routing
  const TAB_ROUTES = ['home', 'cari', 'vouchers', 'profile'];
  const ROUTE_TO_TAB = { home: 'home', cari: 'cari', vouchers: 'voucher', profile: 'akun' };
  const TAB_TO_ROUTE = { home: 'home', cari: 'cari', voucher: 'vouchers', akun: 'profile' };
  const showNavBar = TAB_ROUTES.includes(cur);
  const handleTab = (tabId) => {
    const route = TAB_TO_ROUTE[tabId];
    if (route === cur) return;
    if ((route === 'profile' || route === 'vouchers') && !user) {
      reset('login-prompt');
      return;
    }
    reset(route);
  };
  const navBarEl = showNavBar ? (
    <NavBar
      current={ROUTE_TO_TAB[cur]}
      voucherCount={user?.vouchers.length || 0}
      onTab={handleTab}
      onScan={() => { setSelectedProduct(null); reset('scan'); }}
    />
  ) : null;

  const renderScreen = () => {
    switch (cur) {
      case 'home':
        return <ScreenHome
          user={user}
          onScan={handleScan}
          onOpenProfile={() => go(loggedIn ? 'profile' : 'login-prompt')}
          onOpenVouchers={() => reset('vouchers')}
          onOpenRiwayat={() => go('riwayat')}
          onOpenProduct={handleOpenFromCari}
          onOpenCari={() => reset('cari')}
          onOpenMap={() => go('map-full')}
          navbar={navBarEl}
        />;
      case 'scan':
        return <ScreenScan onBack={back} onDetected={handleDetected} />;
      case 'machine':
        return <ScreenMachine
          machine={machine}
          cart={cart}
          onAddToCart={addToCart}
          onRemoveFromCart={removeFromCart}
          onBack={back}
          onOpenCart={handleOpenCart}
          onOpenProduct={handleOpenProduct}
          onSwitchMachine={handleSwitchMachine}
        />;
      case 'cart':
        return <ScreenCart
          cart={cart}
          machine={machine}
          user={user}
          useVoucher={useVoucher}
          setUseVoucher={setUseVoucher}
          reservationLeft={reservation}
          onBack={back}
          onAdd={addToCart}
          onRemove={removeFromCart}
          onClear={clearCart}
          onCheckout={handleCheckout}
          onVoucherPicker={() => user ? setVoucherPickerOpen(true) : go('login-prompt')}
        />;
      case 'qris':
        return <ScreenQris total={pendingTotal} onBack={back} onPaid={handlePaid} onCancel={back} />;
      case 'dispense':
        return <ScreenDispense cart={cart} machine={machine} onFinish={handleDispenseFinish} />;
      case 'result':
        return <ScreenResult
          cart={cart}
          results={dispenseResults}
          total={pendingTotal}
          user={user}
          onDone={handleDone}
          onScanAgain={handleScanAgain}
          onRegisterPrompt={() => go('login')}
        />;
      case 'riwayat':
        return <ScreenRiwayat
          user={user}
          onBack={back}
          onLogin={handleLogin}
        />;
      case 'cari':
        return <ScreenCari
          onBack={back}
          onOpenProduct={handleOpenFromCari}
          onOpenMap={() => go('map-full')}
          navbar={navBarEl}
        />;
      case 'map-full':
        return <ScreenMapFull
          onBack={back}
          locOn={t.locationOn}
          focusMachineId={focusMachineId}
          onOpenMachine={(m) => { setDetailMachine(m); go('machine-detail'); }}
        />;
      case 'machine-detail':
        return <ScreenMachineDetail
          machine={detailMachine}
          onBack={back}
          onScan={() => reset('scan')}
        />;
      case 'product-detail':
        return <ScreenProductDetail
          product={detailProduct}
          locOn={t.locationOn}
          onBack={back}
          onScan={() => reset('scan')}
          onOpenProduct={handleOpenFromCari}
          onOpenMap={() => {}}
        />;
      case 'profile':
        return <ScreenProfile
          user={user}
          onBack={back}
          onLogin={handleLogin}
          onLogout={handleLogout}
          onOpenVouchers={() => go('vouchers')}
          onOpenHistory={() => go('riwayat')}
          onOpenKtp={() => go('ktp')}
          navbar={navBarEl}
        />;
      case 'ktp':
        return <ScreenKtp
          user={user}
          onBack={back}
          onVerified={() => { setVerifiedAgeOverride(true); }}
        />;
      case 'login-prompt':
        return <ScreenLoginPrompt onBack={back} onLogin={handleLogin} />;
      case 'login':
        return <ScreenLogin onBack={back} onLoggedIn={handleLoggedIn} />;
      case 'vouchers':
        return user
          ? <ScreenVouchers user={user} onBack={back} navbar={navBarEl} />
          : <ScreenLoginPrompt onBack={back} onLogin={handleLogin} />;
      default:
        return <ScreenHome user={user} onScan={handleScan}
          onOpenProfile={() => go(loggedIn ? 'profile' : 'login-prompt')}
          onOpenVouchers={() => reset('vouchers')}
          onOpenRiwayat={() => go('riwayat')}
          onOpenProduct={handleOpenFromCari}
          onOpenCari={() => reset('cari')}
          onOpenMap={() => go('map-full')}
          navbar={navBarEl} />;
    }
  };

  // Determine status bar color
  const darkStatus = cur === 'scan' || cur === 'dispense';

  return (
    <div className="stage">
      <div className="stage-label">
        <span className="dot" />
        {(window.BRAND && window.BRAND.name) || 'Elektrobee'} Vending · {cur}
      </div>

      <PhoneScaler>
        <IOSDevice dark={darkStatus} width={402} height={874}>
          <div className="app">
            {renderScreen()}
            <ProductSheet
              product={selectedProduct}
              cart={cart}
              user={user}
              machine={machine}
              onAdd={addToCart}
              onRemove={removeFromCart}
              onClose={handleCloseProduct}
              onBuyNow={handleBuyNow}
              onAgeGate={handleAgeGate}
            />
            <AgeGateSheet
              open={!!ageGateProduct}
              product={ageGateProduct}
              isLoggedIn={loggedIn}
              onClose={() => setAgeGateProduct(null)}
              onRegister={handleAgeGateRegister}
            />
            <VoucherPickerSheet
              open={voucherPickerOpen}
              user={user}
              current={useVoucher}
              onPick={(id) => { setUseVoucher(id); setVoucherPickerOpen(false); }}
              onClose={() => setVoucherPickerOpen(false)}
            />
          </div>
        </IOSDevice>
      </PhoneScaler>

      {/* Tweaks panel */}
      <TweaksPanel title={`Tweaks · ${(window.BRAND && window.BRAND.name) || 'Elektrobee'}`}>
        <TweakSection label="Brand">
          <TweakSelect
            label="Brand"
            value={t.brand}
            options={[
              { value: 'elektrobee', label: 'Elektrobee' },
              { value: 'iqos',       label: 'IQOS' },
              { value: 'marlboro',   label: 'Marlboro' },
              { value: 'durex',      label: 'Durex' },
            ]}
            onChange={(v) => { setTweak('brand', v); }}
          />
        </TweakSection>

        <TweakSection label="State">
          <TweakToggle label="Logged in" value={loggedIn} onChange={(v) => setTweak('loggedIn', v)} />
          <TweakToggle label="Lokasi aktif" value={t.locationOn} onChange={(v) => setTweak('locationOn', v)} />
          <TweakToggle label="Foto produk (drag)" value={t.productImageSlots} onChange={(v) => setTweak('productImageSlots', v)} />
          <TweakToggle label="Akun 21+ terverifikasi"
            value={user ? user.verifiedAge : false}
            onChange={(v) => setVerifiedAgeOverride(v)} />
        </TweakSection>

        <TweakSection label="Jump to screen">
          <TweakSelect
            label="Layar"
            value={cur}
            options={[
              { value: 'home', label: 'Beranda' },
              { value: 'scan', label: 'Pindai QR' },
              { value: 'machine', label: 'Mesin (produk)' },
              { value: 'cari', label: 'Cari produk' },
              { value: 'map-full', label: 'Peta mesin' },
              { value: 'machine-detail', label: 'Detail mesin (browse)' },
              { value: 'product-detail', label: 'Detail produk (Cari)' },
              { value: 'cart', label: 'Keranjang' },
              { value: 'qris', label: 'Bayar QRIS' },
              { value: 'dispense', label: 'Sedang keluar' },
              { value: 'result', label: 'Hasil transaksi' },
              { value: 'riwayat', label: 'Riwayat' },
              { value: 'profile', label: 'Akun' },
              { value: 'vouchers', label: 'Voucher saya' },
              { value: 'login', label: 'OTP login' },
            ]}
            onChange={(v) => reset(v)}
          />
          <TweakButton label="Reset ke Beranda" onClick={() => { clearCart(); reset('home'); }} />
        </TweakSection>

        <TweakSection label="Demo data">
          <TweakButton label="Isi keranjang demo (5 item)" onClick={() => {
            setCart({
              'C1-0': 2,
              'C3-1': 1,
              'C4-0': 1,
              'C2-0': 1,
            });
            setReservation(180);
          }} secondary />
          <TweakButton label="Kosongkan keranjang" onClick={clearCart} secondary />
        </TweakSection>

        <TweakSection label="Tema warna">
          <TweakColor
            label="Aksen"
            value={t.accent}
            options={['var(--eb-amber)', '#F0793E', '#34D798', '#5B8DEF', '#9B5BEF']}
            onChange={(v) => setTweak('accent', v)}
          />
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

// Apply dynamic tweak colors via CSS vars (legacy — kept for accent picker if used)
function ColorBridge() {
  const [t] = useTweaks(TWEAK_DEFAULTS);
  React.useEffect(() => {
    // Skip when a brand controls the palette
    if (t.brand && t.brand !== 'elektrobee') return;
    document.documentElement.style.setProperty('--eb-amber', t.accent);
    document.documentElement.style.setProperty('--eb-amber-strong', shadeColor(t.accent, -18));
    document.documentElement.style.setProperty('--eb-amber-soft', tintColor(t.accent, 0.85));
  }, [t.accent, t.brand]);
  return null;
}

// Simple color utilities
function shadeColor(hex, percent) {
  const h = hex.replace('#', '');
  const num = parseInt(h, 16);
  let r = (num >> 16) + Math.round(2.55 * percent);
  let g = ((num >> 8) & 0xff) + Math.round(2.55 * percent);
  let b = (num & 0xff) + Math.round(2.55 * percent);
  r = Math.max(0, Math.min(255, r));
  g = Math.max(0, Math.min(255, g));
  b = Math.max(0, Math.min(255, b));
  return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
}
function tintColor(hex, amount) {
  const h = hex.replace('#', '');
  const num = parseInt(h, 16);
  const r = Math.round(((num >> 16) * (1 - amount)) + 255 * amount);
  const g = Math.round((((num >> 8) & 0xff) * (1 - amount)) + 255 * amount);
  const b = Math.round(((num & 0xff) * (1 - amount)) + 255 * amount);
  return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
}

function Root() {
  return (
    <>
      <ColorBridge />
      <App />
    </>
  );
}

// PhoneScaler — scales the iPhone frame to fit the viewport.
// Uses transform: scale() so taps and pointer events stay accurate.
function PhoneScaler({ children, w = 402, h = 874, margin = 56 }) {
  const wrapRef = React.useRef(null);
  const recompute = React.useCallback(() => {
    if (!wrapRef.current) return;
    const vw = window.innerWidth;
    const vh = window.innerHeight;
    const sx = (vw - margin) / w;
    const sy = (vh - margin) / h;
    const scale = Math.min(1, sx, sy);
    wrapRef.current.style.setProperty('--scale', scale);
  }, [w, h, margin]);
  React.useEffect(() => {
    recompute();
    window.addEventListener('resize', recompute);
    return () => window.removeEventListener('resize', recompute);
  }, [recompute]);
  return (
    <div ref={wrapRef} className="phone-scaler"
      style={{ '--phone-w': `${w}px`, '--phone-h': `${h}px` }}>
      {children}
    </div>
  );
}

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