// Screens 7 (Theme Board) + 8 (Item Detail sheet) + 9 (Shopping List / Tracking)

// ── Item catalogue (shared across themes for demo) ──
const CATALOG = [
  // Decor
  { id: 'shell-confetti',  em: '🐚', name: 'Seashell confetti',    desc: 'Biodegradable pastels',       price: 12, cat: 'Decor',   src: 'Etsy',   qtyHint: '×2 packs' },
  { id: 'pearl-garland',   em: '🪩', name: 'Pearl strand garland', desc: '12 ft, matte finish',          price: 18, cat: 'Decor',   src: 'Shein',  qtyHint: '×3' },
  { id: 'rattan-tray',     em: '🏖️', name: 'Rattan serving tray',  desc: 'Round, medium',                price: 28, cat: 'Decor',   src: 'Etsy',   qtyHint: '×2' },
  { id: 'taper-candles',   em: '🕯️', name: 'Taper candle set',     desc: 'Cream + navy, 12pk',           price: 22, cat: 'Decor',   src: 'Temu',   qtyHint: '×1' },
  { id: 'navy-ribbon',     em: '🎀', name: 'Navy ribbon spool',    desc: 'Silk, 50 yards',               price: 14, cat: 'Decor',   src: 'Amazon', qtyHint: '×1' },
  { id: 'palm-placemats',  em: '🌿', name: 'Palm leaf placemats',  desc: 'Set of 8',                      price: 16, cat: 'Decor',   src: 'Amazon', qtyHint: '×1 set' },

  // Outfits
  { id: 'bride-sash',      em: '👰', name: 'Bride-to-be sash',     desc: 'Pearl trim, satin',            price: 10, cat: 'Outfits', src: 'Shein',  qtyHint: '×1' },
  { id: 'bm-sashes',       em: '💐', name: 'Bridesmaid sashes',    desc: 'Pack of 6, ivory',             price: 24, cat: 'Outfits', src: 'Shein',  qtyHint: '×1 pk' },
  { id: 'pearl-hairpins',  em: '💍', name: 'Pearl hair pins',      desc: 'Set of 12',                    price: 18, cat: 'Outfits', src: 'Etsy',   qtyHint: '×1' },
  { id: 'statement-earrings', em: '💎', name: 'Statement earrings', desc: 'Drop pearls',                 price: 22, cat: 'Outfits', src: 'Amazon', qtyHint: '×1' },

  // Drinkware
  { id: 'acrylic-flutes',  em: '🥂', name: 'Acrylic flutes ×8',    desc: 'Navy rim, giftable',           price: 32, cat: 'Drinks',  src: 'Amazon', qtyHint: '×1 set' },
  { id: 'gold-straws',     em: '✨', name: 'Gold metallic straws',  desc: '50pk, reusable',               price: 12, cat: 'Drinks',  src: 'Temu',   qtyHint: '×1' },
  { id: 'monogram-cups',   em: '🥤', name: 'Monogrammed cups',     desc: 'Set of 8, personalised',       price: 28, cat: 'Drinks',  src: 'Etsy',   qtyHint: '×1' },

  // Props & Photo
  { id: 'polaroid',        em: '📸', name: 'Polaroid camera',      desc: 'Instant, 10 film pack',        price: 68, cat: 'Props',   src: 'Amazon', qtyHint: '×1' },
  { id: 'neon-bride',      em: '💡', name: '"Bride" neon sign',    desc: 'USB-powered, 16"',             price: 34, cat: 'Props',   src: 'Etsy',   qtyHint: '×1' },
  { id: 'balloon-arch',    em: '🎈', name: 'Balloon arch kit',     desc: 'Cream + coral, 100pc',         price: 26, cat: 'Props',   src: 'Temu',   qtyHint: '×1 kit' },

  // Favors
  { id: 'spf-minis',       em: '🧴', name: 'SPF minis ×8',         desc: 'Reef-safe, branded labels',    price: 32, cat: 'Favors',  src: 'Amazon', qtyHint: '×1 set' },
  { id: 'hangover-kit',    em: '💊', name: 'Custom hangover kit',  desc: 'Gauze bag + essentials',       price: 42, cat: 'Favors',  src: 'Etsy',   qtyHint: '×8' },
];

const CATEGORIES = ['Decor', 'Outfits', 'Drinks', 'Props', 'Favors'];
const RETAILERS  = ['Shein', 'Amazon', 'Etsy', 'Temu'];

const VIBE_DESCRIPTIONS = {
  coastal:   'Navy and white everything, pearls, champagne, rattan.',
  disco:     'Glitter, metallics, mirror balls — all the sparkle.',
  nashville: 'Rhinestones, fringe, boots, honky-tonk neon.',
  tropical:  'Rattan, gold, frangipani — breezy and sun-drenched.',
  ski:       'Fur, fire, mulled wine, cosy alpine luxe.',
  vegas:     'Neon, feathers, late-nights, high-voltage glam.',
  garden:    'Roses, linen, Pimms, English afternoon charm.',
  parisian:  'Cream, ribbon, Sancerre, Left Bank elegance.',
  custom:    'Your custom theme — built from your brief.',
};

// Shared tile renderer used for both Popular and AI grids.
// `isAi` adds a subtle ✨ badge to distinguish AI-generated suggestions.
function renderTile(it, cart, addToCart, onOpenItem, v, user, isAi) {
  const inCart = !!(cart && cart[it.id]);
  const qty = (cart && cart[it.id]) || 0;
  return (
    <div key={it.id} style={{
      background: '#fff', border: `1px solid ${TBL.line}`, borderRadius: 12, padding: 0,
      overflow: 'hidden', position: 'relative', display: 'flex', flexDirection: 'column',
    }}>
      <button onClick={() => onOpenItem(it)} style={{
        background: v.grad, border: 'none', padding: 0, aspectRatio: '1',
        cursor: 'pointer', display: 'flex', alignItems: 'stretch', justifyContent: 'stretch',
        fontSize: 32, position: 'relative', width: '100%', overflow: 'hidden',
      }}>
        <div style={{ position: 'absolute', top: 6, left: 6, zIndex: 2 }}><RetailerBadge name={it.src}/></div>
        {isAi && (
          <div title="AI suggestion" style={{
            position: 'absolute', bottom: 6, left: 6, zIndex: 2,
            background: 'rgba(122,78,142,0.85)', color: TBL.cream,
            padding: '2px 6px', borderRadius: 4,
            fontFamily: MONO, fontSize: 8, letterSpacing: 0.8, fontWeight: 500,
          }}>✨ AI</div>
        )}
        <ProductImage src={it.image} alt={it.name} emoji={it.em} gradient={v.grad} fontSize={32}/>
      </button>
      <button onClick={(e) => { e.stopPropagation(); addToCart(it.id); }} aria-label="Add to list" style={{
        position: 'absolute', top: 6, right: 6, zIndex: 2,
        width: 24, height: 24, borderRadius: 999,
        background: inCart ? TBL.jam : 'rgba(255,255,255,0.92)',
        color: inCart ? TBL.cream : TBL.ink,
        border: 'none', cursor: 'pointer',
        fontSize: inCart ? 11 : 15, fontWeight: inCart ? 600 : 300, lineHeight: 1,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        boxShadow: '0 2px 6px rgba(0,0,0,0.15)',
      }}>{inCart ? `×${qty}` : '+'}</button>
      <button onClick={() => onOpenItem(it)} style={{
        background: 'none', border: 'none', padding: 8, textAlign: 'left', cursor: 'pointer', width: '100%',
      }}>
        <div style={{ fontFamily: SERIF, fontSize: 13, fontStyle: 'italic', color: TBL.ink, lineHeight: 1.1, marginBottom: 4, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{it.name}</div>
        <div style={{ fontSize: 9, color: TBL.mute, marginBottom: 6, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{it.desc}</div>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <span style={{ fontFamily: SERIF, fontSize: 14, color: TBL.ink }}>{formatPrice(it.price, user && user.region, it.priceCurrency)}</span>
          <span style={{ fontFamily: MONO, fontSize: 9, color: TBL.jam }}>{it.qtyHint}</span>
        </div>
      </button>
    </div>
  );
}

function ThemeBoard({ vibe, user, dates, cart, setCart, saved, setSaved, onOpenItem, onCart, items: itemsProp, generatingMore, onGenerateMore, onClearAi }) {
  const [catTab, setCatTab] = React.useState('All');
  const [srcFilter, setSrcFilter] = React.useState(null);

  const v = vibe || { key: 'coastal', n: 'Coastal Pool Party', em: '🐚', grad: THEME_GRADIENTS.coastal, palette: ['#2d5d8a','#fbeee0','#e8d4c5','#f3b94a'] };
  const isSaved = !!(saved && saved[v.key]);
  const toggleSaved = () => setSaved && setSaved({ ...(saved || {}), [v.key]: !isSaved });

  // Use AI-generated items for this theme when present, otherwise fall back to the static CATALOG
  const allItems = (itemsProp && itemsProp.length > 0) ? itemsProp : CATALOG;

  // Filter items
  let items = allItems;
  if (catTab !== 'All') items = items.filter(i => i.cat === catTab);
  if (srcFilter)       items = items.filter(i => i.src === srcFilter);

  // Split into Popular (curated) and AI suggestions
  const popular = items.filter(i => i.origin !== 'ai');
  const aiItems = items.filter(i => i.origin === 'ai');
  const hasPopular = popular.length > 0;
  const hasAi = aiItems.length > 0;

  // Cart math — each item may have been priced in a different currency
  // (a curated item stored in GBP, an AI item generated for a USA user in USD).
  // Convert to the viewer's region currency before summing so totals are coherent.
  const cartItems = Object.keys(cart || {}).filter(k => cart[k] > 0);
  const cartCount = cartItems.reduce((s, k) => s + (cart[k] || 0), 0);
  const viewerRegion = user && user.region;
  const cartTotal = cartItems.reduce((s, k) => {
    const item = allItems.find(x => x.id === k);
    if (!item) return s;
    const converted = convertAmount(item.price, viewerRegion, item.priceCurrency);
    return s + converted * (cart[k] || 0);
  }, 0);

  const addToCart = (id) => {
    setCart({ ...(cart || {}), [id]: (cart[id] || 0) + 1 });
  };

  const tabs = [{ k: 'All', n: 'All' }].concat(CATEGORIES.map(c => {
    const total = CATALOG.filter(i => i.cat === c).length;
    return { k: c, n: c, total };
  }));

  return (
    <div style={{ background: TBL.cream, height: '100%', display: 'flex', flexDirection: 'column', position: 'relative' }}>
      {/* Hero */}
      <div style={{ background: v.grad, padding: '28px 22px 22px', position: 'relative' }}>
        <div style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', marginBottom: 12 }}>
          <button onClick={toggleSaved} aria-label={isSaved ? 'Saved' : 'Save theme'} style={{
            background: isSaved ? TBL.jam : 'rgba(255,255,255,0.55)', border: 'none',
            width: 34, height: 34, borderRadius: 999, cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            color: isSaved ? TBL.cream : TBL.ink, fontSize: 15, transition: 'background 0.15s',
          }}>{isSaved ? '♥' : '♡'}</button>
        </div>
        <Eyebrow color={TBL.ink} style={{ marginBottom: 6 }}>Your theme</Eyebrow>
        <div style={{ fontFamily: SERIF, fontSize: 38, fontStyle: 'italic', color: TBL.ink, letterSpacing: -1.1, lineHeight: 1, marginBottom: 10 }}>
          {v.n || v.name || 'Your theme'}
        </div>
        <div style={{ fontSize: 13, color: TBL.subtle, marginBottom: 14 }}>
          {VIBE_DESCRIPTIONS[v.key] || 'Your custom theme.'}
        </div>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 14 }}>
          {dates && dates.guests ? <Chip size="sm" active color={TBL.ink}>{dates.guests} guests</Chip> : null}
          {user && user.region ? <Chip size="sm">{REGIONS[user.region].flag} {user.region}</Chip> : null}
          {user && user.brideName ? <Chip size="sm">For {user.brideName}</Chip> : null}
        </div>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
          <div>
            <Eyebrow color={TBL.ink} style={{ marginBottom: 2, opacity: 0.7, whiteSpace: 'nowrap' }}>List total</Eyebrow>
            <div style={{ fontFamily: SERIF, fontSize: 40, fontStyle: 'italic', color: TBL.ink, letterSpacing: -1, lineHeight: 1 }}>
              {/* cartTotal is already in viewerRegion currency from convertAmount above */}
              {formatPrice(cartTotal, viewerRegion)}
            </div>
            {dates && dates.guests > 0 && cartTotal > 0 ? (
              <div style={{ fontSize: 11, color: TBL.subtle, marginTop: 4 }}>
                {formatPrice(cartTotal / dates.guests, viewerRegion)} per guest · {cartCount} item{cartCount === 1 ? '' : 's'}
              </div>
            ) : (
              <div style={{ fontSize: 11, color: TBL.subtle, marginTop: 4 }}>
                {cartCount === 0 ? 'Add items to start your list' : `${cartCount} item${cartCount === 1 ? '' : 's'} in your list`}
              </div>
            )}
            {cartTotal > 0 && (
              <div style={{ fontSize: 10, color: TBL.mute, marginTop: 6, fontStyle: 'italic', lineHeight: 1.3 }}>
                ✨ Prices are estimates — retailers run discounts all the time, you may pay less at checkout
              </div>
            )}
          </div>
          <PaletteDots colors={v.palette || ['#2d5d8a','#fbeee0','#e8d4c5','#f3b94a']} size={14}/>
        </div>
      </div>

      {/* Category filter */}
      <div style={{ background: TBL.cream, borderBottom: `1px solid ${TBL.line}`, padding: '10px 0 10px', display: 'flex', gap: 6, overflowX: 'auto', paddingLeft: 20, paddingRight: 20, flexShrink: 0 }}>
        {tabs.map(t => (
          <button key={t.k} onClick={() => setCatTab(t.k)} style={{
            background: catTab === t.k ? TBL.ink : 'transparent', color: catTab === t.k ? TBL.cream : TBL.ink,
            border: 'none', padding: '8px 14px', borderRadius: 999, cursor: 'pointer',
            fontFamily: SANS, fontSize: 12, fontWeight: 500, whiteSpace: 'nowrap',
          }}>{t.n}</button>
        ))}
      </div>

      {/* Retailer filter */}
      <div style={{ background: TBL.cream, borderBottom: `1px solid ${TBL.line}`, padding: '8px 20px', display: 'flex', gap: 6, flexShrink: 0, alignItems: 'center' }}>
        <span style={{ fontFamily: MONO, fontSize: 9, color: TBL.mute, letterSpacing: 1.5, marginRight: 4 }}>RETAILER</span>
        <button onClick={() => setSrcFilter(null)} style={{
          background: srcFilter === null ? TBL.ink : 'transparent', color: srcFilter === null ? TBL.cream : TBL.ink,
          border: `1px solid ${srcFilter === null ? TBL.ink : TBL.line}`, padding: '5px 11px', borderRadius: 999,
          cursor: 'pointer', fontFamily: SANS, fontSize: 11, fontWeight: 500,
        }}>All</button>
        {RETAILERS.map(r => (
          <button key={r} onClick={() => setSrcFilter(srcFilter === r ? null : r)} style={{
            background: srcFilter === r ? TBL.ink : 'transparent', color: srcFilter === r ? TBL.cream : TBL.ink,
            border: `1px solid ${srcFilter === r ? TBL.ink : TBL.line}`, padding: '5px 11px', borderRadius: 999,
            cursor: 'pointer', fontFamily: SANS, fontSize: 11, fontWeight: 500,
          }}>{r}</button>
        ))}
      </div>

      {/* Grid — split into Popular (curated) + AI suggestions */}
      <div style={{ flex: 1, overflow: 'auto', padding: '14px 20px 100px' }}>
        {items.length === 0 ? (
          <div style={{ textAlign: 'center', padding: '40px 20px', color: TBL.mute, fontSize: 13 }}>
            No items in this filter.<br/>Try clearing the retailer or category filter.
          </div>
        ) : (
          <>
            {hasPopular && (
              <>
                <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 10 }}>
                  <div>
                    <Eyebrow>Popular picks</Eyebrow>
                    <div style={{ fontFamily: MONO, fontSize: 9, color: TBL.mute, letterSpacing: 1, marginTop: 2 }}>
                      {popular.length} handpicked for this theme
                    </div>
                  </div>
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8, marginBottom: hasAi ? 24 : 16 }}>
                  {popular.map(it => renderTile(it, cart, addToCart, onOpenItem, v, user))}
                </div>
              </>
            )}

            {hasAi && (
              <>
                <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 10, gap: 10 }}>
                  <div style={{ minWidth: 0 }}>
                    <Eyebrow color={TBL.sky}>AI suggestions</Eyebrow>
                    <div style={{ fontFamily: MONO, fontSize: 9, color: TBL.mute, letterSpacing: 1, marginTop: 2 }}>
                      {aiItems.length} fresh idea{aiItems.length === 1 ? '' : 's'} · verify on retailer
                    </div>
                  </div>
                  {onClearAi && (
                    <button onClick={onClearAi} title="Clears AI items but keeps anything you've added to your bach list" style={{
                      background: 'none', border: `1px solid ${TBL.line}`, borderRadius: 999,
                      padding: '6px 12px', fontFamily: SANS, fontSize: 11, fontWeight: 500,
                      color: TBL.subtle, cursor: 'pointer', flexShrink: 0,
                    }}>Clear suggestions</button>
                  )}
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8, marginBottom: 16 }}>
                  {aiItems.map(it => renderTile(it, cart, addToCart, onOpenItem, v, user, true))}
                </div>
              </>
            )}

            {/* Generate-more button — always at the very bottom so users only see it
                after scrolling through everything else */}
            {onGenerateMore && (
              <button
                onClick={onGenerateMore}
                disabled={generatingMore}
                style={{
                  width: '100%',
                  background: `linear-gradient(120deg, ${TBL.citrus}20 0%, ${TBL.jam}20 50%, ${TBL.sky}20 100%)`,
                  border: `1.5px dashed ${TBL.jam}`,
                  borderRadius: 14,
                  padding: '14px 18px',
                  fontFamily: SANS, fontSize: 13, fontWeight: 500,
                  color: TBL.ink, cursor: generatingMore ? 'default' : 'pointer',
                  marginTop: 8,
                  display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
                }}
              >
                <span style={{ fontSize: 16 }}>{generatingMore ? '⏳' : '✨'}</span>
                {generatingMore ? 'Asking the AI for more ideas…' : (hasAi || hasPopular ? 'Generate even more with AI' : 'Generate items with AI')}
              </button>
            )}
          </>
        )}
      </div>

      {/* Floating cart (only when items in cart) */}
      {cartCount > 0 && (
        <button onClick={onCart} style={{
          position: 'absolute', bottom: 20, left: 20, right: 20, zIndex: 40,
          background: TBL.ink, color: TBL.cream, border: 'none', borderRadius: 999,
          padding: '14px 20px', cursor: 'pointer', display: 'flex', justifyContent: 'space-between', alignItems: 'center',
          boxShadow: '0 10px 30px rgba(0,0,0,0.25)', fontFamily: SANS, fontSize: 14,
        }}>
          <span><b>{cartCount}</b> in list</span>
          <span style={{ opacity: 0.5 }}>|</span>
          <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}>View shopping list → <b style={{ fontFamily: SERIF, fontStyle: 'italic', fontSize: 18 }}>{formatPrice(cartTotal, viewerRegion)}</b></span>
        </button>
      )}

    </div>
  );
}

// Global actions sheet — shown from the top-bar burger on any screen
function ActionsSheet({ step, onClose, onBrowse, onHome, onBuildCustom, onRestart, onDelete, onShare, onShareBach, onSettings, onClear, themeName, hasActiveTheme, themeCount }) {
  const actions = [];
  if (step !== 'home' && onHome) {
    actions.push({ em: '🏠', label: 'All my themes', desc: 'Back to your bach overview', onClick: onHome });
  }
  if (onShareBach && (themeCount || 0) > 0) {
    actions.push({ em: '🥂', label: 'Share my whole bach', desc: 'One link with every theme you\'ve built', onClick: onShareBach });
  }
  if (hasActiveTheme && onShare && (step === 'theme' || step === 'cart')) {
    actions.push({ em: '🔗', label: 'Share this theme', desc: 'Just this theme, not the whole bach', onClick: onShare });
  }
  if (onBuildCustom) {
    actions.push({ em: '✨', label: 'Build another theme', desc: 'Describe your own from scratch', onClick: onBuildCustom });
  }
  if (onBrowse) {
    actions.push({ em: '📚', label: 'Browse library', desc: 'Pick a new vibe from our library', onClick: onBrowse });
  }
  if (onSettings) {
    actions.push({ em: '⚙️', label: 'Edit bach details', desc: 'Change names, dates, region, guests', onClick: onSettings });
  }
  if ((step === 'theme' || step === 'cart') && onRestart) {
    actions.push({ em: '🔄', label: 'Restart this theme', desc: 'Clear items and start over', onClick: onRestart });
  }
  if ((step === 'theme' || step === 'cart') && onDelete) {
    actions.push({ em: '🗑️', label: 'Delete this theme', desc: 'Remove it from your bach', onClick: onDelete, danger: true });
  }
  if (onClear) {
    actions.push({ em: '⚠️', label: 'Clear my bach', desc: 'Reset everything and start over', onClick: onClear, danger: true });
  }

  return (
    <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(42,26,31,0.5)', display: 'flex', alignItems: 'flex-end', zIndex: 200 }}>
      <div onClick={(e) => e.stopPropagation()} style={{ background: TBL.cream, width: '100%', borderRadius: '24px 24px 0 0', padding: 20, maxHeight: '80%', overflow: 'auto' }}>
        <div style={{ width: 40, height: 4, background: TBL.line, borderRadius: 999, margin: '0 auto 14px' }}/>
        <Eyebrow style={{ marginBottom: 6 }}>Menu</Eyebrow>
        {themeName && (
          <div style={{ fontFamily: SERIF, fontSize: 22, fontStyle: 'italic', color: TBL.ink, marginBottom: 16, letterSpacing: -0.5 }}>{themeName}</div>
        )}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
          {actions.map((a, i) => (
            <button key={i} onClick={a.onClick} style={{
              background: '#fff',
              border: `1px solid ${a.danger ? 'rgba(224,90,61,0.3)' : TBL.line}`,
              borderRadius: 14, padding: '14px 16px',
              display: 'flex', alignItems: 'center', gap: 14, cursor: 'pointer', textAlign: 'left', width: '100%',
            }}>
              <div style={{ fontSize: 22 }}>{a.em}</div>
              <div style={{ flex: 1 }}>
                <div style={{ fontFamily: SANS, fontSize: 14, color: a.danger ? TBL.jam : TBL.ink, fontWeight: 500, marginBottom: 2 }}>{a.label}</div>
                <div style={{ fontSize: 11, color: TBL.mute }}>{a.desc}</div>
              </div>
              <svg width="6" height="10" viewBox="0 0 7 12"><path d="M1 1 L6 6 L1 11" stroke={TBL.mute} strokeWidth="1.5" fill="none" strokeLinecap="round"/></svg>
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { ActionsSheet });

// ── Item detail sheet ──
function ItemDetail({ item, vibe, user, cart, setCart, onClose, onShop }) {
  const it = item || CATALOG[0];
  const v = vibe || { grad: THEME_GRADIENTS.coastal };
  const qty = (cart && cart[it.id]) || 0;
  const hasRealImage = !!it.image;
  const gradients = [v.grad, THEME_GRADIENTS.parisian, THEME_GRADIENTS.garden];
  const [imgIdx, setImgIdx] = React.useState(0);
  // When we have a real product image, show it as the single hero. Otherwise use the 3-gradient demo.
  const imageSlots = hasRealImage ? [it.image] : [null, null, null];

  const add = () => setCart({ ...(cart || {}), [it.id]: qty + 1 });
  const sub = () => {
    const next = Math.max(0, qty - 1);
    const c = { ...(cart || {}) };
    if (next === 0) delete c[it.id]; else c[it.id] = next;
    setCart(c);
  };

  return (
    <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(42,26,31,0.5)', display: 'flex', alignItems: 'flex-end', zIndex: 200 }}>
      <div onClick={(e) => e.stopPropagation()} style={{ background: TBL.cream, width: '100%', borderRadius: '24px 24px 0 0', padding: 20, maxHeight: '90%', overflow: 'auto' }}>
        <div style={{ width: 40, height: 4, background: TBL.line, borderRadius: 999, margin: '0 auto 16px' }}/>

        {/* Image carousel — real product image when available, gradient placeholder otherwise */}
        <div style={{ position: 'relative', marginBottom: 12 }}>
          <div style={{
            aspectRatio: '1.4', borderRadius: 16,
            position: 'relative', overflow: 'hidden',
          }}>
            <div style={{ position: 'absolute', top: 10, left: 10, zIndex: 2 }}><RetailerBadge name={it.src}/></div>
            <button onClick={onClose} aria-label="Close" style={{ position: 'absolute', top: 10, right: 10, zIndex: 2, width: 30, height: 30, borderRadius: 999, background: 'rgba(255,255,255,0.85)', border: 'none', cursor: 'pointer', fontSize: 16, color: TBL.ink }}>×</button>
            <ProductImage src={it.image} alt={it.name} emoji={it.em} gradient={gradients[imgIdx]} fontSize={82} fit="cover"/>
          </div>
          {/* Dots only shown for placeholder carousel */}
          {!hasRealImage && (
            <div style={{ display: 'flex', justifyContent: 'center', gap: 6, marginTop: 10 }}>
              {imageSlots.map((_, i) => (
                <button key={i} onClick={() => setImgIdx(i)} aria-label={`Image ${i+1}`} style={{
                  width: imgIdx === i ? 22 : 7, height: 7, borderRadius: 999,
                  background: imgIdx === i ? TBL.jam : TBL.line,
                  border: 'none', cursor: 'pointer', padding: 0, transition: 'all 0.15s',
                }}/>
              ))}
            </div>
          )}
          {it.shopName && (
            <div style={{ marginTop: 10, textAlign: 'center', fontFamily: MONO, fontSize: 10, letterSpacing: 1.2, color: TBL.mute }}>
              SHOP · {it.shopName.toUpperCase()}
            </div>
          )}
        </div>

        <div style={{ fontFamily: SERIF, fontSize: 26, fontStyle: 'italic', color: TBL.ink, letterSpacing: -0.6, marginBottom: 6 }}>{it.name}</div>
        <div style={{ fontSize: 13, color: TBL.subtle, lineHeight: 1.5, marginBottom: 16 }}>{it.desc}</div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 14 }}>
          <Card pad={14}>
            <Eyebrow style={{ marginBottom: 4 }}>Price</Eyebrow>
            <div style={{ fontFamily: SERIF, fontStyle: 'italic', fontSize: 24, color: TBL.ink }}>{formatPrice(it.price, user && user.region, it.priceCurrency)}</div>
          </Card>
          <Card pad={14}>
            <Eyebrow style={{ marginBottom: 4 }}>Qty suggested</Eyebrow>
            <div style={{ fontFamily: SERIF, fontStyle: 'italic', fontSize: 24, color: TBL.ink }}>{it.qtyHint}</div>
          </Card>
        </div>

        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 18, padding: 12, background: '#fff', border: `1px solid ${TBL.line}`, borderRadius: 14 }}>
          <div>
            <Eyebrow>In your list</Eyebrow>
            <div style={{ fontFamily: SERIF, fontStyle: 'italic', fontSize: 22, color: TBL.jam }}>{formatPrice(it.price * qty, user && user.region, it.priceCurrency)}</div>
          </div>
          <div style={{ display: 'inline-flex', alignItems: 'center', background: '#fff', border: `1px solid ${TBL.line}`, borderRadius: 999, overflow: 'hidden' }}>
            <button onClick={sub} disabled={qty === 0} style={{ width: 40, height: 40, border: 'none', background: 'transparent', fontSize: 20, cursor: qty === 0 ? 'not-allowed' : 'pointer', color: qty === 0 ? TBL.line : TBL.ink }}>−</button>
            <div style={{ width: 36, textAlign: 'center', fontFamily: SERIF, fontStyle: 'italic', fontSize: 18, color: TBL.ink }}>{qty}</div>
            <button onClick={add} style={{ width: 40, height: 40, border: 'none', background: 'transparent', fontSize: 20, cursor: 'pointer', color: TBL.ink }}>+</button>
          </div>
        </div>

        <div style={{ display: 'flex', gap: 8, marginBottom: 10 }}>
          <PrimaryBtn full onClick={add}>
            {qty > 0 ? `Add another (${qty} in list)` : 'Add to Bach List'}
          </PrimaryBtn>
          <SecondaryBtn full onClick={() => onShop && onShop(it)}>Buy on {it.src} now</SecondaryBtn>
        </div>
        <div style={{ fontSize: 10, color: TBL.mute, marginBottom: 18, fontStyle: 'italic', textAlign: 'center', lineHeight: 1.3 }}>
          ✨ Price shown is our estimate — {it.src} may have an active discount at checkout
        </div>

        <Card pad={14} style={{ background: `${TBL.mint}18`, border: `1px solid ${TBL.mint}40` }}>
          <Eyebrow color={TBL.ink} style={{ marginBottom: 6 }}>Why this works</Eyebrow>
          <div style={{ fontSize: 12, color: TBL.subtle, lineHeight: 1.5 }}>Palette-matched to your theme and sized for your guest count. Pool-safe, gift-wrappable as a favor post-weekend.</div>
        </Card>
      </div>
    </div>
  );
}

// ── Shopping List ──
function ShoppingList({ cart, user, dates, onClose, onCheckout, onBack, onShare, items: itemsProp, onShopRetailer }) {
  const [tab, setTab] = React.useState('list');
  const allItems = (itemsProp && itemsProp.length > 0) ? itemsProp : CATALOG;
  const cartItems = Object.keys(cart || {}).filter(k => cart[k] > 0)
    .map(id => ({ ...(allItems.find(x => x.id === id) || { id, name: 'Item', price: 0, src: 'Amazon', cat: 'Decor', em: '🎀', qtyHint: '×1' }), qty: cart[id] }));

  if (cartItems.length === 0) {
    return (
      <div style={{ background: TBL.cream, height: '100%', display: 'flex', flexDirection: 'column' }}>
        <div style={{ padding: '24px 22px 14px' }}>
          <Eyebrow>Shopping list</Eyebrow>
        </div>
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: 30, textAlign: 'center' }}>
          <div style={{ fontSize: 54, marginBottom: 14 }}>🛒</div>
          <div style={{ fontFamily: SERIF, fontSize: 26, fontStyle: 'italic', color: TBL.ink, letterSpacing: -0.6, marginBottom: 10 }}>Your list is empty.</div>
          <div style={{ fontSize: 13, color: TBL.subtle, lineHeight: 1.5, marginBottom: 24, maxWidth: 320 }}>
            Head back to your theme board and tap the <b style={{ color: TBL.jam }}>+</b> on any item to start building.
          </div>
          <PrimaryBtn size="lg" onClick={onBack || onClose}>← Back to theme</PrimaryBtn>
        </div>
      </div>
    );
  }

  // Convert each line to the viewer's region currency before summing so totals
  // are coherent when items were priced in different currencies (curated UK items
  // next to AI items generated for a US user, for example).
  const viewerRegion = user && user.region;
  const total = cartItems.reduce((s, i) => s + convertAmount(i.price, viewerRegion, i.priceCurrency) * i.qty, 0);

  // Group by retailer
  const groups = RETAILERS.map(r => {
    const its = cartItems.filter(i => i.src === r);
    const sub = its.reduce((s, i) => s + convertAmount(i.price, viewerRegion, i.priceCurrency) * i.qty, 0);
    const color = r === 'Shein' ? TBL.shein : r === 'Amazon' ? TBL.amazon : r === 'Etsy' ? TBL.etsy : TBL.temu;
    return { src: r, items: its, sub, color };
  }).filter(g => g.items.length > 0);

  return (
    <div style={{ background: TBL.cream, height: '100%', display: 'flex', flexDirection: 'column' }}>
      <div style={{ padding: '24px 22px 14px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 14 }}>
          <div>
            <Eyebrow style={{ marginBottom: 4 }}>Shopping list</Eyebrow>
            <div style={{ fontFamily: SERIF, fontSize: 28, fontStyle: 'italic', color: TBL.ink, letterSpacing: -0.6, lineHeight: 1 }}>
              {/* total already in viewer currency */}
              {formatPrice(total, viewerRegion)}
            </div>
            {dates && dates.guests > 0 && (
              <div style={{ fontSize: 11, color: TBL.subtle, marginTop: 4 }}>
                {formatPrice(total / dates.guests, viewerRegion)} per guest · {cartItems.length} items
              </div>
            )}
            <div style={{ fontSize: 10, color: TBL.mute, marginTop: 6, fontStyle: 'italic', lineHeight: 1.3, maxWidth: 320 }}>
              ✨ These are estimates — each retailer shows its live price (and any discounts) at checkout
            </div>
          </div>
        </div>
        <div style={{ background: '#fff', border: `1px solid ${TBL.line}`, borderRadius: 999, padding: 3, display: 'flex' }}>
          {[['list','Shopping list'],['track','Order tracking']].map(([k,n]) => (
            <button key={k} onClick={() => setTab(k)} style={{
              flex: 1, background: tab === k ? TBL.ink : 'transparent', color: tab === k ? TBL.cream : TBL.ink,
              border: 'none', padding: '10px', borderRadius: 999, cursor: 'pointer', fontFamily: SANS, fontSize: 12, fontWeight: 500,
            }}>{n}</button>
          ))}
        </div>
      </div>
      <div style={{ flex: 1, overflow: 'auto', padding: '4px 20px 100px' }}>
        {tab === 'list' ? <ListTab groups={groups} user={user} onShopRetailer={onShopRetailer}/> : <TrackTab cartItems={cartItems} user={user}/>}
      </div>
      <div style={{ padding: '12px 20px 16px', background: TBL.cream, borderTop: `1px solid ${TBL.line}`, display: 'flex', gap: 8 }}>
        <SecondaryBtn full size="md" onClick={onShare}>🔗 Share with group</SecondaryBtn>
        <PrimaryBtn full size="md" onClick={onCheckout}>💌 Email me a copy</PrimaryBtn>
      </div>
    </div>
  );
}

function ListTab({ groups, user, onShopRetailer }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 12, paddingTop: 14 }}>
      {groups.map((g, i) => (
        <Card key={i} pad={0} style={{ overflow: 'hidden' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: 14, borderBottom: `1px solid ${TBL.line}` }}>
            <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
              <RetailerBadge name={g.src}/>
              {/* g.sub already in viewer currency */}
              <div style={{ fontSize: 13, color: TBL.ink }}>{g.items.length} items · <b>{formatPrice(g.sub, user && user.region)}</b></div>
            </div>
            <button
              onClick={() => onShopRetailer && onShopRetailer(g.src, g.items)}
              style={{ background: g.color, color: '#fff', border: 'none', padding: '7px 12px', borderRadius: 999, cursor: 'pointer', fontSize: 11, fontWeight: 500 }}
            >Buy on {g.src} →</button>
          </div>
          {g.items.map((it, j) => (
            <div key={j} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', borderBottom: j < g.items.length - 1 ? `1px solid ${TBL.line}` : 'none' }}>
              <div style={{ width: 36, height: 36, borderRadius: 8, background: THEME_GRADIENTS.coastal, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 18 }}>{it.em}</div>
              <div style={{ flex: 1 }}>
                <div style={{ fontFamily: SERIF, fontStyle: 'italic', fontSize: 14, color: TBL.ink, lineHeight: 1 }}>{it.name}</div>
                <div style={{ fontSize: 10, color: TBL.mute, marginTop: 3 }}>{it.cat} · {it.qtyHint}</div>
              </div>
              <div style={{ fontFamily: MONO, fontSize: 11, color: TBL.jam, minWidth: 24, textAlign: 'right' }}>×{it.qty}</div>
              <div style={{ fontFamily: SERIF, fontStyle: 'italic', fontSize: 15, color: TBL.ink, minWidth: 44, textAlign: 'right' }}>{formatPrice(it.price * it.qty, user && user.region, it.priceCurrency)}</div>
            </div>
          ))}
        </Card>
      ))}
    </div>
  );
}

function TrackTab({ cartItems, user }) {
  const viewerRegion = user && user.region;
  const done = Math.floor(cartItems.length * 0.4);
  const total = cartItems.length;
  // Convert each item to viewer currency before summing for coherent totals
  const cartTotal = cartItems.reduce((s, i) => s + convertAmount(i.price, viewerRegion, i.priceCurrency) * i.qty, 0);
  const doneTotal = Math.round(cartTotal * 0.4);
  const pct = total > 0 ? Math.round((done / total) * 100) : 0;

  return (
    <div style={{ paddingTop: 14 }}>
      <Card style={{ marginBottom: 16 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 8 }}>
          <div style={{ fontFamily: SERIF, fontSize: 24, fontStyle: 'italic', color: TBL.ink }}>You're {pct}% there</div>
          <div style={{ fontFamily: MONO, fontSize: 11, color: TBL.jam }}>{done}/{total}</div>
        </div>
        <div style={{ fontSize: 12, color: TBL.subtle, marginBottom: 12 }}>
          {/* both totals already in viewer currency */}
          {formatPrice(doneTotal, viewerRegion)} ordered of {formatPrice(cartTotal, viewerRegion)}
        </div>
        <GradientProgress pct={pct}/>
      </Card>
      <Card pad={0} style={{ overflow: 'hidden', marginBottom: 14 }}>
        {cartItems.map((it, i) => {
          const isDone = i < done;
          return (
            <div key={i} style={{ borderBottom: i < cartItems.length - 1 ? `1px solid ${TBL.line}` : 'none' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: 14 }}>
                <div style={{ width: 22, height: 22, borderRadius: 999, border: `1.5px solid ${isDone ? TBL.sage : TBL.line}`, background: isDone ? TBL.sage : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  {isDone && <svg width="12" height="12" viewBox="0 0 12 12"><path d="M2 6 L5 9 L10 3" stroke="#fff" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>}
                </div>
                <div style={{ flex: 1, fontSize: 14, color: TBL.ink, textDecoration: isDone ? 'line-through' : 'none', opacity: isDone ? 0.55 : 1 }}>{it.name}</div>
                <div style={{ fontFamily: SERIF, fontStyle: 'italic', fontSize: 15, color: TBL.ink, opacity: isDone ? 0.55 : 1 }}>{formatPrice(it.price * it.qty, viewerRegion, it.priceCurrency)}</div>
              </div>
            </div>
          );
        })}
      </Card>
      <Card style={{ background: `${TBL.citrus}20`, border: `1px solid ${TBL.citrus}60` }}>
        <Eyebrow color={TBL.ink} style={{ marginBottom: 6 }}>Pro-tip · soon</Eyebrow>
        <div style={{ fontSize: 12, color: TBL.subtle, lineHeight: 1.5 }}>
          Forward order confirmations to <b style={{ color: TBL.ink }}>track@thebachlists.com</b> — we'll auto-match items and update tracking.
        </div>
      </Card>
    </div>
  );
}

Object.assign(window, { ThemeBoard, ItemDetail, ShoppingList, CATALOG, CATEGORIES, RETAILERS, VIBE_DESCRIPTIONS });
