// TruckOrderCount.jsx — iPad fullscreen count screen.
//
// Top:    cancel + vendor toggle strip + missed-only toggle + finalize
// Body:   storage-area groups with count rows
// Row:    [skip ×] [item name + vendor] · [count input(s)] · on-hand · [order input]
//           - items with sub-unit:  [partial]/N + [full]
//           - items without sub-unit: [full]
//         skipped → tiny strikethrough strip; tap to expand
//
// Count semantics (matches portal):
//   When storage > purchase (e.g. rice: 1 bag = 0.25 bin), display
//   divisor flips to its inverse: "/4 rice bin" instead of "/0.25 rice bin".
//   Math is unchanged — partial input is interpreted in storage units.

const { useState: useTc, useMemo: useMemoTc } = React;

const TruckOrderCount = ({ draft, pars, onUpdateLine, onUpdateMeta, onCancel, onFinalize }) => {
  const allItems   = window.SAMPLE_INVENTORY_ITEMS  || [];
  const allAreas   = window.SAMPLE_STORAGE_AREAS    || [];
  const allVendors = window.SAMPLE_VENDORS          || [];

  const itemById   = useMemoTc(() => Object.fromEntries(allItems.map(i => [i.id, i])), [allItems]);
  const areaById   = useMemoTc(() => Object.fromEntries(allAreas.map(a => [a.id, a])), [allAreas]);
  const vendorById = useMemoTc(() => Object.fromEntries(allVendors.map(v => [v.id, v])), [allVendors]);

  const [showMissedOnly, setShowMissedOnly] = useTc(false);

  // The custom on-screen keypad operates on whichever input the user last
  // tapped. `active` holds { itemId, field, allowDecimal, label } where
  // field is the data key to write to (countStorage / countPurchase / finalOverride).
  const [active, setActive] = useTc(null);

  const excludedVendors = new Set(draft.excludedVendorIds || []);
  const isLineHandled = (line) =>
    line.skipped === true ||
    (line.countStorage !== '' && line.countStorage !== null && line.countStorage !== undefined) ||
    (line.countPurchase !== '' && line.countPurchase !== null && line.countPurchase !== undefined);

  const activeLines = useMemoTc(
    () => draft.lines.filter(l => {
      const item = itemById[l.itemId];
      if (!item || excludedVendors.has(item.vendorId)) return false;
      if (showMissedOnly && isLineHandled(l)) return false;
      return true;
    }),
    [draft.lines, itemById, draft.excludedVendorIds, showMissedOnly]
  );

  // Group by storage area.
  const groups = useMemoTc(() => {
    const buckets = {};
    allAreas.forEach(a => buckets[a.id] = { area: a, lines: [] });
    buckets['__none'] = { area: { id: '__none', name: 'Other / Unassigned' }, lines: [] };
    activeLines.forEach(line => {
      const item = itemById[line.itemId];
      if (!item) return;
      const key = areaById[item.storageAreaId] ? item.storageAreaId : '__none';
      buckets[key].lines.push({ ...line, item });
    });
    return Object.values(buckets).filter(g => g.lines.length > 0);
  }, [activeLines, itemById, areaById, allAreas]);

  // Vendor toggle strip
  const vendorStrip = useMemoTc(() => {
    const counts = {};
    draft.lines.forEach(line => {
      const item = itemById[line.itemId];
      if (!item || !item.vendorId) return;
      counts[item.vendorId] = (counts[item.vendorId] || 0) + 1;
    });
    return Object.keys(counts)
      .map(id => ({ vendor: vendorById[id], count: counts[id] }))
      .filter(v => v.vendor)
      .sort((a, b) => a.vendor.name.localeCompare(b.vendor.name));
  }, [draft.lines, itemById, vendorById]);

  // Header stats — only count active (un-excluded) lines.
  const summary = useMemoTc(() => {
    let counted = 0, total = 0, toOrder = 0, overrides = 0;
    draft.lines.forEach(line => {
      const item = itemById[line.itemId];
      if (!item || excludedVendors.has(item.vendorId)) return;
      total += 1;
      if (line.skipped) { counted += 1; return; }
      const onHand = window.truckOnHand(item, line.countStorage, line.countPurchase);
      const suggested = window.truckSuggested(pars[line.itemId], onHand);
      const finalRaw = (line.finalOverride === null || line.finalOverride === undefined || line.finalOverride === '')
        ? suggested
        : Number(line.finalOverride);
      const final = isNaN(finalRaw) ? 0 : finalRaw;
      if (line.countStorage !== '' || line.countPurchase !== '') counted += 1;
      if (final > 0) toOrder += 1;
      if (line.finalOverride !== null && line.finalOverride !== undefined && line.finalOverride !== '' && Number(line.finalOverride) !== suggested) overrides += 1;
    });
    return { counted, total, toOrder, overrides };
  }, [draft.lines, pars, itemById, draft.excludedVendorIds]);

  const startedBy = window.SAMPLE_STAFF.find(s => s.id === draft.createdByStaffId);

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: 'var(--bg-page)',
      display: 'flex', flexDirection: 'column',
      zIndex: 30,
    }}>
      {/* Header */}
      <div style={{
        flexShrink: 0,
        padding: '14px 22px',
        background: '#FFFFFF',
        borderBottom: '1px solid var(--border-1)',
        display: 'flex', alignItems: 'center', gap: 14,
      }}>
        <button onClick={onCancel} style={{
          width: 36, height: 36, borderRadius: 10,
          background: 'var(--bg-sunken)', border: 'none',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          cursor: 'pointer', flexShrink: 0,
        }} title="Cancel">
          <Icon name="x" size={18} color="var(--fg-1)" strokeWidth={1.8} />
        </button>
        <div style={{ minWidth: 0 }}>
          <div style={{ fontSize: 10, fontWeight: 700, color: 'var(--fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em' }}>
            New truck order · {toFmtDateTo(draft.createdAt)}
          </div>
          <div style={{ fontSize: 17, fontWeight: 600, letterSpacing: '-0.01em', color: 'var(--fg-1)', display: 'flex', alignItems: 'center', gap: 8 }}>
            <span>{summary.counted} / {summary.total} counted</span>
            {summary.toOrder > 0 && (
              <span style={{ fontSize: 13, fontWeight: 500, color: '#2D6A2A' }}>· {summary.toOrder} to order</span>
            )}
            {summary.overrides > 0 && (
              <span style={{ fontSize: 13, fontWeight: 500, color: '#92400E' }}>· {summary.overrides} override</span>
            )}
          </div>
        </div>
        <div style={{ flex: 1 }} />
        <button
          onClick={() => setShowMissedOnly(v => !v)}
          style={{
            padding: '8px 14px',
            background: showMissedOnly ? '#FFF8EC' : 'var(--bg-sunken)',
            border: '1px solid ' + (showMissedOnly ? '#F0CB7D' : 'transparent'),
            borderRadius: 999,
            fontSize: 13, fontWeight: 500,
            color: showMissedOnly ? '#92400E' : 'var(--fg-2)',
            cursor: 'pointer',
            display: 'inline-flex', alignItems: 'center', gap: 6,
          }}
        >
          <Icon name={showMissedOnly ? 'check' : 'eye'} size={14} strokeWidth={2} />
          Missed only
        </button>
        <Btn variant="primary" size="md" icon="check" onClick={onFinalize} disabled={summary.counted === 0}>
          Finalize
        </Btn>
      </div>

      {/* Vendor toggle strip */}
      {vendorStrip.length > 0 && (
        <div style={{
          flexShrink: 0,
          padding: '10px 22px',
          background: '#FAFAF9',
          borderBottom: '1px solid var(--border-1)',
          display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap',
        }}>
          <span style={{ fontSize: 10, fontWeight: 700, color: 'var(--fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em' }}>
            Vendors
          </span>
          {vendorStrip.map(({ vendor, count }) => {
            const excluded = excludedVendors.has(vendor.id);
            return (
              <button
                key={vendor.id}
                onClick={() => {
                  const cur = draft.excludedVendorIds || [];
                  const next = excluded ? cur.filter(id => id !== vendor.id) : [...cur, vendor.id];
                  onUpdateMeta({ excludedVendorIds: next });
                }}
                style={{
                  display: 'inline-flex', alignItems: 'center', gap: 6,
                  padding: '6px 12px',
                  background: excluded ? '#FFFFFF' : 'var(--fg-1)',
                  color: excluded ? 'var(--fg-3)' : '#FFFFFF',
                  border: '1px solid ' + (excluded ? 'var(--border-2)' : 'var(--fg-1)'),
                  borderRadius: 999,
                  fontSize: 13, fontWeight: 500,
                  cursor: 'pointer',
                  textDecoration: excluded ? 'line-through' : 'none',
                }}
              >
                {vendor.name}
                <span style={{
                  fontSize: 11, fontWeight: 600,
                  color: excluded ? 'var(--fg-3)' : 'rgba(255,255,255,0.7)',
                  fontFamily: 'var(--font-num)',
                }}>{count}</span>
              </button>
            );
          })}
          {excludedVendors.size > 0 && (
            <button
              onClick={() => onUpdateMeta({ excludedVendorIds: [] })}
              style={{
                fontSize: 12.5, color: 'var(--fg-2)',
                background: 'transparent', padding: '4px 10px',
                marginLeft: 'auto', cursor: 'pointer', border: 'none',
              }}
            >Include all</button>
          )}
        </div>
      )}

      {/* Body */}
      <div className="scroll-soft" style={{ flex: 1, overflowY: 'auto', padding: '16px 22px 24px' }}>
        {/* Optional note — focusing this dismisses the on-screen keypad so the
            native iPad keyboard can come up for text entry. */}
        <div style={{ marginBottom: 14 }}>
          <input
            value={draft.note || ''}
            onChange={e => onUpdateMeta({ note: e.target.value })}
            onFocus={() => setActive(null)}
            placeholder="Optional note for this order…"
            style={{
              width: '100%', height: 38, padding: '0 14px',
              borderRadius: 10,
              border: '1px solid var(--border-2)',
              background: '#FFFFFF',
              fontSize: 13.5, color: 'var(--fg-1)',
              outline: 'none',
            }}
          />
        </div>

        {groups.length === 0 ? (
          <div style={{ padding: 36, textAlign: 'center', fontSize: 14, color: 'var(--fg-2)' }}>
            {vendorStrip.length > 0 && excludedVendors.size === vendorStrip.length
              ? 'All vendors are excluded — select at least one above.'
              : showMissedOnly
                ? 'Nothing left to count. Great work.'
                : 'No active items in inventory.'}
          </div>
        ) : groups.map(group => (
          <CountGroup
            key={group.area.id}
            area={group.area}
            lines={group.lines}
            pars={pars}
            vendorById={vendorById}
            onUpdateLine={onUpdateLine}
            active={active}
            setActive={setActive}
          />
        ))}
        {/* Reserve scroll space so the bottom keypad never covers the last row */}
        {active && <div style={{ height: 290 }} />}
      </div>

      {/* Custom on-screen keypad — sticks to the bottom when an input is active */}
      {active && (
        <CountKeypad
          active={active}
          draft={draft}
          pars={pars}
          itemById={itemById}
          onApply={(line, patch) => onUpdateLine(line.itemId, patch)}
          onClose={() => setActive(null)}
        />
      )}
    </div>
  );
};

// ------------------------------------------------------------------
// One storage-area group
// ------------------------------------------------------------------
const CountGroup = ({ area, lines, pars, vendorById, onUpdateLine, active, setActive }) => {
  const counted = lines.filter(l => l.skipped || l.countStorage !== '' || l.countPurchase !== '').length;
  return (
    <div style={{ marginBottom: 24 }}>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 10,
        padding: '0 4px 8px',
      }}>
        <Icon name="box" size={16} color="var(--fg-2)" strokeWidth={1.7} />
        <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--fg-1)', letterSpacing: '-0.005em' }}>{area.name}</div>
        <div style={{ fontSize: 12, color: 'var(--fg-3)', fontFamily: 'var(--font-num)' }}>
          {counted}/{lines.length}
        </div>
      </div>
      <div style={{
        background: '#FFFFFF',
        border: '1px solid var(--border-2)',
        borderRadius: 14,
        overflow: 'hidden',
      }}>
        {lines.map((line, i) => (
          <CountRow
            key={line.itemId}
            line={line}
            par={pars[line.itemId]}
            vendor={vendorById[line.item.vendorId]}
            onUpdate={(patch) => onUpdateLine(line.itemId, patch)}
            isLast={i === lines.length - 1}
            active={active}
            setActive={setActive}
          />
        ))}
      </div>
    </div>
  );
};

// ------------------------------------------------------------------
// One row
// ------------------------------------------------------------------
const CountRow = ({ line, par, vendor, onUpdate, isLast, active, setActive }) => {
  const item = line.item;
  const skipped = line.skipped === true;

  if (skipped) {
    return (
      <div
        onClick={() => onUpdate({ skipped: false })}
        style={{
          display: 'flex', alignItems: 'center', gap: 12,
          padding: '10px 16px',
          borderBottom: isLast ? 'none' : '1px solid var(--border-2)',
          background: '#FBFAF8',
          cursor: 'pointer',
        }}
        title="Tap to un-skip"
      >
        <span style={{
          width: 28, height: 28, borderRadius: 999,
          background: 'var(--bg-sunken)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
        }}>
          <Icon name="chevronD" size={14} color="var(--fg-3)" strokeWidth={1.8} />
        </span>
        <span style={{ fontSize: 13, color: 'var(--fg-3)', textDecoration: 'line-through', flex: 1 }}>
          {item.name}
        </span>
        <span style={{
          fontSize: 10, fontWeight: 700, color: 'var(--fg-3)',
          textTransform: 'uppercase', letterSpacing: '0.08em',
        }}>Skipped</span>
      </div>
    );
  }

  const onHand = window.truckOnHand(item, line.countStorage, line.countPurchase);
  const suggested = window.truckSuggested(par, onHand);
  const hasOverride = line.finalOverride !== null && line.finalOverride !== undefined && line.finalOverride !== '';
  const finalAmount = hasOverride ? Number(line.finalOverride) : suggested;
  const isOverridden = hasOverride && Number(line.finalOverride) !== suggested;
  const hasCount = line.countStorage !== '' || line.countPurchase !== '';
  const hasSubUnit = item.conversion && Number(item.conversion) !== 1 && item.storageUnit && item.storageUnit !== item.purchaseUnit;
  const displayN = window.truckDisplayN(item);
  const isStorageLarger = window.truckIsStorageLarger(item);
  const onHandDisplay = window.truckOnHandDisplay(item, line.countStorage, line.countPurchase);

  // Inputs are arranged by SIZE, not by purchase-vs-storage:
  //   - Smaller-unit input (with /N divisor) on the left
  //   - Larger-unit input on the right
  // For broccoli (R=2, purchase larger): small=storage(pan), large=purchase(case)
  // For rice     (R<1, storage larger):  small=purchase(bag), large=storage(bin)
  const smallerKey  = isStorageLarger ? 'countPurchase' : 'countStorage';
  const smallerUnit = isStorageLarger ? item.purchaseUnit : item.storageUnit;
  const largerKey   = isStorageLarger ? 'countStorage' : 'countPurchase';
  const largerUnit  = isStorageLarger ? item.storageUnit : item.purchaseUnit;
  const onHandDisplayUnit = largerUnit;

  // Input styles — chunkier than the portal (touch targets)
  const fullCountStyle = {
    width: 64, height: 40,
    border: '1px solid var(--border-2)',
    borderRadius: 8,
    padding: '0 8px',
    fontFamily: 'var(--font-num)',
    fontSize: 16, fontWeight: 600,
    textAlign: 'center',
    background: '#FFFFFF',
  };
  const subCountStyle = { ...fullCountStyle, width: 52, height: 32, fontSize: 13 };

  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: '1.4fr 1.5fr 0.7fr 1fr',
      padding: '12px 16px',
      borderBottom: isLast ? 'none' : '1px solid var(--border-2)',
      alignItems: 'center',
      gap: 12,
      background: hasCount ? '#FBFAF8' : 'transparent',
    }}>
      {/* Item + skip */}
      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 8, minWidth: 0 }}>
        <button
          onClick={() => onUpdate({ skipped: true })}
          title="Skip"
          style={{
            width: 26, height: 26, borderRadius: 999,
            background: 'transparent', border: '1px solid var(--border-2)',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            flexShrink: 0, marginTop: 2, cursor: 'pointer',
          }}
        >
          <Icon name="x" size={12} color="var(--fg-3)" strokeWidth={2} />
        </button>
        <div style={{ minWidth: 0 }}>
          <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--fg-1)', lineHeight: 1.25, letterSpacing: '-0.005em' }}>
            {item.name}
          </div>
          <div style={{ fontSize: 11.5, color: 'var(--fg-3)', marginTop: 2 }}>
            {vendor?.name || 'No vendor'}
            {par && (
              <span style={{ marginLeft: 6, fontFamily: 'var(--font-num)' }}>
                · par {par.threshold !== null && par.threshold !== undefined ? `${par.threshold}–${par.max}` : `up to ${par.max}`}
              </span>
            )}
          </div>
        </div>
      </div>

      {/* Count inputs — right-aligned so full-unit column lines up across rows.
          Each "input" is actually a button that activates the bottom keypad. */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, justifyContent: 'flex-end' }}>
        {hasSubUnit && (
          <>
            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 2 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                <TapInput
                  value={line[smallerKey]}
                  active={active && active.itemId === item.id && active.field === smallerKey}
                  onTap={() => setActive({
                    itemId: item.id, field: smallerKey, allowDecimal: true,
                    label: `${item.name} · ${smallerUnit}`,
                  })}
                  style={subCountStyle}
                />
                <span style={{ fontSize: 13, color: 'var(--fg-3)', fontFamily: 'var(--font-num)', fontWeight: 500 }}>
                  /{toFmtQtyTo(displayN)}
                </span>
              </div>
              <span style={{ fontSize: 10, color: 'var(--fg-3)', lineHeight: 1 }}>
                {smallerUnit}
              </span>
            </div>
            <span style={{ fontSize: 16, color: 'var(--fg-3)', fontWeight: 400, margin: '0 2px' }}>+</span>
          </>
        )}
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 2 }}>
          <TapInput
            value={line[largerKey]}
            active={active && active.itemId === item.id && active.field === largerKey}
            onTap={() => {
              // Sanitize any legacy decimal in this integer-only field on entry.
              const cur = String(line[largerKey] ?? '');
              if (cur.includes('.')) onUpdate({ [largerKey]: cur.split('.')[0] });
              setActive({
                itemId: item.id, field: largerKey, allowDecimal: false,
                label: `${item.name} · ${largerUnit}`,
              });
            }}
            style={fullCountStyle}
          />
          {hasSubUnit && (
            <span style={{ fontSize: 10, color: 'var(--fg-3)', lineHeight: 1 }}>
              {largerUnit}
            </span>
          )}
        </div>
      </div>

      {/* On hand */}
      <div style={{ textAlign: 'right' }}>
        <div style={{ fontSize: 15, fontWeight: 600, fontFamily: 'var(--font-num)', color: hasCount ? 'var(--fg-1)' : 'var(--fg-3)' }}>
          {hasCount ? toFmtQtyTo(onHandDisplay) : '—'}
        </div>
        <div style={{ fontSize: 10, color: 'var(--fg-3)' }}>{onHandDisplayUnit}</div>
      </div>

      {/* Order */}
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 3 }}>
        {isOverridden && (
          <span style={{
            display: 'inline-flex', alignItems: 'center', gap: 4,
            fontSize: 9, fontWeight: 700, color: '#92400E',
            background: '#FDE68A', padding: '2px 6px', borderRadius: 4,
            letterSpacing: '0.04em', textTransform: 'uppercase',
            whiteSpace: 'nowrap',
          }}>was {suggested}</span>
        )}
        <TapInput
          value={hasOverride ? line.finalOverride : (hasCount ? String(suggested) : '')}
          active={active && active.itemId === item.id && active.field === 'finalOverride'}
          onTap={() => {
            // First tap on the auto-suggested value: pre-fill the override
            // with the suggested number so the user can backspace + retype.
            if (!hasOverride && hasCount) {
              onUpdate({ finalOverride: String(suggested) });
            }
            setActive({
              itemId: item.id, field: 'finalOverride', allowDecimal: false,
              label: `${item.name} · order`,
            });
          }}
          style={{
            width: 64, height: 40,
            border: isOverridden ? '1px solid #F0CB7D' : '1px solid var(--border-2)',
            borderRadius: 8, padding: '0 8px',
            fontFamily: 'var(--font-num)',
            fontSize: 17, fontWeight: 700,
            textAlign: 'center',
            background: isOverridden ? '#FFF8EC' : (finalAmount > 0 ? '#F0F7E8' : '#FFFFFF'),
            color: isOverridden ? '#92400E' : (finalAmount > 0 ? '#2D6A2A' : 'var(--fg-3)'),
          }}
        />
        <span style={{ fontSize: 10, color: 'var(--fg-3)' }}>{item.purchaseUnit}</span>
      </div>
    </div>
  );
};

// ------------------------------------------------------------------
// TapInput — looks like a number input, but is actually a button that
// activates the bottom keypad. No native iOS keyboard pop-up.
// ------------------------------------------------------------------
const TapInput = ({ value, active, onTap, style }) => {
  const display = value === '' || value === null || value === undefined ? '' : String(value);
  return (
    <button
      type="button"
      onClick={onTap}
      style={{
        ...style,
        cursor: 'pointer',
        outline: active ? '2px solid var(--fg-1)' : 'none',
        outlineOffset: '1px',
        // When active, gently tint to confirm focus.
        boxShadow: active ? '0 0 0 4px rgba(15,17,21,0.08)' : 'none',
      }}
    >
      {display === '' ? <span style={{ color: 'var(--fg-3)', fontWeight: 400 }}>0</span> : display}
    </button>
  );
};

// ------------------------------------------------------------------
// CountKeypad — sticky bottom keypad. Operates on the currently active
// input (set via setActive in CountRow). Appends digits, supports decimal
// when allowed, backspace, and a Done button. Closes when Done is tapped.
// ------------------------------------------------------------------
const CountKeypad = ({ active, draft, pars, itemById, onApply, onClose }) => {
  const line = draft.lines.find(l => l.itemId === active.itemId);
  if (!line) return null;
  const item = itemById[line.itemId];

  // Live preview of on-hand + suggested for the currently-being-edited item.
  const onHand = item ? window.truckOnHand(item, line.countStorage, line.countPurchase) : 0;
  const suggested = item ? window.truckSuggested(pars[line.itemId], onHand) : 0;
  const onHandDisplay = item ? window.truckOnHandDisplay(item, line.countStorage, line.countPurchase) : 0;
  const isStorageLarger = item ? window.truckIsStorageLarger(item) : false;
  const onHandUnit = item ? (isStorageLarger ? item.storageUnit : item.purchaseUnit) : '';

  const press = (key) => {
    let cur = String(line[active.field] ?? '');
    // Bulletproof: integer-only fields get any pre-existing decimal stripped
    // before we append. Covers legacy drafts where the value was stored as a
    // float and protects against an empty "." being left around.
    if (!active.allowDecimal && cur.includes('.')) {
      cur = cur.split('.')[0];
    }
    let next = cur;

    if (key === '⌫') {
      next = cur.slice(0, -1);
    } else if (key === '.') {
      if (!active.allowDecimal) return;
      if (cur.includes('.')) return;
      next = cur === '' ? '0.' : cur + '.';
    } else {
      // Limit length to 5 chars
      if (cur.length >= 5) return;
      // Replace leading "0" with the new digit so user doesn't have to clear it
      if (cur === '0') next = key;
      else next = cur + key;
    }

    // For finalOverride: if user backspaces all the way out, restore to null
    // (so the row shows the auto-suggested value again).
    if (active.field === 'finalOverride' && next === '') {
      onApply(line, { finalOverride: null });
      return;
    }
    // Same: if they type exactly the suggested, clear override.
    if (active.field === 'finalOverride' && Number(next) === suggested) {
      onApply(line, { finalOverride: null });
      return;
    }
    onApply(line, { [active.field]: next });
  };

  const Key = ({ k, wide, accent }) => (
    <button
      onClick={() => press(k)}
      style={{
        height: 56,
        gridColumn: wide ? 'span 2' : 'auto',
        background: accent ? 'var(--fg-1)' : '#FFFFFF',
        color: accent ? '#FFFFFF' : 'var(--fg-1)',
        border: '1px solid var(--border-2)',
        borderRadius: 12,
        fontSize: 24, fontWeight: 500, letterSpacing: '-0.01em',
        fontFamily: k === '⌫' ? 'inherit' : 'var(--font-num)',
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        cursor: 'pointer',
        transition: 'transform 80ms var(--ease-snap), background 120ms',
      }}
      onTouchStart={e => e.currentTarget.style.background = '#F2F2F5'}
      onTouchEnd={e => e.currentTarget.style.background = accent ? 'var(--fg-1)' : '#FFFFFF'}
      onMouseDown={e => e.currentTarget.style.transform = 'scale(0.97)'}
      onMouseUp={e => e.currentTarget.style.transform = ''}
      onMouseLeave={e => e.currentTarget.style.transform = ''}
    >
      {k === '⌫' ? <Icon name="backspace" size={20} color={accent ? '#FFFFFF' : 'var(--fg-1)'} strokeWidth={1.6} /> : k}
    </button>
  );

  return (
    <div style={{
      position: 'absolute', bottom: 0, left: 0, right: 0,
      background: 'var(--bg-page)',
      borderTop: '1px solid var(--border-1)',
      boxShadow: '0 -4px 24px rgba(0,0,0,0.08)',
      zIndex: 40,
      padding: '10px 16px 14px',
      animation: 'keypad-slide-up 200ms var(--ease-snap)',
    }}>
      {/* Context bar */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 12,
        padding: '8px 12px 10px',
      }}>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{ fontSize: 10, fontWeight: 700, color: 'var(--fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em' }}>
            Editing
          </div>
          <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--fg-1)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
            {active.label}
          </div>
        </div>
        {item && (line.countStorage !== '' || line.countPurchase !== '') && (
          <div style={{ textAlign: 'right' }}>
            <div style={{ fontSize: 10, fontWeight: 700, color: 'var(--fg-3)', textTransform: 'uppercase', letterSpacing: '0.08em' }}>
              On hand
            </div>
            <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--fg-1)', fontFamily: 'var(--font-num)' }}>
              {toFmtQtyTo(onHandDisplay)} <span style={{ fontSize: 11, color: 'var(--fg-3)', fontWeight: 500 }}>{onHandUnit}</span>
            </div>
          </div>
        )}
        <button
          onClick={onClose}
          style={{
            padding: '8px 16px', height: 36,
            background: 'var(--fg-1)', color: '#FFFFFF',
            border: 'none', borderRadius: 10,
            fontSize: 13.5, fontWeight: 600, cursor: 'pointer',
            letterSpacing: '-0.005em',
          }}
        >Done</button>
      </div>

      {/* 3-column digit grid */}
      <div style={{
        display: 'grid',
        gridTemplateColumns: 'repeat(3, 1fr)',
        gap: 8,
        maxWidth: 560,
        margin: '0 auto',
      }}>
        <Key k="1" /><Key k="2" /><Key k="3" />
        <Key k="4" /><Key k="5" /><Key k="6" />
        <Key k="7" /><Key k="8" /><Key k="9" />
        {active.allowDecimal
          ? <Key k="." />
          : <div />}
        <Key k="0" />
        <Key k="⌫" />
      </div>

      <style>{`
        @keyframes keypad-slide-up {
          from { transform: translateY(100%); }
          to { transform: translateY(0); }
        }
      `}</style>
    </div>
  );
};

Object.assign(window, { TruckOrderCount });
