/* Shopping list — recursively flattens current Buy/Craft choices into raw
 * materials. Reuses defaultModeFor so it stays in lockstep with the tree. */

const { useState: useStateS, useMemo: useMemoS, useEffect: useEffectS } = React;

// Walk the recipe and aggregate all leaf "buy" materials into a flat map.
function walkShoppingList(recipe, choices, priceOverrides, ctx, opts = {}) {
  const scale = opts.scale ?? 1;
  const depth = opts.depth ?? 0;
  const visited = opts.visited ?? new Set();
  const items = opts.items ?? new Map(); // itemType -> { name, qty, unitPrice, hasPrice }
  const threshold = ctx.laborThreshold ?? 0;
  const laborMult = ctx.laborMult ?? 1;
  let labor = (recipe.laborCost || 0) * scale * laborMult;

  for (const mat of recipe.materials) {
    const qty = mat.amount * scale;
    const key = mat.itemType;
    const subRecipe = window.getRecipeFor(key, ctx);
    const canCraft = !!subRecipe && depth < 6 && !visited.has(key);
    const choice = (choices[key] ||
      window.defaultModeFor(key, qty, subRecipe, canCraft, ctx, choices, priceOverrides, depth, visited, threshold));

    if (choice === 'craft' && canCraft) {
      const newV = new Set(visited); newV.add(key);
      const subScale = qty / subRecipe.productCount;
      const sub = walkShoppingList(subRecipe, choices, priceOverrides, ctx, {
        scale: subScale, depth: depth + 1, visited: newV, items,
      });
      labor += sub.labor;
    } else {
      const price = (priceOverrides[key] != null) ? priceOverrides[key] : (ctx.prices[key] ?? 0);
      const hasPrice = ctx.prices[key] != null || priceOverrides[key] != null;
      const existing = items.get(key);
      if (existing) {
        existing.qty += qty;
      } else {
        items.set(key, {
          name: mat.name,
          itemType: key,
          qty,
          unitPrice: price,
          hasPrice,
        });
      }
    }
  }

  return { items, labor };
}

function ShoppingListModal({ open, onClose, recipe, ctx, choices, priceOverrides, currency, laborValue }) {
  const [batches, setBatches] = useStateS(1);
  const [copied, setCopied] = useStateS(false);

  useEffectS(() => {
    if (!open) { setBatches(1); setCopied(false); }
  }, [open]);

  // Esc to close
  useEffectS(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);

  const result = useMemoS(() => {
    if (!open || !recipe) return null;
    const { items, labor } = walkShoppingList(recipe, choices, priceOverrides, ctx, { scale: batches });
    const list = [...items.values()].map(it => ({
      ...it,
      subtotal: it.unitPrice * it.qty,
    }));
    list.sort((a, b) => b.subtotal - a.subtotal);
    const totalCost = list.reduce((s, x) => s + x.subtotal, 0);
    const missingCount = list.filter(x => !x.hasPrice).length;
    return { list, totalCost, labor, missingCount };
  }, [open, recipe, ctx, choices, priceOverrides, batches]);

  if (!open || !recipe || !result) return null;

  const { list, totalCost, labor, missingCount } = result;
  const laborGold = labor * (laborValue || 0);
  const produced = recipe.productCount * batches;

  async function copyText() {
    const lines = [
      `Shopping list — ${recipe.productName} ×${produced}`,
      ...list.map(x => `${fmtInt(x.qty)}× ${x.name}${x.hasPrice ? ` (${fmtG(x.subtotal)}${currency})` : ' (no price)'}`),
      ``,
      `Total cost: ${fmtG(totalCost)}${currency}`,
      `Labor: ${fmtInt(labor)} lp${laborValue > 0 ? ` (≈ ${fmtG(laborGold)}${currency})` : ''}`,
    ];
    try {
      await navigator.clipboard.writeText(lines.join('\n'));
      setCopied(true);
      setTimeout(() => setCopied(false), 1500);
    } catch (e) {}
  }

  return (
    <div className="shop-overlay" onClick={onClose}>
      <div className="shop-modal" onClick={(e) => e.stopPropagation()}>
        <div className="shop-head">
          <div style={{minWidth: 0}}>
            <div className="r-cat">Shopping List</div>
            <h2 className="shop-title">{recipe.productName} <span className="shop-x">×{produced}</span></h2>
            <div className="r-tags" style={{marginTop: 6}}>
              <span>{list.length} unique material{list.length === 1 ? '' : 's'}</span>
              {missingCount > 0 && (
                <>
                  <span className="dot" />
                  <span style={{color: 'var(--garnet)'}}>{missingCount} no price</span>
                </>
              )}
              <span className="dot" />
              <span style={{color: 'var(--labor)'}}>{fmtInt(labor)} labor</span>
              <span className="dot" />
              <span style={{color: 'var(--muted)', fontSize: 11}}>reflects current Buy/Craft picks</span>
            </div>
          </div>
          <div className="shop-actions">
            <div className="batch-stepper">
              <span className="thr-unit">crafts</span>
              <button className="thr-step" onClick={() => setBatches(b => Math.max(1, b - 1))}>−</button>
              <input
                type="number"
                className="thr-input"
                value={batches}
                min="1"
                onChange={(e) => setBatches(Math.max(1, parseInt(e.target.value || '1', 10)))}
              />
              <button className="thr-step" onClick={() => setBatches(b => b + 1)}>+</button>
            </div>
            <button className="btn" onClick={copyText}>{copied ? '✓ Copied' : '⧉ Copy'}</button>
            <button className="btn shop-close" onClick={onClose}>Close ✕</button>
          </div>
        </div>

        <div className="shop-body">
          <div className="shop-row shop-head-row">
            <div>Material</div>
            <div className="num">Qty</div>
            <div className="num">Unit · {currency}</div>
            <div className="num">Subtotal</div>
          </div>
          {list.map(item => (
            <div key={item.itemType} className={`shop-row ${!item.hasPrice ? 'missing' : ''}`}>
              <div className="shop-name">
                <window.ItemIcon itemType={item.itemType} name={item.name} size="sm" />
                <div style={{minWidth: 0}}>
                  <div className="ing-label">{item.name}</div>
                  <div className="ing-meta">
                    <span className="mono" style={{opacity: 0.6}}>ID {item.itemType}</span>
                    {!item.hasPrice && <span className="nomarket">no price</span>}
                    {(() => {
                      const vol = ctx.volumes && ctx.volumes[item.itemType];
                      if (vol == null) return null;
                      const unit = vol.p === 'week' ? '/wk' : '/day';
                      // Daily volumes compare against the full shopping qty;
                      // weekly volumes are a fuzzier signal (still meaningful
                      // for "is this item ever traded at scale"). Tight check
                      // applies only to daily values.
                      const tight = vol.p === 'day' && vol.v < item.qty;
                      const periodLabel = vol.p === 'week' ? 'Weekly' : 'Daily';
                      return (
                        <span
                          className={`vol-tag mini ${vol.p === 'week' ? 'weekly' : ''} ${tight ? 'tight' : ''}`}
                          title={tight
                            ? `Only ${window.fmtCompact(vol.v)} units traded per day — you need ${window.fmtCompact(item.qty)}. May not be available at scale.`
                            : `${periodLabel} auction volume: ${vol.v.toLocaleString()} units${unit === '/wk' ? '/week' : '/day'}`}
                        >
                          <span className="vol-ico">↻</span>{window.fmtCompact(vol.v)}{unit}
                        </span>
                      );
                    })()}
                  </div>
                </div>
              </div>
              <div className="num mono shop-qty">×{fmtInt(item.qty)}</div>
              <div className="num mono" style={{color: item.hasPrice ? 'var(--parch)' : 'var(--muted)'}}>
                {item.hasPrice ? fmtG(item.unitPrice) : '—'}
              </div>
              <div className="num mono" style={{color: item.hasPrice ? 'var(--gold)' : 'var(--garnet)', fontWeight: 500}}>
                {item.hasPrice ? `${fmtG(item.subtotal)}${currency}` : 'unset'}
              </div>
            </div>
          ))}
          {list.length === 0 && (
            <div style={{padding: 40, textAlign: 'center', color: 'var(--muted)'}}>
              No materials to buy — this recipe is fully self-crafted from labor alone.
            </div>
          )}
        </div>

        <div className="shop-foot">
          <div className="shop-foot-row">
            <span>Materials cost</span>
            <span className="mono" style={{color: 'var(--parch)'}}>{fmtG(totalCost)}{currency}</span>
          </div>
          <div className="shop-foot-row">
            <span style={{color: 'var(--labor)'}}>Labor</span>
            <span className="mono" style={{color: 'var(--labor)'}}>
              {fmtInt(labor)} lp{laborValue > 0 ? ` · ≈ ${fmtG(laborGold)}${currency}` : ''}
            </span>
          </div>
          <div className="shop-foot-row total">
            <span>Total outlay</span>
            <span className="mono" style={{color: 'var(--gold)', fontWeight: 600}}>
              {fmtG(totalCost + laborGold)}{currency}
            </span>
          </div>
        </div>
      </div>
    </div>
  );
}

window.ShoppingListModal = ShoppingListModal;
window.walkShoppingList = walkShoppingList;
