// ─── Settld · Split strategies (interactive) ────────────────────────────────
// Single screen. Four modes. Per-mode state preserved. Live bar morph.

const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ─── Setup ──────────────────────────────────────────────────────────────────
const TOTAL = 4200;
const PEOPLE = [
  { id: 'you',   name: 'You',   initial: 'Y', cls: 'av-you',   color: '#0E7C66' },
  { id: 'aarav', name: 'Aarav', initial: 'A', cls: 'av-aarav', color: '#E76F51' },
  { id: 'priya', name: 'Priya', initial: 'P', cls: 'av-priya', color: '#F4C94E' },
];
const IDS = PEOPLE.map(p => p.id);
const BY_ID = Object.fromEntries(PEOPLE.map(p => [p.id, p]));

const MODES = [
  { id: 'equal',   label: 'Equal'   },
  { id: 'manual',  label: 'Manual'  },
  { id: 'percent', label: '%'       },
  { id: 'shares',  label: 'Shares'  },
];

// ─── Helpers ────────────────────────────────────────────────────────────────
function fmt(n) {
  if (n == null) return '0';
  const v = Math.round(n);
  const s = String(Math.abs(v));
  let out;
  if (s.length <= 3) out = s;
  else {
    const last3 = s.slice(-3);
    const rest = s.slice(0, -3);
    out = rest.replace(/\B(?=(\d{2})+(?!\d))/g, ',') + ',' + last3;
  }
  return v < 0 ? '−' + out : out;
}
function haptic(ms = 8) {
  if (navigator.vibrate) try { navigator.vibrate(ms); } catch (_) {}
}

// ─── Number tick (animates on value change) ─────────────────────────────────
function Tick({ children }) {
  // key changes via React's reconciliation when content changes; we use a wrap span
  // and let CSS animate on remount via React keys passed by parent.
  return <span className="tick">{children}</span>;
}

// ─── Avatar ─────────────────────────────────────────────────────────────────
function Avatar({ p }) {
  return <span className={`av ${p.cls}`}>{p.initial}</span>;
}

// ─── Segmented control ──────────────────────────────────────────────────────
function Segmented({ mode, setMode }) {
  const idx = MODES.findIndex(m => m.id === mode);
  return (
    <div className="seg-wrap">
      <div className="seg" role="tablist">
        <div
          className="seg-thumb"
          style={{ transform: `translateX(calc(${idx} * 100%))` }}
        />
        {MODES.map(m => (
          <button
            key={m.id}
            className={`seg-btn${m.id === mode ? ' active' : ''}`}
            onClick={() => { if (mode !== m.id) { haptic(10); setMode(m.id); } }}
          >{m.label}</button>
        ))}
      </div>
    </div>
  );
}

// ─── The bar (mode-aware) ───────────────────────────────────────────────────
function SplitBar({ mode, fractions, locked, draggable, onDrag }) {
  // fractions: ordered array of {id, pct, excluded}
  const barRef = useRef();
  const [dragState, setDragState] = useState(null); // {idx, startX, startPctL, startPctR}

  useEffect(() => {
    if (!dragState) return;
    const move = (e) => {
      const w = barRef.current?.getBoundingClientRect().width || 1;
      const clientX = e.touches ? e.touches[0].clientX : e.clientX;
      const dx = clientX - dragState.startX;
      const dPct = (dx / w) * 100;
      onDrag(dragState.idx, dPct, dragState.startPctL, dragState.startPctR);
    };
    const up = () => { setDragState(null); haptic(4); };
    window.addEventListener('mousemove', move);
    window.addEventListener('touchmove', move, { passive: false });
    window.addEventListener('mouseup', up);
    window.addEventListener('touchend', up);
    return () => {
      window.removeEventListener('mousemove', move);
      window.removeEventListener('touchmove', move);
      window.removeEventListener('mouseup', up);
      window.removeEventListener('touchend', up);
    };
  }, [dragState, onDrag]);

  const startDrag = (idx, e) => {
    e.preventDefault();
    const clientX = e.touches ? e.touches[0].clientX : e.clientX;
    const left  = fractions[idx];
    const right = fractions[idx + 1];
    if (!left || !right) return;
    haptic(10);
    setDragState({
      idx,
      startX: clientX,
      startPctL: left.pct,
      startPctR: right.pct,
    });
  };

  return (
    <div className="bar-wrap">
      <div className="bar-meta">
        <span>split bar</span>
        <span className={`right${draggable ? ' draggable' : ''}`}>
          {draggable ? 'drag to adjust' : 'read-only'}
        </span>
      </div>
      <div
        ref={barRef}
        className={`bar${draggable ? ' draggable' : ''}${dragState ? ' dragging' : ''}`}
      >
        {fractions.map((f, i) => {
          const p = BY_ID[f.id];
          const isLocked = locked && locked.has(f.id);
          const isExcluded = f.excluded;
          // Show a drag handle if this segment AND the next are unlocked, draggable mode, and not excluded
          const nextSeg = fractions[i + 1];
          const showHandle = draggable && nextSeg && !isLocked && !locked.has(nextSeg.id)
                             && !isExcluded && !nextSeg.excluded;
          return (
            <div
              key={f.id}
              className={`bar-seg${isLocked ? ' locked' : ''}${isExcluded ? ' excluded' : ''}`}
              style={{
                background: p.color,
                flexBasis: `${Math.max(0, f.pct)}%`,
              }}
            >
              {showHandle && (
                <div
                  className={`bar-handle${dragState && dragState.idx === i ? ' active' : ''}`}
                  onMouseDown={(e) => startDrag(i, e)}
                  onTouchStart={(e) => startDrag(i, e)}
                  aria-label="drag to redistribute"
                />
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ─── Right-side panes per mode ──────────────────────────────────────────────
function EqualPane({ p, excluded, share, onToggle }) {
  return (
    <div className="mode-pane" key={`eq-${p.id}`}>
      <span className={`lr-readonly${excluded ? ' muted' : ''}`}>
        <span className="cur">₹</span>
        <span className="tick" key={excluded ? 'x' : share}>
          {excluded ? '—' : fmt(share)}
        </span>
      </span>
      <button
        className={`lr-x ${excluded ? 'excluded-x' : 'included'}`}
        onClick={onToggle}
        aria-label={excluded ? 'include' : 'exclude'}
      >
        <svg viewBox="0 0 12 12" fill="none">
          <path d="M2 2L10 10M10 2L2 10" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/>
        </svg>
      </button>
    </div>
  );
}

function ManualPane({ p, value, isAuto, onChange, onFocus }) {
  return (
    <div className="mode-pane" key={`mn-${p.id}`}>
      {isAuto && <span className="auto-pill" key="auto">auto</span>}
      <label className="lr-input" onClick={onFocus}>
        <span className="cur">₹</span>
        <input
          type="text"
          inputMode="numeric"
          value={value || 0}
          onChange={(e) => {
            const v = e.target.value.replace(/\D/g, '').slice(0, 6);
            onChange(parseInt(v || '0', 10));
          }}
          onFocus={onFocus}
        />
      </label>
    </div>
  );
}

function PercentPane({ p, pct, locked, onChange, onFocus }) {
  return (
    <div className="mode-pane" key={`pc-${p.id}`}>
      <div className="pct-mini-bar">
        <span
          className="fill"
          style={{ width: `${Math.max(0, pct)}%`, color: p.color }}
        />
      </div>
      <label className={`lr-input pct${locked ? ' locked' : ''}`} onClick={onFocus}>
        <input
          type="text"
          inputMode="numeric"
          value={Math.round(pct)}
          disabled={locked}
          onChange={(e) => {
            const v = e.target.value.replace(/\D/g, '').slice(0, 3);
            onChange(parseInt(v || '0', 10));
          }}
          onFocus={onFocus}
        />
        <span className="pct-sym">%</span>
      </label>
    </div>
  );
}

function SharesPane({ p, shares, totalShares, onChange }) {
  const ruppees = totalShares > 0 ? (shares / totalShares) * TOTAL : 0;
  // intentionally unused here; ₹ shown in lr-sub by parent
  return (
    <div className="mode-pane" key={`sh-${p.id}`}>
      <div className="stepper">
        <button
          onClick={() => onChange(Math.max(0, shares - 0.5))}
          disabled={shares <= 0}
          aria-label="decrease share"
        >−</button>
        <span className="val">
          <span className="tick" key={shares}>{shares % 1 === 0 ? shares : shares.toFixed(1)}</span>
        </span>
        <button
          onClick={() => onChange(shares + 0.5)}
          aria-label="increase share"
        >+</button>
      </div>
    </div>
  );
}

// ─── Main ───────────────────────────────────────────────────────────────────
function App() {
  const [mode, setMode] = useState('equal');

  // Equal state
  const [excluded, setExcluded] = useState(new Set());

  // Manual state — values per id + most-recently-edited order (last = most recent, first = auto)
  const [manualAmts, setManualAmts] = useState({ you: 1400, aarav: 1400, priya: 1400 });
  const [manualOrder, setManualOrder] = useState(['priya', 'aarav', 'you']); // priya = auto initially

  // Percent state
  const [percent, setPercent] = useState({ you: 33, aarav: 33, priya: 34 });
  const [locked, setLocked] = useState(new Set());

  // Shares state (half-share increments)
  const [shares, setShares] = useState({ you: 1, aarav: 1, priya: 1 });

  // UI
  const [toast, setToast] = useState(null);
  const [ctaBreath, setCtaBreath] = useState(false);
  const [deltaFlash, setDeltaFlash] = useState(false);

  // ─── Derived: per-person values + fractions for the bar ───────────────────
  const activeEq = IDS.filter(id => !excluded.has(id));
  const equalShare = activeEq.length > 0 ? TOTAL / activeEq.length : 0;

  // manual derived: elastic = manualOrder[0]
  const elasticId = manualOrder[0];
  const sumNonElastic = IDS.filter(id => id !== elasticId)
    .reduce((s, id) => s + (manualAmts[id] || 0), 0);
  const elasticVal = Math.max(0, TOTAL - sumNonElastic);
  const manualEffective = { ...manualAmts, [elasticId]: elasticVal };
  const manualSum = sumNonElastic + elasticVal;
  const manualDelta = manualSum - TOTAL; // positive when others overflow (elastic clamped to 0)

  // percent
  const pctSum = IDS.reduce((s, id) => s + (percent[id] || 0), 0);
  const pctDelta = pctSum - 100;

  // shares
  const totalShares = IDS.reduce((s, id) => s + (shares[id] || 0), 0);

  // ─── Bar fractions per mode ───────────────────────────────────────────────
  const fractions = useMemo(() => {
    if (mode === 'equal') {
      return IDS.map(id => ({
        id, pct: excluded.has(id) ? 0 : 100 / Math.max(1, activeEq.length),
        excluded: excluded.has(id),
      }));
    }
    if (mode === 'manual') {
      return IDS.map(id => ({
        id, pct: (manualEffective[id] / TOTAL) * 100,
      }));
    }
    if (mode === 'percent') {
      return IDS.map(id => ({ id, pct: percent[id] || 0 }));
    }
    // shares
    return IDS.map(id => ({
      id, pct: totalShares > 0 ? ((shares[id] || 0) / totalShares) * 100 : 100 / 3,
    }));
  }, [mode, excluded, activeEq.length, manualEffective, percent, shares, totalShares]);

  // ─── Delta chip ───────────────────────────────────────────────────────────
  const showDelta = mode === 'manual' || mode === 'percent';
  let deltaState = 'balanced';
  let deltaText = 'balanced ✓';
  if (mode === 'manual') {
    if (manualDelta > 0) { deltaState = 'over'; deltaText = `₹${fmt(manualDelta)} over`; }
    else                 { deltaState = 'balanced'; deltaText = 'balanced ✓'; }
  } else if (mode === 'percent') {
    if (pctDelta > 0)      { deltaState = 'over';  deltaText = `${pctDelta}% over`; }
    else if (pctDelta < 0) { deltaState = 'under'; deltaText = `${-pctDelta}% remaining`; }
    else                   { deltaState = 'balanced'; deltaText = 'balanced ✓'; }
  }

  // Flash on transition into balanced
  const prevDeltaRef = useRef(deltaState);
  useEffect(() => {
    if (showDelta && prevDeltaRef.current !== 'balanced' && deltaState === 'balanced') {
      setDeltaFlash(true);
      haptic(12);
      const t = setTimeout(() => setDeltaFlash(false), 720);
      return () => clearTimeout(t);
    }
    prevDeltaRef.current = deltaState;
  }, [deltaState, showDelta]);

  // ─── CTA enabled + breathe ────────────────────────────────────────────────
  const canSubmit = useMemo(() => {
    if (mode === 'equal')   return activeEq.length > 0;
    if (mode === 'manual')  return manualDelta === 0;
    if (mode === 'percent') return pctDelta === 0;
    if (mode === 'shares')  return totalShares > 0;
    return false;
  }, [mode, activeEq.length, manualDelta, pctDelta, totalShares]);

  const prevCanRef = useRef(canSubmit);
  useEffect(() => {
    if (!prevCanRef.current && canSubmit) {
      setCtaBreath(true);
      const t = setTimeout(() => setCtaBreath(false), 720);
      return () => clearTimeout(t);
    }
    prevCanRef.current = canSubmit;
  }, [canSubmit]);

  // ─── Toast on disabled tap ────────────────────────────────────────────────
  const onCtaClick = () => {
    if (canSubmit) return; // would navigate; this is a prototype
    let msg;
    if (mode === 'manual') {
      msg = <>still <span className="amt">₹{fmt(manualDelta)}</span> to assign — tap any value to fix</>;
    } else if (mode === 'percent') {
      const sign = pctDelta > 0 ? 'over' : 'remaining';
      msg = <>still <span className="amt">{Math.abs(pctDelta)}%</span> {sign} — tap any value to fix</>;
    } else if (mode === 'equal') {
      msg = <>everyone is excluded — include at least one person</>;
    } else {
      msg = <>add at least one share</>;
    }
    setToast(msg);
    haptic(20);
    clearTimeout(window.__toastT);
    window.__toastT = setTimeout(() => setToast(null), 2400);
  };

  // ─── Handlers ─────────────────────────────────────────────────────────────
  const toggleExclude = (id) => {
    setExcluded(prev => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      haptic(10);
      return next;
    });
  };

  const editManual = (id, val) => {
    // If id is auto, this shifts auto to next-LRU
    setManualOrder(prev => {
      const next = prev.filter(x => x !== id);
      next.push(id);
      return next;
    });
    setManualAmts(prev => ({ ...prev, [id]: val }));
  };
  const focusManual = (id) => {
    // Tapping the auto row shifts elasticity even before typing
    if (manualOrder[0] === id) {
      setManualOrder(prev => {
        const next = prev.filter(x => x !== id);
        next.push(id);
        return next;
      });
    }
  };

  const editPct = (id, val) => {
    // Cap at 100
    const v = Math.min(100, Math.max(0, val));
    setPercent(prev => ({ ...prev, [id]: v }));
  };

  // Bar drag in percent mode: between segment idx and idx+1
  const onBarDrag = useCallback((idx, dPct, startPctL, startPctR) => {
    if (mode !== 'percent') return;
    const leftId  = IDS[idx];
    const rightId = IDS[idx + 1];
    if (!leftId || !rightId) return;
    if (locked.has(leftId) || locked.has(rightId)) return;
    // Clamp so neither goes below 1
    const min = 1;
    const sumPair = startPctL + startPctR;
    let newL = Math.round(startPctL + dPct);
    if (newL < min) newL = min;
    if (newL > sumPair - min) newL = sumPair - min;
    const newR = sumPair - newL;
    setPercent(prev => {
      // Snap-ish to integers; haptic on every 5%
      const oldL = prev[leftId];
      if (newL !== oldL && newL % 5 === 0) haptic(5);
      return { ...prev, [leftId]: newL, [rightId]: newR };
    });
  }, [mode, locked]);

  // Long-press to lock (percent mode)
  const pressTimerRef = useRef();
  const pressFiredRef = useRef(false);
  const onRowPressStart = (id) => {
    if (mode !== 'percent') return;
    pressFiredRef.current = false;
    pressTimerRef.current = setTimeout(() => {
      pressFiredRef.current = true;
      haptic(22);
      setLocked(prev => {
        const next = new Set(prev);
        if (next.has(id)) next.delete(id);
        else next.add(id);
        return next;
      });
    }, 480);
  };
  const onRowPressEnd = () => {
    clearTimeout(pressTimerRef.current);
  };

  // ─── Render right-side pane per mode ──────────────────────────────────────
  const renderPane = (p) => {
    if (mode === 'equal') {
      return (
        <EqualPane
          p={p}
          excluded={excluded.has(p.id)}
          share={equalShare}
          onToggle={() => toggleExclude(p.id)}
        />
      );
    }
    if (mode === 'manual') {
      const isAuto = manualOrder[0] === p.id;
      const value = isAuto ? elasticVal : manualAmts[p.id];
      return (
        <ManualPane
          p={p}
          value={value}
          isAuto={isAuto}
          onChange={(v) => editManual(p.id, v)}
          onFocus={() => focusManual(p.id)}
        />
      );
    }
    if (mode === 'percent') {
      return (
        <PercentPane
          p={p}
          pct={percent[p.id]}
          locked={locked.has(p.id)}
          onChange={(v) => editPct(p.id, v)}
          onFocus={() => {}}
        />
      );
    }
    if (mode === 'shares') {
      return (
        <SharesPane
          p={p}
          shares={shares[p.id]}
          totalShares={totalShares}
          onChange={(v) => setShares(prev => ({ ...prev, [p.id]: v }))}
        />
      );
    }
    return null;
  };

  // ─── Per-row sub-text ─────────────────────────────────────────────────────
  const renderSub = (p) => {
    if (mode === 'percent') {
      const amt = (percent[p.id] || 0) * TOTAL / 100;
      const isLocked = locked.has(p.id);
      return (
        <div className="lr-sub">
          <span>= ₹<span className="tick" key={Math.round(amt)}>{fmt(amt)}</span></span>
          {isLocked && <span className="lock">· 🔒 locked</span>}
        </div>
      );
    }
    if (mode === 'shares') {
      const amt = totalShares > 0 ? (shares[p.id] / totalShares) * TOTAL : 0;
      return (
        <div className="lr-sub">
          <span>= ₹<span className="tick" key={Math.round(amt)}>{fmt(amt)}</span></span>
        </div>
      );
    }
    if (mode === 'manual') {
      const isAuto = manualOrder[0] === p.id;
      return (
        <div className="lr-sub">
          {isAuto ? 'auto-balances the rest' : 'you set this'}
        </div>
      );
    }
    if (mode === 'equal') {
      return <div className="lr-sub">{excluded.has(p.id) ? 'excluded' : 'equal share'}</div>;
    }
    return null;
  };

  // ─── Render ───────────────────────────────────────────────────────────────
  return (
    <window.IOSDevice width={390} height={844}>
      <div className="screen">
        <div className="page">
          {/* top bar */}
          <div className="topbar">
            <button className="tb-icon" aria-label="back">
              <svg viewBox="0 0 12 14" fill="none">
                <path d="M9 1L3 7l6 6" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
              </svg>
            </button>
            <div className="tb-title">split how?</div>
            <button className="tb-icon" aria-label="help">
              <span className="help">?</span>
            </button>
          </div>

          {/* context strip */}
          <div className="context-strip">
            <div className="cs-title">farzi cafe</div>
            <div className="cs-meta">
              <span className="amt">₹4,200</span>
              <span className="dot">·</span>
              <span>with you, aarav, priya</span>
            </div>
          </div>

          {/* segmented control */}
          <Segmented mode={mode} setMode={setMode} />

          {/* bar */}
          <SplitBar
            mode={mode}
            fractions={fractions}
            locked={mode === 'percent' ? locked : new Set()}
            draggable={mode === 'percent'}
            onDrag={onBarDrag}
          />

          {/* rows */}
          <div className="rows-card">
            {PEOPLE.map(p => {
              const isLocked = mode === 'percent' && locked.has(p.id);
              const isExcluded = mode === 'equal' && excluded.has(p.id);
              return (
                <div
                  key={p.id}
                  className={`lrow${isExcluded ? ' excluded' : ''}${isLocked ? ' locked-row' : ''}`}
                  onMouseDown={() => onRowPressStart(p.id)}
                  onMouseUp={onRowPressEnd}
                  onMouseLeave={onRowPressEnd}
                  onTouchStart={() => onRowPressStart(p.id)}
                  onTouchEnd={onRowPressEnd}
                >
                  <div className="lr-avatar"><Avatar p={p} /></div>
                  <div className="lr-mid">
                    <div className="lr-name">{p.name}</div>
                    {renderSub(p)}
                  </div>
                  <div className="lr-right" key={mode /* crossfade */}>
                    {renderPane(p)}
                  </div>
                </div>
              );
            })}
          </div>

          {/* mode-aware footer line */}
          {mode === 'shares' && (
            <div className="mode-footer">
              <span className="tick" key={totalShares}>{totalShares}</span>
              {' '}share{totalShares === 1 ? '' : 's'}
              {' · ₹4,200 total'}
            </div>
          )}
          {mode === 'percent' && locked.size > 0 && (
            <div className="mode-footer">
              <span>{locked.size} locked · long-press to lock or unlock</span>
            </div>
          )}
          {mode === 'percent' && locked.size === 0 && (
            <div className="mode-footer">
              <span>long-press a row to lock</span>
            </div>
          )}
          {mode === 'equal' && excluded.size > 0 && (
            <div className="mode-footer">
              <span className="tick" key={IDS.length - excluded.size}>{IDS.length - excluded.size}</span>
              {' '}included · tap × to include again
            </div>
          )}
          {mode === 'manual' && (
            <div className="mode-footer">
              <span>tap any value to make others auto-adjust</span>
            </div>
          )}

          {/* bottom area: delta + CTA */}
          <div className="bottom">
            <div className={`delta${showDelta ? ' visible' : ''} ${deltaState}${deltaFlash ? ' flash' : ''}`}>
              <span className="tick" key={deltaText}>{deltaText}</span>
            </div>

            <button
              className={`cta-btn${canSubmit ? '' : ' disabled'}${ctaBreath ? ' breathing' : ''}`}
              onClick={onCtaClick}
            >
              add expense
              <span className="check">✓</span>
            </button>

            <div className={`toast${toast ? ' on' : ''}`}>
              {toast}
            </div>
          </div>
        </div>
      </div>
    </window.IOSDevice>
  );
}

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