/* global React, AuroraMark, CDial, COrb, CHoldButton, CSeg, CGlass, AURORA_TOKENS */
// UNIFIED — a single, fully-navigable Aurora phone.
//   Footer tabs route (Wake · Memory · Me). Rows open detail screens.
//   Any list with 3+ options is a tap-to-open bottom sheet, not a tap-to-cycle.

const { useState, useEffect, useRef, useContext } = React;
const U = AURORA_TOKENS;
const { C_BG, C_FIRE, C_MORN, C_CORAL, C_INDIGO, C_GREEN, C_GOLD, C_TEXT, C_DIM, C_MUTED, C_CARD } = U;

// Bottom-sheet opener is provided by the shell via context.
const SheetCtx = React.createContext(() => {});

// ─── screen wrapper (clears status bar / notch) ───
const UScreen = ({ bg, color, children, padBottom = 92 }) => (
  <div style={{
    width: '100%', height: '100%', background: bg, color: color || C_TEXT,
    fontFamily: 'Inter Tight, system-ui, sans-serif',
    display: 'flex', flexDirection: 'column', overflow: 'hidden',
    paddingTop: 54, paddingBottom: padBottom, position: 'relative',
  }}>{children}</div>
);

const chevR = (c = C_DIM) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M9 6l6 6-6 6" stroke={c} strokeWidth="2" strokeLinecap="round"/></svg>;
const fmt = (t) => `${String(t.h).padStart(2,'0')}:${String(t.m).padStart(2,'0')}`;
const sleepGoal = (bed, alarm) => {
  let mins = (alarm.h*60 + alarm.m) - (bed.h*60 + bed.m);
  if (mins <= 0) mins += 24*60;
  return `${Math.floor(mins/60)} h ${mins%60} m`;
};

// ─── interactive footer tab bar ───
const UTabBar = ({ active, onChange, tone = 'dark' }) => {
  // Warm (apricot) screens: NO background band at all — the gradient must flow
  // uninterrupted to the very bottom, exactly like Plan day. A darkening scrim here
  // collided with the gradient (lightest at the bottom) and produced a luminance
  // ridge that read as a hard cut. Legibility comes from drop-shadows on the glyphs.
  const warm = tone === 'warm';
  const inactive = warm ? 'rgba(60,30,18,0.62)' : 'rgba(255,255,255,0.4)';
  // On the warm Memory footer the coral active state is hard to read against the
  // apricot grade — use white for the active tab there instead.
  const activeColor = warm ? '#fff' : C_CORAL;
  const glyphShadow = warm ? 'drop-shadow(0 1px 2px rgba(40,20,10,0.35))' : 'none';
  const labelShadow = warm ? '0 1px 2px rgba(40,20,10,0.35)' : 'none';
  const tabs = [
    { id: 'wake', label: 'Wake', icon: (c) => (
      <svg width="22" height="22" viewBox="0 0 64 64" fill="none"><path d="M12 40 A20 20 0 0 1 52 40" stroke={c} strokeWidth="4" strokeLinecap="round" fill="none"/><line x1="6" y1="40" x2="58" y2="40" stroke={c} strokeWidth="4" strokeLinecap="round"/></svg>
    )},
    { id: 'memory', label: 'Memory', icon: (c) => (
      <svg width="22" height="22" viewBox="0 0 24 24" fill="none"><path d="M6 4h10l4 4v12a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z" stroke={c} strokeWidth="2"/><line x1="8" y1="10" x2="16" y2="10" stroke={c} strokeWidth="2" strokeLinecap="round"/><line x1="8" y1="14" x2="14" y2="14" stroke={c} strokeWidth="2" strokeLinecap="round"/></svg>
    )},
    { id: 'me', label: 'Me', icon: (c) => (
      <svg width="22" height="22" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="9" r="3.5" stroke={c} strokeWidth="2"/><path d="M5 20c0-3.5 3.5-6 7-6s7 2.5 7 6" stroke={c} strokeWidth="2" strokeLinecap="round"/></svg>
    )},
  ];
  return (
    <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: 90, borderTop: 'none', background: warm ? 'transparent' : 'linear-gradient(to top, #0d0f1f 0%, #0d0f1f 38%, rgba(13,15,31,0.82) 62%, rgba(13,15,31,0) 100%)', backdropFilter: warm ? 'none' : 'blur(8px)', display: 'flex', alignItems: 'flex-end', justifyContent: 'space-around', paddingBottom: 14 }}>
      {tabs.map(t => {
        const on = t.id === active;
        const c = on ? activeColor : inactive;
        return (
          <button key={t.id} onClick={() => onChange(t.id)} style={{ background: 'none', border: 'none', cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3, padding: '4px 18px', fontFamily: 'inherit' }}>
            <span style={{ filter: glyphShadow, display: 'grid' }}>{t.icon(c)}</span>
            <span style={{ fontSize: 10, color: c, letterSpacing: '0.02em', fontWeight: on ? 600 : 400, textShadow: labelShadow }}>{t.label}</span>
          </button>
        );
      })}
    </div>
  );
};

// ─── generic row (tap → onClick); supports toggle + value + chevron ───
const URow = ({ icon, label, value, onClick, chevron, toggle, on, sub }) => {
  const [pressed, setPressed] = useState(false);
  const clickable = !!onClick || toggle;
  return (
    <div
      onClick={onClick}
      onMouseDown={() => clickable && setPressed(true)} onMouseUp={() => setPressed(false)} onMouseLeave={() => setPressed(false)}
      onTouchStart={() => clickable && setPressed(true)} onTouchEnd={() => setPressed(false)}
      style={{ background: pressed ? 'rgba(255,255,255,0.09)' : C_CARD, borderRadius: 14, padding: '13px 16px', display: 'flex', alignItems: 'center', gap: 12, border: '1px solid rgba(255,255,255,0.05)', cursor: clickable ? 'pointer' : 'default', transition: 'background 0.12s, transform 0.08s', transform: pressed ? 'scale(0.985)' : 'scale(1)', userSelect: 'none' }}>
      {icon}
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 15 }}>{label}</div>
        {sub && <div style={{ fontSize: 12, opacity: 0.5, marginTop: 2 }}>{sub}</div>}
      </div>
      {value != null && <span style={{ fontSize: 14, opacity: 0.6, whiteSpace: 'nowrap' }}>{value}</span>}
      {chevron && chevR()}
      {toggle && (
        <div style={{ width: 38, height: 22, borderRadius: 12, background: on ? C_CORAL : 'rgba(255,255,255,0.15)', position: 'relative', transition: 'background 0.2s', flex: '0 0 auto' }}>
          <div style={{ position: 'absolute', top: 2, left: on ? 18 : 2, width: 18, height: 18, borderRadius: '50%', background: '#fff', transition: 'left 0.2s cubic-bezier(0.4,0,0.2,1)' }}/>
        </div>
      )}
    </div>
  );
};

// ─── dropdown row → opens a bottom sheet of options ───
const UDropdownRow = ({ icon, label, value, options, onChange }) => {
  const openSheet = useContext(SheetCtx);
  return <URow icon={icon} label={label} value={value} chevron onClick={() => openSheet({ title: label, options, value, onChange })}/>;
};

// ─── time scroller — original 3-number visual with drag-to-spin interaction ───
// DEV NOTE FOR IMPLEMENTATION: The final native build should use a drum-roller /
// slot-machine picker (iOS UIPickerView / Android NumberPicker). Numbers scroll
// continuously as the user swipes, with momentum and snap-to-value. Interaction
// contract: swipe UP → value increases, swipe DOWN → value decreases. The tap
// targets above/below the current value remain as a secondary affordance.
function ScrollCol({ value, count, onChange, format }) {
  const STEP_PX = 34;  // pixels of drag to advance one step
  const dragRef = useRef(null);
  const valueRef = useRef(value);
  const onChangeRef = useRef(onChange);
  const [isDragging, setIsDragging] = useState(false);

  useEffect(() => { valueRef.current = value; }, [value]);
  useEffect(() => { onChangeRef.current = onChange; }, [onChange]);

  useEffect(() => {
    if (!isDragging) return;
    const onMove = (e) => {
      if (!dragRef.current) return;
      const y = e.touches ? e.touches[0].clientY : e.clientY;
      const { startY, startValue } = dragRef.current;
      const dy = startY - y;  // positive = dragged up = value increases
      const steps = Math.round(dy / STEP_PX);
      const newVal = ((startValue + steps) % count + count) % count;
      if (newVal !== valueRef.current) onChangeRef.current(newVal);
    };
    const onUp = () => { dragRef.current = null; setIsDragging(false); };
    window.addEventListener('pointermove', onMove);
    window.addEventListener('pointerup', onUp);
    return () => {
      window.removeEventListener('pointermove', onMove);
      window.removeEventListener('pointerup', onUp);
    };
  }, [isDragging, count]);

  const prev = format(((value - 1) % count + count) % count);
  const curr = format(value);
  const next = format(((value + 1) % count + count) % count);

  return (
    <div
      style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4, touchAction: 'none', userSelect: 'none', cursor: isDragging ? 'ns-resize' : 'default' }}
      onPointerDown={(e) => { e.preventDefault(); dragRef.current = { startY: e.clientY, startValue: value }; setIsDragging(true); }}
    >
      <span onClick={() => onChange(((value - 1) % count + count) % count)}
        style={{ fontSize: 28, opacity: 0.25, cursor: 'pointer', userSelect: 'none', padding: '2px 8px', fontVariantNumeric: 'tabular-nums' }}>{prev}</span>
      <div style={{ background: 'rgba(255,255,255,0.08)', borderRadius: 14, padding: '4px 16px' }}>
        <span style={{ fontSize: 56, fontWeight: 600, letterSpacing: '-0.04em', fontVariantNumeric: 'tabular-nums' }}>{curr}</span>
      </div>
      <span onClick={() => onChange((value + 1) % count)}
        style={{ fontSize: 28, opacity: 0.25, cursor: 'pointer', userSelect: 'none', padding: '2px 8px', fontVariantNumeric: 'tabular-nums' }}>{next}</span>
    </div>
  );
}

const UTimeScroller = ({ hour, min, setHour, setMin }) => (
  <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', gap: 8, padding: '18px 0 6px', fontVariantNumeric: 'tabular-nums' }}>
    <ScrollCol value={hour} count={24} onChange={setHour} format={(v) => String(v).padStart(2, '0')}/>
    <span style={{ fontSize: 46, fontWeight: 500, opacity: 0.4, padding: '0 4px' }}>:</span>
    <ScrollCol value={min} count={60} onChange={setMin} format={(v) => String(v).padStart(2, '0')}/>
  </div>
);

// ─── edit-screen header: back + Bedtime/Alarm tabs that actually switch ───
const UEditHeader = ({ active, onBack, onSwitch }) => (
  <div style={{ padding: '10px 24px 6px', display: 'flex', alignItems: 'center' }}>
    <button onClick={onBack} style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 0, display: 'grid', placeItems: 'center' }}>
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M15 5l-7 7 7 7" stroke={C_TEXT} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
    </button>
    <div style={{ flex: 1, display: 'flex', justifyContent: 'center', gap: 34 }}>
      {['Bedtime','Alarm'].map(t => {
        const on = t === active;
        return (
          <button key={t} onClick={() => onSwitch(t.toLowerCase())} style={{ position: 'relative', background: 'none', border: 'none', cursor: 'pointer', fontFamily: 'inherit', color: C_TEXT, fontSize: 18, fontWeight: on ? 600 : 500, opacity: on ? 1 : 0.45, padding: '2px 0' }}>
            {t}
            {on && <div style={{ position: 'absolute', bottom: -7, left: '50%', transform: 'translateX(-50%)', width: 30, height: 3, background: C_CORAL, borderRadius: 2 }}/>}
          </button>
        );
      })}
    </div>
    <span style={{ width: 24 }}/>
  </div>
);

const USleepGoal = ({ bed, alarm }) => (
  <div style={{ textAlign: 'center', fontSize: 13, opacity: 0.6, padding: '6px 0 12px', lineHeight: 1.5 }}>
    Your sleep goal is <span style={{ color: C_GOLD, fontWeight: 600 }}>{sleepGoal(bed, alarm)}</span><br/>
    <span style={{ fontSize: 12, opacity: 0.85 }}>Based on your bedtime and alarm time</span>
  </div>
);

// ─── Shared bottom-sheet host: provides openSheet via context + renders the overlay.
//     Wrap a phone's screen(s) in this (inside IOSDevice). Used by BOTH the Unified
//     router and each Combined-canvas frame, so dropdowns work identically everywhere.
const SheetHost = ({ children }) => {
  const [sheet, setSheet] = useState(null); // { title, options, value, onChange }
  return (
    <SheetCtx.Provider value={(cfg) => setSheet(cfg)}>
      <div style={{ position: 'relative', width: '100%', height: '100%' }}>
        {children}
        {sheet && (
          <div style={{ position: 'absolute', inset: 0, zIndex: 200 }}>
            <div onClick={() => setSheet(null)} style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.5)', animation: 'sheetScrim 0.2s ease' }}/>
            <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, background: 'rgba(26,23,32,0.98)', backdropFilter: 'blur(24px)', borderTopLeftRadius: 26, borderTopRightRadius: 26, border: '1px solid rgba(255,255,255,0.1)', borderBottom: 'none', padding: '10px 12px 30px', maxHeight: '72%', overflowY: 'auto', animation: 'sheetUp 0.26s cubic-bezier(0.2,0.9,0.3,1)' }}>
              <div style={{ width: 38, height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.25)', margin: '4px auto 12px' }}/>
              <div style={{ fontSize: 12, letterSpacing: '0.14em', color: 'rgba(232,230,240,0.5)', fontWeight: 600, padding: '0 10px 10px', textTransform: 'uppercase' }}>{sheet.title}</div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                {sheet.options.map(opt => {
                  const on = opt === sheet.value;
                  return (
                    <button key={opt} onClick={() => { sheet.onChange(opt); setSheet(null); }} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '14px 14px', borderRadius: 12, border: 'none', cursor: 'pointer', fontFamily: 'inherit', textAlign: 'left', background: on ? 'rgba(255,122,89,0.16)' : 'transparent', color: C_TEXT, fontSize: 16 }}>
                      <span style={{ flex: 1, fontWeight: on ? 600 : 400 }}>{opt}</span>
                      {on && <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M5 13l4 4L19 7" stroke={C_CORAL} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/></svg>}
                    </button>
                  );
                })}
              </div>
            </div>
          </div>
        )}
      </div>
    </SheetCtx.Provider>
  );
};

Object.assign(window, {
  SheetCtx, SheetHost, UScreen, UTabBar, URow, UDropdownRow, UTimeScroller, UEditHeader, USleepGoal,
  chevR, fmt, sleepGoal,
  U_TOK: U,
});
