// ShopPage.jsx — 香氛商品列表（/shop）
// D10（2026-09-30）：照定版雛形「Phïnn-Phang 商品頁雛形」v6 搬進來。
// 版面照 APFR（store.apfr.jp）量的規格：桌機一列 4 格、平板 3、手機 2；正方形圖；
// 圖下置中只放「品名 / 價格」。預購／售罄標在圖左上角，現貨不標。
// 初期不做分類（Rachel 定）；category 欄位先存，之後開分類不用補資料。
// 被 PP.FEATURES.shopEnabled 擋著：開關關著時 App.jsx 不會進到這一頁。
//
// 這支檔案也放列表頁與商品頁共用的小元件（ShopStatus / ShopPrice / ShopPending），
// 所以 index.html 要排在 ProductPage.jsx 前面載入。

const SHOP_CSS = `
  .shop-head { padding-block: var(--section-y) var(--sp-7); display: grid; gap: var(--sp-3); }
  .shop-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-7) var(--sp-5); padding-bottom: var(--section-y); }
  @media (max-width: 900px) { .shop-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-6) var(--sp-4); } }
  @media (max-width: 600px) { .shop-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-6) var(--sp-3); } }

  .shop-card { position: relative; display: grid; gap: var(--sp-2); align-content: start; justify-items: center; text-align: center; color: inherit; text-decoration: none; }
  .shop-card-img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; display: block; margin-bottom: var(--sp-2); border: 1px solid var(--line-gold); transition: border-color var(--dur-base) var(--ease); }
  .shop-card:hover .shop-card-img { border-color: var(--gold); }
  .shop-card.is-soldout .shop-card-img { opacity: 0.55; }
  .shop-card-badge { position: absolute; top: var(--sp-2); left: var(--sp-2); z-index: 1; }
  .shop-card-name { font-family: var(--font-zh); font-size: var(--fs-body); font-weight: var(--fw-regular); letter-spacing: var(--ls-label); line-height: var(--lh-tight); color: var(--text-main); }
  .shop-card .pp-price { font-size: var(--fs-body); }
  .shop-card:focus-visible { outline: 2px solid var(--btn-focus-ring); outline-offset: 3px; }

  @media (prefers-reduced-motion: reduce) { .shop-card-img { transition: none; } }
`;

// ── 共用小元件（商品頁也用）──────────────────────────────────────────────
function ShopPending({ children = '待定' }) {
  return <span className="pp-pending">{children}</span>;
}

function ShopStatus({ status, className = '' }) {
  const st = PP.SHOP_STATUS[status];
  if (!st) return null;
  return <span className={`pp-status pp-status--${status} ${className}`.trim()}>{st.label}</span>;
}

// price：數字或 null；from：true 時加「起」
function ShopPrice({ price, from, className = '' }) {
  if (price === null || price === undefined) return <ShopPending>價格待定</ShopPending>;
  return (
    <span className={`pp-price ${className}`.trim()}>
      NT$ {Number(price).toLocaleString('en-US')}{from ? ' 起' : ''}
    </span>
  );
}

// 進頁時向後端抓一次商品資料。回傳 'loading'（沒快取、還在抓）｜'ready'｜'error'（沒快取又抓失敗）。
// 有快取就先畫快取（ready），抓回來再重畫一次；抓失敗時保留快取畫面。
function useShopData() {
  const [state, setState] = React.useState(() => PP.hasShopCache() ? 'ready' : 'loading');
  const [, bump] = React.useState(0);
  React.useEffect(() => {
    let alive = true;
    PP.loadShopData().then(ok => {
      if (!alive) return;
      setState(ok || PP.hasShopCache() ? 'ready' : 'error');
      bump(n => n + 1);
    });
    return () => { alive = false; };
  }, []);
  return state;
}

// 載入中／讀不到時的一行字（列表頁與商品頁共用）
function ShopNotice({ state }) {
  return (
    <p className="pp-body" role="status">
      {state === 'error' ? '商品資料暫時讀不到，請稍後再試。' : '載入中…'}
    </p>
  );
}

function productPath(productId) { return '/product/' + encodeURIComponent(productId); }

// ── 列表頁 ────────────────────────────────────────────────────────────────
function ShopCard({ p, setPage }) {
  const summary = PP.shopPriceSummary(p.skus);
  const open = (e) => {
    // 保留 <a href>：按住 Cmd/Ctrl 或中鍵可以開新分頁；一般點擊走站內換頁
    if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) return;
    e.preventDefault();
    setPage('product', { productId: p.productId });
  };
  return (
    <a href={productPath(p.productId)} onClick={open}
      className={`shop-card${p.status === 'soldout' ? ' is-soldout' : ''}`}>
      {p.status !== 'instock' && <ShopStatus status={p.status} className="shop-card-badge" />}
      <SmartImg src={p.images[0]} alt={p.name} label="商品照片待定" className="shop-card-img" />
      <div className="shop-card-name">{p.name}</div>
      {summary ? <ShopPrice price={summary.amount} from={summary.from} /> : <ShopPrice price={null} />}
    </a>
  );
}

function ShopPage({ setPage }) {
  const shopState = useShopData();
  const products = PP.getShopProducts();
  return (
    <div>
      <style>{SHOP_CSS}</style>
      <div style={{ maxWidth: 'var(--container-max)', margin: '0 auto', paddingInline: 'var(--section-x)' }}>
        <div className="shop-head">
          <div className="pp-eyebrow">Shop</div>
          <h1 style={{ fontFamily: 'var(--font-zh)', fontSize: 'var(--fs-h2)', fontWeight: 'var(--fw-light)', letterSpacing: 'var(--ls-heading)', lineHeight: 'var(--lh-heading)', color: 'var(--text-main)' }}>香氛商品</h1>
          <div className="pp-rule" style={{ opacity: 'var(--deco-rule-opacity)' }} />
          <p className="pp-body" style={{ maxWidth: '34em' }}>工作室與學員調的空間香氛。每一支都是限量製作，賣完會標示售罄或開放預購。</p>
        </div>
        {shopState !== 'ready'
          ? <div style={{ paddingBottom: 'var(--section-y)' }}><ShopNotice state={shopState} /></div>
          : products.length > 0
          ? <div className="shop-grid">{products.map(p => <ShopCard key={p.productId} p={p} setPage={setPage} />)}</div>
          : <p className="pp-body" style={{ paddingBottom: 'var(--section-y)' }}>目前沒有上架的商品。</p>}
      </div>
      <SiteFooter />
    </div>
  );
}

Object.assign(window, { ShopPage, ShopPending, ShopStatus, ShopPrice, productPath, useShopData, ShopNotice });
