// Main jet lag calculator app.

const { useState: useStateApp, useEffect: useEffectApp, useMemo: useMemoApp } = React;
const { CITIES, buildPlan, tzOffsetLabel } = window.JL;
const { Flag, haptic } = window.JLFX;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "strictness": "gentle",
  "direction": "preshift",
  "enableCaffeine": true,
  "enableMelatonin": true
}/*EDITMODE-END*/;

function pickCity(name) { return CITIES.find(c => c.name === name); }

function App() {
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // Trip state
  const [origin, setOrigin] = useStateApp(() => pickCity('London'));
  const [dest, setDest]     = useStateApp(() => pickCity('Tokyo'));
  const [departure, setDeparture] = useStateApp(() => {
    const d = new Date(); d.setDate(d.getDate() + 7); d.setHours(10, 0, 0, 0); return d;
  });
  const [arrival, setArrivalState] = useStateApp(() => {
    const d = new Date(); d.setDate(d.getDate() + 8); d.setHours(8, 0, 0, 0); return d;
  });
  const [tripDays, setTripDays] = useStateApp(7);
  // Track the implicit return date (arrival + tripDays). When the user
  // changes arrival, we preserve the return date and let tripDays update
  // naturally, so the plan "auto-extends" or "auto-shrinks".
  const returnDateRef = React.useRef(null);
  if (returnDateRef.current == null) {
    returnDateRef.current = new Date(arrival.getTime() + tripDays * 86400000);
  }
  const setArrival = (newArrival) => {
    const ret = returnDateRef.current;
    const days = Math.max(1, Math.round((ret.getTime() - newArrival.getTime()) / 86400000));
    setArrivalState(newArrival);
    setTripDays(Math.min(60, days));
  };
  // When the user manually sets tripDays, update the return date ref.
  const setTripDaysSynced = (n) => {
    setTripDays(n);
    returnDateRef.current = new Date(arrival.getTime() + n * 86400000);
  };
  const [bedtime, setBedtime]   = useStateApp('23:00');
  const [waketime, setWaketime] = useStateApp('07:00');
  const [chronotype, setChronotype] = useStateApp('neutral');
  const [caffeineCutoff, setCaffeineCutoff] = useStateApp(8);

  // Day selector for timeline
  const [selectedIdx, setSelectedIdx] = useStateApp(0);

  // User-draggable overrides for marker times. When set, takes precedence
  // over the auto-derived schedule. `null` means "auto".
  const [overrides, setOverrides] = useStateApp({
    breakfast: null, lunch: null, dinner: null, melatonin: null,
  });
  const setOverride = (key, hm) => setOverrides(o => ({ ...o, [key]: hm }));

  // Compute the plan (re-runs whenever inputs change)
  const plan = useMemoApp(() => {
    if (!origin || !dest) return null;
    return buildPlan({
      originTz: origin.tz, destTz: dest.tz,
      departureDate: departure, arrivalDate: arrival, tripLengthDays: tripDays,
      usualBedtime: bedtime, usualWaketime: waketime,
      chronotype, caffeineCutoffH: caffeineCutoff,
      strictness: tweaks.strictness, direction: tweaks.direction,
      enableCaffeine: tweaks.enableCaffeine, enableMelatonin: tweaks.enableMelatonin,
      overrides,
    });
  }, [origin, dest, departure, arrival, tripDays, bedtime, waketime, chronotype,
      caffeineCutoff, tweaks.strictness, tweaks.direction, tweaks.enableCaffeine,
      tweaks.enableMelatonin, overrides]);

  // Marker drag handler — called by the dial when user drags a marker.
  // Dispatches to the right state setter (or override) based on event type.
  const onDragMarker = (type, minutes) => {
    const h = Math.floor(minutes / 60), m = minutes % 60;
    const hm = `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;
    if (type === 'wake')     setWaketime(hm);
    else if (type === 'bed') setBedtime(hm);
    else if (type === 'caffeine-cutoff') {
      // caffeineCutoff is hours-before-bed. Compute from new caffeine-end time vs bedtime.
      const bedMin = (() => { const [bh, bm] = bedtime.split(':').map(Number); return bh*60+bm; })();
      let delta = (bedMin - minutes + 1440) % 1440;
      if (delta > 720) delta -= 1440;
      const hoursBefore = Math.max(0, Math.min(12, delta / 60));
      setCaffeineCutoff(Math.round(hoursBefore * 2) / 2);
    } else if (type === 'breakfast' || type === 'lunch' || type === 'dinner') {
      setOverride(type, { h, m });
    } else if (type === 'melatonin') {
      setOverride('melatonin', { h, m });
    }
  };

  // Auto-jump to today's day when plan changes BUT only on first build
  // (i.e. when the plan length or first-date changes). We don't want to
  // override the user's chip selection on minor input changes.
  const planRangeKey = plan
    ? `${plan.days[0]?.date.getTime()}-${plan.days.length}`
    : '';
  useEffectApp(() => {
    if (!plan) return;
    const now = Date.now();
    for (let i = 0; i < plan.days.length; i++) {
      const d = plan.days[i].date.getTime();
      if (now >= d && now < d + 86400000) { setSelectedIdx(i); return; }
    }
    setSelectedIdx(0);
  }, [planRangeKey]);

  return (
    <React.Fragment>
      <div style={{
        width: '100%', minHeight: '100vh',
        background: '#08070d', color: '#fafafa',
        fontFamily: '"Inter", "Helvetica Neue", system-ui, sans-serif',
        position: 'relative', overflow: 'hidden',
      }}>
        {/* Ambient cinematic glow */}
        <div style={{
          position: 'fixed', inset: 0, pointerEvents: 'none', opacity: 0.5,
          background: `radial-gradient(60% 50% at 15% 15%, #9b59b644, transparent 70%),
                       radial-gradient(60% 50% at 85% 85%, #ff7e5f44, transparent 70%),
                       radial-gradient(80% 50% at 50% 50%, #1e3c7222, transparent 70%)`,
        }} />

        {/* Twinkling background stars */}
        <BgStars />

        {/* Header */}
        <div className="jl-boot" style={{ padding: '32px 28px 12px', position: 'relative', zIndex: 2 }}>
          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', flexWrap: 'wrap', gap: 12 }}>
            <div>
              <div style={{ fontSize: 11, letterSpacing: '0.4em', color: 'rgba(255,255,255,0.55)',
                textTransform: 'uppercase', fontWeight: 700 }}>
                Jet Lag Coach
              </div>
              <div style={{ fontSize: 28, fontWeight: 200, letterSpacing: '-0.5px', marginTop: 4,
                color: '#fafafa' }}>
                Sync your body before, during, after.
              </div>
            </div>
            {origin && dest && (
              <div style={{ display: 'flex', alignItems: 'center', gap: 10,
                fontSize: 12, letterSpacing: '0.2em', color: 'rgba(255,255,255,0.55)',
                textTransform: 'uppercase' }}>
                <Flag code={origin.code} size={18} /> {origin.name}
                <span style={{ opacity: 0.5 }}>→</span>
                <Flag code={dest.code} size={18} /> {dest.name}
              </div>
            )}
          </div>
        </div>

        {/* Inputs panel */}
        <TripInputs
          origin={origin} setOrigin={setOrigin}
          dest={dest} setDest={setDest}
          departure={departure} setDeparture={setDeparture}
          arrival={arrival} setArrival={setArrival}
          tripDays={tripDays} setTripDays={setTripDaysSynced}
          bedtime={bedtime} setBedtime={setBedtime}
          waketime={waketime} setWaketime={setWaketime}
          chronotype={chronotype} setChronotype={setChronotype}
          caffeineCutoff={caffeineCutoff} setCaffeineCutoff={setCaffeineCutoff}
        />

        {/* Main grid: clock + right rail */}
        <div style={{
          display: 'grid',
          gridTemplateColumns: 'minmax(0, 1.4fr) minmax(280px, 1fr)',
          gap: 24, padding: '8px 28px 20px', position: 'relative', zIndex: 2,
        }} className="jl-grid">
          <div className="jl-pop jl-glass" style={{
            padding: '24px',
            borderRadius: 22, minWidth: 0,
          }}>
            <DualClock plan={plan} selectedIdx={selectedIdx} onDragMarker={onDragMarker} />
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14, minWidth: 0 }} className="jl-stagger">
            <div className="jl-glass" style={{ padding: 16, borderRadius: 16 }}>
              <SeverityScore plan={plan} />
            </div>
            <div className="jl-glass" style={{ padding: 16, borderRadius: 16 }}>
              <Recommendation plan={plan} selectedIdx={selectedIdx} />
            </div>
            <div className="jl-glass" style={{ padding: 16, borderRadius: 16 }}>
              <ClaudeAdvice plan={plan} chronotype={chronotype} />
            </div>
          </div>
        </div>

        {/* Day-by-day timeline */}
        <div style={{ padding: '8px 0 40px', position: 'relative', zIndex: 2 }}>
          <Timeline plan={plan} selectedIdx={selectedIdx} onSelect={(i) => { haptic(10); setSelectedIdx(i); }} />
        </div>
      </div>

      {/* Responsive: single-column on narrow */}
      <style>{`
        @media (max-width: 880px) {
          .jl-grid { grid-template-columns: 1fr !important; }
        }
      `}</style>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Schedule">
          <TweakRadio label="Strictness" value={tweaks.strictness}
            options={[{ value: 'gentle', label: 'Gentle' }, { value: 'strict', label: 'Strict' }]}
            onChange={(v) => setTweak('strictness', v)} />
          <TweakRadio label="Adjust" value={tweaks.direction}
            options={[{ value: 'preshift', label: 'Pre-shift' }, { value: 'arrival', label: 'On arrival' }]}
            onChange={(v) => setTweak('direction', v)} />
        </TweakSection>
        <TweakSection label="Guidance">
          <TweakToggle label="Caffeine guidance" value={tweaks.enableCaffeine}
            onChange={(v) => setTweak('enableCaffeine', v)} />
          <TweakToggle label="Melatonin guidance" value={tweaks.enableMelatonin}
            onChange={(v) => setTweak('enableMelatonin', v)} />
        </TweakSection>
      </TweaksPanel>
    </React.Fragment>
  );
}

// Sparkle background stars — fixed positions, twinkling. Bigger than the
// crescent in TZ Calc — these are decorative ambient stars in the page bg.
const BG_STARS = [];
{
  for (let i = 0; i < 35; i++) {
    const a = ((Math.sin(i * 12.9898) * 43758.5453) % 1 + 1) % 1;
    const b = ((Math.sin(i * 78.233)  * 43758.5453) % 1 + 1) % 1;
    const c = ((Math.sin(i * 56.123)  * 43758.5453) % 1 + 1) % 1;
    BG_STARS.push({ x: a * 100, y: b * 60, r: 0.4 + c * 0.7, delay: c * 4 });
  }
}
function BgStars() {
  return (
    <svg viewBox="0 0 100 60" preserveAspectRatio="xMidYMin slice"
      style={{ position: 'fixed', inset: 0, width: '100%', height: '100%',
        pointerEvents: 'none', opacity: 0.55, zIndex: 1 }}>
      {BG_STARS.map((s, i) => (
        <circle key={i} cx={s.x} cy={s.y} r={s.r * 0.18} fill="#fff"
          style={{
            animation: `jlTwink ${3 + (i % 4) * 0.5}s ease-in-out infinite`,
            animationDelay: `${s.delay}s`,
            transformOrigin: `${s.x}px ${s.y}px`,
          }} />
      ))}
    </svg>
  );
}

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