// App.jsx — main React app
const { useState, useEffect, useMemo, useRef, useCallback } = React;

const TABS = [
  { id: 'turnout', label: 'Turnout' },
  { id: 'results', label: 'Results' },
  { id: 'history', label: 'Historical' },
  { id: 'data', label: 'Data' },
];

function App() {
  const [tab, setTab] = useState('turnout');
  const [store, setStore] = useState(() => loadStore());
  const [now, setNow] = useState(new Date());     // minute-level clock for math
  const [tick, setTick] = useState(Date.now());   // second-level clock for the countdown
  const [toast, setToast] = useState(null);
  const [activePrecinct, setActivePrecinct] = useState(null);
  const [bulkOpen, setBulkOpen] = useState(false);

  // Tweaks
  const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
    "darkMode": false,
    "baseline": "2022",
    "winThreshold": 35,
    "heatmapMode": "vsBaseline",
    "lowFlagPct": -15,
    "highFlagPct": 15,
    "showCandidates": ["lowery","burgess","collins","feagins","kuhn","qualls","smiley"]
  }/*EDITMODE-END*/;
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // Theme
  useEffect(() => {
    document.body.dataset.theme = t.darkMode ? 'dark' : 'light';
  }, [t.darkMode]);

  // Two clocks: a 30s `now` for math (recomputes shares, projections, etc.)
  // and a 1s `tick` for the polls countdown only. Avoids re-running the
  // 142-precinct row memo every second.
  useEffect(() => {
    const id = setInterval(() => setTick(Date.now()), 1000);
    return () => clearInterval(id);
  }, []);
  useEffect(() => {
    const id = setInterval(() => setNow(new Date()), 30000);
    return () => clearInterval(id);
  }, []);

  // Persist store
  useEffect(() => { saveStore(store); }, [store]);

  // Toast — uses an incrementing id so the cleanup timer only clears the
  // toast it created, even when multiple flashes fire in quick succession.
  const toastIdRef = useRef(0);
  const flash = (msg, action) => {
    const id = ++toastIdRef.current;
    const value = { id, message: msg, action: action || null };
    setToast(value);
    setTimeout(() => setToast(t => t && t.id === id ? null : t), action ? 6000 : 2200);
  };

  const updateStore = (fn) => setStore(prev => fn({...prev}));

  const precincts = window.PRECINCTS_2026;
  const baseline = t.baseline === '2023' ? window.TURNOUT_2023 : window.TURNOUT_2022;
  const baselineTotals = t.baseline === '2023' ? window.TURNOUT_TOTALS_2023 : window.TURNOUT_TOTALS_2022;

  const agg = useMemo(() => aggregateTurnout(store, precincts), [store, precincts]);

  // Pace projection
  const pace = useMemo(() => {
    const share = shareAt(now);
    if (share <= 0.02) return null;
    return Math.round(agg.total / share);
  }, [now, agg.total]);

  return (
    <div className="app">
      <header className="appbar">
        <ClientChip />
        <div className="appbar-titleblock">
          <div className="appbar-title">Election Day Tracker</div>
          <div className="appbar-sub">Shelby County Mayor · May 5, 2026</div>
        </div>
        <div className="appbar-spacer"></div>
        <PollsCountdown tick={tick} />
      </header>
      {tick >= POLLS_CLOSE.getTime() && (
        <div className="closed-banner" role="status">
          <strong>Polls closed at 7:00 PM CT.</strong>
          <span> Counts entered after close are unofficial.</span>
        </div>
      )}

      <nav className="tabs" role="tablist">
        {TABS.map(x => (
          <button key={x.id} className={'tab' + (tab === x.id ? ' active' : '')} onClick={() => setTab(x.id)}>
            {x.label}
            {x.id === 'turnout' && <span className="tab-count">{agg.reported}/{precincts.length}</span>}
            {x.id === 'results' && <span className="tab-count">{Object.keys(store.results).length}/{precincts.length}</span>}
          </button>
        ))}
      </nav>

      <main className="page">
        {tab === 'turnout' && (
          <TurnoutPage
            store={store}
            updateStore={updateStore}
            precincts={precincts}
            baseline={baseline}
            baselineKey={t.baseline}
            baselineTotals={baselineTotals}
            tweaks={t}
            setTweak={setTweak}
            agg={agg}
            pace={pace}
            now={now}
            pollsClosed={tick >= POLLS_CLOSE.getTime()}
            beforePolls={tick < POLLS_OPEN.getTime()}
            onPrecinctClick={setActivePrecinct}
            onBulkOpen={() => setBulkOpen(true)}
            flash={flash}
          />
        )}
        {tab === 'results' && (
          <ResultsPage
            store={store}
            updateStore={updateStore}
            precincts={precincts}
            tweaks={t}
            onPrecinctClick={setActivePrecinct}
            flash={flash}
          />
        )}
        {tab === 'history' && (
          <HistoryPage precincts={precincts} />
        )}
        {tab === 'data' && (
          <DataPage store={store} setStore={setStore} flash={flash} />
        )}
      </main>

      <footer className="brand-bar">
        <div className="navy-bar"></div>
        <div className="teal-bar"></div>
        <div className="credit">VoteShift Strategies · War Room</div>
      </footer>

      {activePrecinct && (
        <PrecinctModal
          precinct={activePrecinct}
          store={store}
          updateStore={updateStore}
          baseline={baseline}
          baselineKey={t.baseline}
          tweaks={t}
          onClose={() => setActivePrecinct(null)}
          flash={flash}
        />
      )}

      {bulkOpen && (
        <BulkEntryModal
          precincts={precincts}
          store={store}
          updateStore={updateStore}
          onClose={() => setBulkOpen(false)}
          flash={flash}
        />
      )}

      <TweaksUI tweaks={t} setTweak={setTweak} />

      {toast && (
        <div
          className={'toast ' + (toast.action ? 'has-action' : '')}
          onClick={() => {
            if (toast.action) toast.action();
            setToast(null);
          }}
        >
          {toast.message}
        </div>
      )}
    </div>
  );
}

function ClientChip() {
  return (
    <div className="client-chip" title="Lowery for 901 — Shelby County Mayor">
      <img src="assets/lowery-logo.png" alt="Lowery for 901 — Shelby County Mayor" />
    </div>
  );
}

// Polls close 7:00 PM Central on May 5, 2026 (== 00:00 UTC May 6).
// Polls open  7:00 AM Central on May 5, 2026 (== 12:00 UTC May 5).
const POLLS_CLOSE = new Date('2026-05-06T00:00:00Z');
const POLLS_OPEN  = new Date('2026-05-05T12:00:00Z');

function PollsCountdown({ tick }) {
  const ms = POLLS_CLOSE.getTime() - tick;
  const closed = ms <= 0;
  const beforeOpen = tick < POLLS_OPEN.getTime();

  if (closed) {
    return (
      <div className="polls-state polls-closed">
        <div className="polls-flag">
          <span className="dot"></span>
          <span>Polls Closed</span>
        </div>
        <div className="polls-sub">Counting underway · 7:00 PM CT</div>
      </div>
    );
  }

  if (beforeOpen) {
    const t = fmtClock(POLLS_OPEN.getTime() - tick);
    return (
      <div className="polls-state polls-pre">
        <div className="polls-flag pre-open">
          <span className="dot"></span>
          <span>Polls Open at 7 AM</span>
        </div>
        <div className="polls-sub">{t} until polls open</div>
      </div>
    );
  }

  const total = Math.floor(ms / 1000);
  const h = Math.floor(total / 3600);
  const m = Math.floor((total % 3600) / 60);
  const s = total % 60;

  return (
    <div className="polls-state polls-open">
      <div className="polls-flag">
        <span className="dot"></span>
        <span>Polls Open</span>
      </div>
      <div className="countdown" aria-live="polite">
        <span className="cd-num">{String(h).padStart(2,'0')}</span>
        <span className="cd-sep">:</span>
        <span className="cd-num">{String(m).padStart(2,'0')}</span>
        <span className="cd-sep">:</span>
        <span className="cd-num">{String(s).padStart(2,'0')}</span>
      </div>
      <div className="polls-sub">until polls close · 7:00 PM CT</div>
    </div>
  );
}

function fmtClock(ms) {
  const total = Math.max(0, Math.floor(ms / 1000));
  const h = Math.floor(total / 3600);
  const m = Math.floor((total % 3600) / 60);
  return `${h}h ${String(m).padStart(2,'0')}m`;
}

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