// app.jsx — root Desk-Dash Editorial dashboard.

const TWEAKS_DEFAULTS = /*EDITMODE-BEGIN*/{
  "planePosition": "top",
  "mastheadTitle": "The Daily Desk",
  "showTickerWhenEmpty": true,
  "demoFlipOpen": false,
  "paperWarmth": 82
}/*EDITMODE-END*/;

// Refresh rates (ms)
const REFRESH = {
  weather: 10 * 60 * 1000,
  crcl:     5 * 60 * 1000,
  usdc:    15 * 60 * 1000,
  flight:       30 * 1000,
};

function useLiveData(fetcher, intervalMs) {
  const [data, setData] = React.useState(null);
  React.useEffect(() => {
    let alive = true;
    const tick = async () => {
      const r = await fetcher();
      if (alive) setData(r);
    };
    tick();
    const id = setInterval(tick, intervalMs);
    return () => { alive = false; clearInterval(id); };
  }, []);
  return data;
}

function Masthead({ title }) {
  const now = useClock();
  const dateStr = now.toLocaleDateString('en-US', {
    weekday: 'short', month: 'short', day: 'numeric', year: 'numeric',
    timeZone: 'America/New_York',
  }).toUpperCase();
  const vol = 'XVII';
  return (
    <div className="dd-masthead">
      <div className="dd-mast-title">{title}</div>
      <div className="dd-mast-meta">
        {dateStr}  ·  QUINCY MA
      </div>
    </div>
  );
}

function Ticker({ flight, showWhenEmpty }) {
  if (!flight || !flight.flight) {
    if (!showWhenEmpty) return <div className="dd-ticker"/>;
    return (
      <div className="dd-ticker">
        <div className="dd-ticker-empty">— quiet skies overhead —</div>
      </div>
    );
  }
  const p = Math.max(0.04, Math.min(0.96, flight.progress));
  const pctLeft = `${p * 100}%`;
  return (
    <div className="dd-ticker">
      <span className="dd-ticker-endpoint">{airportLabel(flight.from)}</span>
      <div className="dd-ticker-track">
        <div className="dd-ticker-line"/>
        <div className="dd-ticker-plane" style={{ left: pctLeft, transform: 'translateX(-50%)' }}>
          <svg width="16" height="16" viewBox="0 0 24 24" style={{ overflow: 'visible' }}>
            <path d="M20.5 12 L 12.8 13.6 L 8 20 L 6.5 19.6 L 8.8 13.8 L 4 14.6 L 3 13.8 L 3 12 L 4 11.2 L 8.8 12 L 6.5 6.2 L 8 5.8 L 12.8 12.2 L 20.5 13.8 C 21.2 13.8 21.8 13 21.8 12.9 C 21.8 12.8 21.2 12 20.5 12 Z"
              fill="var(--ink)" stroke="var(--ink)" strokeWidth="0.4" strokeLinejoin="round"/>
          </svg>
        </div>
      </div>
      <span className="dd-ticker-endpoint">{airportLabel(flight.to)}</span>
      <span className="dd-ticker-meta">· {flight.flight} · {(flight.alt / 1000).toFixed(0)}k ft</span>
    </div>
  );
}

// Scale canvas to fit the viewport (letterboxed)
function useCanvasScale() {
  const [scale, setScale] = React.useState(1);
  React.useEffect(() => {
    const recompute = () => {
      // Mobile: skip scaling; CSS media query takes over the layout.
      if (window.innerWidth <= 700) { setScale(1); return; }
      const sx = window.innerWidth / 800;
      const sy = window.innerHeight / 480;
      setScale(Math.min(sx, sy));
    };
    recompute();
    window.addEventListener('resize', recompute);
    return () => window.removeEventListener('resize', recompute);
  }, []);
  return scale;
}

function App() {
  const [tweaks, setTweaks] = React.useState(TWEAKS_DEFAULTS);
  const [tweakOpen, setTweakOpen] = React.useState(false);

  // Tweaks protocol
  React.useEffect(() => {
    const onMsg = (e) => {
      if (e.data?.type === '__activate_edit_mode') setTweakOpen(true);
      if (e.data?.type === '__deactivate_edit_mode') setTweakOpen(false);
    };
    window.addEventListener('message', onMsg);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', onMsg);
  }, []);
  const update = (edits) => {
    setTweaks(t => ({ ...t, ...edits }));
    window.parent.postMessage({ type: '__edit_mode_set_keys', edits }, '*');
  };

  // Live data
  const weather = useLiveData(fetchWeather, REFRESH.weather);
  const crcl    = useLiveData(fetchCrcl, REFRESH.crcl);
  const usdc    = useLiveData(fetchUsdc, REFRESH.usdc);
  const flight  = useLiveData(fetchFlight, REFRESH.flight);

  // Clock cycle state (persist)
  const [clockVariant, setClockVariant] = React.useState(() => {
    return localStorage.getItem('dd.clockVariant') || 'digital';
  });
  const cycleClock = () => {
    const idx = CLOCK_VARIANTS.indexOf(clockVariant);
    const next = CLOCK_VARIANTS[(idx + 1) % CLOCK_VARIANTS.length];
    setClockVariant(next);
    localStorage.setItem('dd.clockVariant', next);
  };

  // Flip states
  const [flipped, setFlipped] = React.useState({ weather: false, crcl: false, usdc: false });
  const toggleFlip = (k) => setFlipped(f => ({ ...f, [k]: !f[k] }));

  // Demo tweak: open all backs
  React.useEffect(() => {
    if (tweaks.demoFlipOpen) setFlipped({ weather: true, crcl: true, usdc: true });
  }, [tweaks.demoFlipOpen]);

  const scale = useCanvasScale();

  return (
    <div className="dd-stage">
      <div className="dd-canvas" style={{ transform: `scale(${scale})` }}>
        <Masthead title={tweaks.mastheadTitle}/>
        {tweaks.planePosition === 'top' && (
          <Ticker flight={flight} showWhenEmpty={tweaks.showTickerWhenEmpty}/>
        )}
        <div className="dd-grid">
          <ClockCard variant={clockVariant} onTap={cycleClock}/>
          <WeatherCard data={weather} flipped={flipped.weather} onTap={() => toggleFlip('weather')}/>
          <CrclCard    data={crcl}    flipped={flipped.crcl}    onTap={() => toggleFlip('crcl')}/>
          <UsdcCard    data={usdc}    flipped={flipped.usdc}    onTap={() => toggleFlip('usdc')}/>
        </div>
        {tweaks.planePosition === 'bottom' && (
          <Ticker flight={flight} showWhenEmpty={tweaks.showTickerWhenEmpty}/>
        )}
      </div>

      {tweakOpen && (
        <div className="dd-tweaks">
          <h3>Tweaks</h3>
          <div className="group">
            <div className="label">Masthead title</div>
            <input
              value={tweaks.mastheadTitle}
              onChange={e => update({ mastheadTitle: e.target.value })}
              style={{
                width: '100%', background: 'rgba(255,255,255,0.08)', border: 'none',
                color: 'inherit', padding: '6px 8px', borderRadius: 5, fontSize: 11,
                fontFamily: 'var(--serif)', fontStyle: 'italic',
              }}/>
          </div>
          <div className="group">
            <div className="label">Plane ticker</div>
            <div className="row">
              {['top', 'bottom'].map(p => (
                <button key={p}
                  className={tweaks.planePosition === p ? 'active' : ''}
                  onClick={() => update({ planePosition: p })}>{p}</button>
              ))}
            </div>
          </div>
          <div className="group">
            <label className="check">
              <input type="checkbox" checked={tweaks.showTickerWhenEmpty}
                onChange={e => update({ showTickerWhenEmpty: e.target.checked })}/>
              Show ticker when no flight overhead
            </label>
          </div>
          <div className="group">
            <label className="check">
              <input type="checkbox" checked={tweaks.demoFlipOpen}
                onChange={e => {
                  update({ demoFlipOpen: e.target.checked });
                  if (!e.target.checked) setFlipped({ weather: false, crcl: false, usdc: false });
                }}/>
              Demo: show all card back-sides
            </label>
          </div>
          <div className="group" style={{ fontSize: 10, opacity: 0.6, lineHeight: 1.5, marginTop: 10 }}>
            Preview uses realistic mock data. Deploy wires to real APIs via /api/* worker.
            See <code style={{ background: 'rgba(255,255,255,0.1)', padding: '1px 5px', borderRadius: 3 }}>DEPLOY.md</code>.
          </div>
        </div>
      )}
    </div>
  );
}

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