// Main app — top tabs, no sidebar. Compact layout.

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

const DEFAULT_TWEAKS = /*EDITMODE-BEGIN*/{
  "heatmap": "warm",
  "density": "compact",
  "showHints": true,
  "slotThreshold": 2
}/*EDITMODE-END*/;

function App() {
  const [dataReady, setDataReady] = useState(false);
  const [clientAvail, setClientAvail] = useState(window.FS_DATA.CLIENT_AVAIL);
  const [therapistAvail, setTherapistAvail] = useState(window.FS_DATA.THERAPIST_AVAIL);
  const [pairings, setPairings] = useState(window.FS_DATA.PAIRINGS);

  const [tab, setTab] = useState('client');
  const [weekIdx, setWeekIdx] = useState(0);
  const [selectedClient, setSelectedClient] = useState(window.FS_DATA.CLIENTS[0].id);
  const [selectedTherapist, setSelectedTherapist] = useState(window.FS_DATA.THERAPISTS[0].id);
  const [filterMode, setFilterMode] = useState(false);

  const [clients, setClientsState] = useState(window.FS_DATA.CLIENTS);
  const [therapists, setTherapistsState] = useState(window.FS_DATA.THERAPISTS);
  const [slotThreshold, setSlotThreshold] = useState(2);

  // Mirror to FS_DATA so all child components/matchers see the same arrays.
  useEffect(() => { window.FS_DATA.setClients(clients); }, [clients]);
  useEffect(() => { window.FS_DATA.setTherapists(therapists); }, [therapists]);

  // Load from Firestore on mount.
  useEffect(() => {
    const db = firebase.firestore();
    Promise.all([
      db.doc('planner/state').get(),
      db.doc('planner/settings').get(),
    ]).then(([stateSnap, settingsSnap]) => {
      if (stateSnap.exists) {
        const d = stateSnap.data();
        if (d.clientAvail)    setClientAvail(d.clientAvail);
        if (d.therapistAvail) setTherapistAvail(d.therapistAvail);
        if (d.pairings)       setPairings(d.pairings);
      }
      if (settingsSnap.exists) {
        const d = settingsSnap.data();
        if (Array.isArray(d.clients) && d.clients.length > 0) {
          setClientsState(d.clients);
          window.FS_DATA.setClients(d.clients);
        }
        if (Array.isArray(d.therapists) && d.therapists.length > 0) {
          setTherapistsState(d.therapists);
          window.FS_DATA.setTherapists(d.therapists);
        }
        if (d.slotThreshold != null) setSlotThreshold(d.slotThreshold);
      }
      setDataReady(true);
    }).catch(err => {
      console.error('Firestore load failed, using defaults:', err);
      setDataReady(true);
    });
  }, []);

  // Debounced save of schedule state to Firestore.
  const stateTimerRef = useRef(null);
  useEffect(() => {
    if (!dataReady) return;
    clearTimeout(stateTimerRef.current);
    stateTimerRef.current = setTimeout(() => {
      firebase.firestore().doc('planner/state')
        .set({ clientAvail, therapistAvail, pairings })
        .catch(console.error);
    }, 800);
  }, [clientAvail, therapistAvail, pairings, dataReady]);

  // Debounced save of roster/settings to Firestore.
  const settingsTimerRef = useRef(null);
  useEffect(() => {
    if (!dataReady) return;
    if (clients.length === 0 || therapists.length === 0) return;
    clearTimeout(settingsTimerRef.current);
    settingsTimerRef.current = setTimeout(() => {
      firebase.firestore().doc('planner/settings')
        .set({ clients, therapists, slotThreshold })
        .catch(console.error);
    }, 800);
  }, [clients, therapists, slotThreshold, dataReady]);

  const tweaks = window.useTweaks ? window.useTweaks(DEFAULT_TWEAKS) : null;
  const tweakVals = tweaks ? tweaks[0] : DEFAULT_TWEAKS;
  const setTweak = tweaks ? tweaks[1] : () => {};

  useEffect(() => {
    const root = document.documentElement.style;
    if (tweakVals.heatmap === 'cool') {
      root.setProperty('--heatmap-low', '#eef0ec'); root.setProperty('--heatmap-mid', '#e0eaf5'); root.setProperty('--heatmap-high', '#e4f1e8');
    } else if (tweakVals.heatmap === 'mono') {
      root.setProperty('--heatmap-low', '#f4ecdd'); root.setProperty('--heatmap-mid', '#e4f1e8'); root.setProperty('--heatmap-high', '#a7d1b4');
    } else {
      root.setProperty('--heatmap-low', '#f0d7cf'); root.setProperty('--heatmap-mid', '#f4e1b0'); root.setProperty('--heatmap-high', '#e4f1e8');
    }
    if (tweakVals.density === 'compact') {
      root.setProperty('--density-cell-h', '34px'); root.setProperty('--density-sched-h', '54px');
    } else {
      root.setProperty('--density-cell-h', '40px'); root.setProperty('--density-sched-h', '64px');
    }
  }, [tweakVals.heatmap, tweakVals.density]);

  const toggleCell = (kind) => (personId, wIdx, dayId, slotIdx) => {
    const setter = kind === 'client' ? setClientAvail : setTherapistAvail;
    setter(prev => {
      const next = { ...prev };
      const person = { ...(next[personId] || {}) };
      const week = { ...(person[wIdx] || {}) };
      const days = [...(week[dayId] || [false, false, false])];
      days[slotIdx] = !days[slotIdx];
      week[dayId] = days; person[wIdx] = week; next[personId] = person;
      return next;
    });
  };
  const replicate = (kind) => (personId, fromWeek, scope) => {
    const setter = kind === 'client' ? setClientAvail : setTherapistAvail;
    setter(prev => {
      const next = { ...prev };
      const person = { ...(next[personId] || {}) };
      const source = person[fromWeek] || {};
      for (const w of window.FS_DATA.WEEKS) {
        if (scope === 'rest' && w.id < fromWeek) continue;
        if (w.id === fromWeek) continue;
        const cloneDays = {};
        for (const d of window.FS_DATA.DAYS) cloneDays[d.id] = [...(source[d.id] || [false, false, false])];
        person[w.id] = cloneDays;
      }
      next[personId] = person; return next;
    });
  };
  const clearWeek = (kind) => (personId, wIdx) => {
    const setter = kind === 'client' ? setClientAvail : setTherapistAvail;
    setter(prev => {
      const next = { ...prev };
      const person = { ...(next[personId] || {}) };
      const week = {};
      for (const d of window.FS_DATA.DAYS) week[d.id] = [false, false, false];
      person[wIdx] = week; next[personId] = person; return next;
    });
  };
  const pairingAdd = (cid, tid) => setPairings(prev => { const list = prev[cid] || []; if (list.includes(tid)) return prev; return { ...prev, [cid]: [...list, tid] }; });
  const pairingRemove = (cid, idx) => setPairings(prev => { const list = [...(prev[cid] || [])]; list.splice(idx, 1); return { ...prev, [cid]: list }; });
  const pairingReorder = (cid, from, to) => setPairings(prev => { const list = [...(prev[cid] || [])]; if (to < 0 || to >= list.length) return prev; const [x] = list.splice(from, 1); list.splice(to, 0, x); return { ...prev, [cid]: list }; });

  const weekAvailC = useMemo(() => { const out = {}; for (const c of window.FS_DATA.CLIENTS) out[c.id] = clientAvail[c.id]?.[weekIdx] || {}; return out; }, [clientAvail, weekIdx]);
  const weekAvailT = useMemo(() => { const out = {}; for (const t of window.FS_DATA.THERAPISTS) out[t.id] = therapistAvail[t.id]?.[weekIdx] || {}; return out; }, [therapistAvail, weekIdx]);
  const schedule = useMemo(() => window.FS_MATCHER.buildWeekSchedule(weekIdx, weekAvailC, weekAvailT, pairings), [weekIdx, weekAvailC, weekAvailT, pairings, clients, therapists]);
  const metrics = useMemo(() => window.FS_MATCHER.weekMetrics(schedule, weekAvailC, weekAvailT, slotThreshold), [schedule, weekAvailC, weekAvailT, slotThreshold]);
  const hints = useMemo(() => window.FS_MATCHER.negotiationHints(weekIdx, weekAvailC, weekAvailT, pairings, schedule), [weekIdx, weekAvailC, weekAvailT, pairings, schedule]);
  const sparks = useMemo(() => { const out = {}; for (const w of window.FS_DATA.WEEKS) out[w.id] = window.FS_MATCHER.weekSparkData(w.id, clientAvail, therapistAvail, pairings); return out; }, [clientAvail, therapistAvail, pairings]);
  const allSchedules = useMemo(() => window.FS_MATCHER.buildAllWeeks(clientAvail, therapistAvail, pairings), [clientAvail, therapistAvail, pairings]);
  const totalScheduled = useMemo(() => { let n = 0; for (const w of window.FS_DATA.WEEKS) n += window.FS_MATCHER.countMatched(allSchedules[w.id]); return n; }, [allSchedules]);

  const resetData = () => {
    if (!confirm("Reset all availability and pairings to demo data?")) return;
    setClientAvail(window.FS_DATA.CLIENT_AVAIL);
    setTherapistAvail(window.FS_DATA.THERAPIST_AVAIL);
    setPairings(window.FS_DATA.PAIRINGS);
  };

  const exportCsv = () => {
    const rows = [["Week", "Slot", "Time", "Day", "Client", "Therapist", "Location"]];
    for (const w of window.FS_DATA.WEEKS) {
      const sched = allSchedules[w.id];
      for (const d of window.FS_DATA.DAYS) {
        for (let s = 0; s < window.FS_DATA.SLOTS.length; s++) {
          const cell = sched[d.id][s];
          for (const m of cell.matched) {
            rows.push([`Week of ${w.month} ${w.day}`, window.FS_DATA.SLOTS[s].label, window.FS_DATA.SLOTS[s].time, d.label, window.FS_DATA.getClient(m.clientId).name, window.FS_DATA.getTherapist(m.therapistId).name, window.FS_DATA.getLoc(m.loc).label]);
          }
          for (const cid of cell.unmatched) {
            const uc = window.FS_DATA.getClient(cid);
            const ucLoc = Array.isArray(uc.loc) ? uc.loc.join('/') : (window.FS_DATA.getLoc(uc.loc)?.label || uc.loc);
            rows.push([`Week of ${w.month} ${w.day}`, window.FS_DATA.SLOTS[s].label, window.FS_DATA.SLOTS[s].time, d.label, uc.name, "UNMATCHED", ucLoc]);
          }
        }
      }
    }
    const csv = rows.map(r => r.map(v => /[",\n]/.test(v) ? `"${v.replace(/"/g, '""')}"` : v).join(",")).join("\n");
    const blob = new Blob([csv], { type: "text/csv" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a"); a.href = url; a.download = "famspring-summer-2026.csv"; a.click();
    URL.revokeObjectURL(url);
  };

  const onJumpToTherapist = (tid) => { setSelectedTherapist(tid); setTab('therapist'); setFilterMode(false); };
  const onJumpToClient = (cid) => { setSelectedClient(cid); setTab('client'); setFilterMode(false); };

  if (!dataReady) return (
    <div className="auth-screen">
      <div className="auth-card">
        <div className="auth-brand">
          <div className="brand-mark">F</div>
          <div className="brand-name">Famspring</div>
        </div>
        <p className="auth-sub" style={{textAlign:'center', marginTop: 20}}>Loading schedule data…</p>
      </div>
    </div>
  );

  // Determine the highlight subject from current tab + selection
  const highlightId = tab === 'client' ? selectedClient : tab === 'therapist' ? selectedTherapist : null;
  const highlightKind = tab === 'client' ? 'client' : tab === 'therapist' ? 'therapist' : null;

  const Tab = ({ id, label, count }) => (
    <button className={`ttab ${tab === id ? 'active' : ''}`} onClick={() => { setTab(id); setFilterMode(false); }}>
      <span>{label}</span>
      {count != null && <span className="badge">{count}</span>}
    </button>
  );

  const showCapture = tab === 'client' || tab === 'therapist';

  return (
    <div data-screen-label={`Tab: ${tab}`}>
      <div className="topbar">
        <div className="brand">
          <div className="brand-mark">F</div>
          <div className="brand-name">Famspring</div>
        </div>
        <div className="topbar-tabs">
          <Tab id="client" label="Client availability" count={window.FS_DATA.CLIENTS.length} />
          <Tab id="therapist" label="Therapist availability" count={window.FS_DATA.THERAPISTS.length} />
          <Tab id="pairings" label="Client → therapist" />
          <Tab id="locked" label="Locked schedule" count={totalScheduled} />
          <Tab id="settings" label="Settings" />
        </div>
        <div className="topbar-actions">
          <button className="btn-sm" onClick={exportCsv} title="Export CSV">⤓ CSV</button>
          {tab === 'locked' && <button className="btn-sm primary" onClick={() => window.print()}>⎙ Print / PDF</button>}
          <button className="btn-sm" onClick={resetData} title="Reset to demo data">↻</button>
          {window.FS_AUTH && (
            <div style={{display:'flex', alignItems:'center', gap:8, marginLeft:8, paddingLeft:8, borderLeft:'1px solid var(--ink-300)'}}>
              <div style={{width:26, height:26, borderRadius:'50%', background:'var(--green-600)', color:'var(--cream-50)', display:'grid', placeItems:'center', fontSize:11, fontWeight:700, flexShrink:0}}>
                {(window.FS_AUTH.user.displayName || window.FS_AUTH.user.email).charAt(0).toUpperCase()}
              </div>
              <span style={{fontSize:12, color:'var(--ink-700)', fontWeight:500, maxWidth:140, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap'}}>
                {window.FS_AUTH.user.displayName || window.FS_AUTH.user.email}
              </span>
              <button className="btn-sm" onClick={window.FS_AUTH.signOut} style={{color:'var(--danger)', borderColor:'var(--danger)'}}>Log out</button>
            </div>
          )}
        </div>
      </div>

      <main className="main">
        {showCapture && (
          <>
            <window.WeekStrip value={weekIdx} onChange={setWeekIdx} sparks={sparks} />

            <div className="two-col">
              <div className="left-stack">
                {tab === 'client' ? (
                  <window.AvailabilityTab
                    kind="client" selectedId={selectedClient} onSelectId={setSelectedClient}
                    weekIdx={weekIdx} avail={clientAvail} schedule={schedule}
                    onToggle={toggleCell('client')} onReplicate={replicate('client')} onClearWeek={clearWeek('client')}
                  />
                ) : (
                  <window.AvailabilityTab
                    kind="therapist" selectedId={selectedTherapist} onSelectId={setSelectedTherapist}
                    weekIdx={weekIdx} avail={therapistAvail} schedule={schedule}
                    onToggle={toggleCell('therapist')} onReplicate={replicate('therapist')} onClearWeek={clearWeek('therapist')}
                  />
                )}
                <window.MetricsRow metrics={metrics} hints={hints} showHints={tweakVals.showHints} />
              </div>
              <window.SchedulePreview
                weekIdx={weekIdx} schedule={schedule}
                highlightId={highlightId} highlightKind={highlightKind}
                filterMode={filterMode} onToggleFilter={setFilterMode}
                onJumpToTherapist={onJumpToTherapist} onJumpToClient={onJumpToClient}
              />
            </div>
          </>
        )}

        {tab === 'pairings' && (
          <window.PairingsTab pairings={pairings} onAdd={pairingAdd} onRemove={pairingRemove} onReorder={pairingReorder} />
        )}

        {tab === 'locked' && (
          <window.LockedView allSchedules={allSchedules} onPrint={() => window.print()} />
        )}

        {tab === 'settings' && (
          <window.SettingsTab
            clients={clients} therapists={therapists}
            slotThreshold={slotThreshold}
            onSetClients={setClientsState}
            onSetTherapists={setTherapistsState}
            onSetThreshold={setSlotThreshold}
          />
        )}
      </main>

      {window.TweaksPanel && (
        <window.TweaksPanel>
          <window.TweakSection title="Schedule">
            <window.TweakToggle label="Negotiation suggestions" hint="Show 'if X added one slot…' hints." value={tweakVals.showHints} onChange={(v) => setTweak('showHints', v)} />
            <window.TweakRadio label="Heatmap palette" value={tweakVals.heatmap} onChange={(v) => setTweak('heatmap', v)}
              options={[{ value: 'warm', label: 'Warm' }, { value: 'cool', label: 'Cool' }, { value: 'mono', label: 'Mono' }]} />
            <window.TweakRadio label="Density" value={tweakVals.density} onChange={(v) => setTweak('density', v)}
              options={[{ value: 'compact', label: 'Compact' }, { value: 'cozy', label: 'Cozy' }]} />
          </window.TweakSection>
        </window.TweaksPanel>
      )}
    </div>
  );
}

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