/* Settings tab.
 *
 * Phase 4 ships with one panel: Pending Setup (member sheet, meeting
 * template, workout builder). The rest of Settings (theme, data export,
 * keyboard shortcuts) lands in Phase 8.
 */
(function () {
  const { useState, useEffect } = React;
  const {
    Banner,
    Button,
    Card,
    Input,
    Pill,
    Drawer,
    LoadingSpinner,
    EmptyState,
    Icons,
    showToast,
    coach,
    members,
    meetings,
    entries,
    fb,
    time,
    tokens,
  } = window.CC;

  function Settings() {
    const [open, setOpen] = useState(null); // "sheet" | "meeting" | "workouts" | null

    return (
      <div className="cc-settings">
        <h1 className="cc-hub__title">Settings</h1>

        <section className="cc-settings__section">
          <h2 className="cc-section-h2">Pending setup</h2>
          <PendingItem
            title="Member sheet"
            status={<SheetStatus />}
            cta="Configure →"
            onClick={() => setOpen("sheet")}
          />
          <PendingItem
            title="Meeting agenda template"
            status={<span className="cc-settings__status cc-settings__status--idle">Placeholder template active</span>}
            cta="Configure →"
            onClick={() => setOpen("meeting")}
          />
          <PendingItem
            title="Workout builder"
            status={<span className="cc-settings__status cc-settings__status--idle">Embed pending paste</span>}
            cta="Open →"
            onClick={() => setOpen("workouts")}
          />
        </section>

        <section className="cc-settings__section">
          <h2 className="cc-section-h2">Workouts</h2>
          <Card padding={16}>
            <EquipmentEditor />
          </Card>
        </section>

        <section className="cc-settings__section">
          <h2 className="cc-section-h2">Coach</h2>
          <Card padding={16}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
              <span>
                Signed in as <strong>{coach.label(coach.get())}</strong>
              </span>
              <Button
                variant="ghost"
                onClick={() => {
                  if (confirm("Switch user? Next person to open the app picks again.")) {
                    coach.clear();
                    location.reload();
                  }
                }}
              >
                Switch user
              </Button>
            </div>
          </Card>
        </section>

        <section className="cc-settings__section">
          <h2 className="cc-section-h2">Keyboard shortcuts</h2>
          <Card padding={16}>
            <ul className="cc-settings__shortcuts">
              {window.CC.shortcuts.catalogue.map((s, i) => (
                <li key={i}>
                  <span className="cc-settings__shortcut-keys">
                    {s.keys.map((k, j) => (
                      <kbd key={j}>{k}</kbd>
                    ))}
                  </span>
                  <span className="cc-settings__shortcut-desc">{s.desc}</span>
                </li>
              ))}
            </ul>
          </Card>
        </section>

        <section className="cc-settings__section">
          <h2 className="cc-section-h2">Data</h2>
          <Card padding={16}>
            <DataExport />
          </Card>
          <Card padding={16}>
            <FirebaseHealth />
          </Card>
        </section>

        <SheetSetupDrawer open={open === "sheet"} onClose={() => setOpen(null)} />
        <MeetingTemplateDrawer
          open={open === "meeting"}
          onClose={() => setOpen(null)}
        />
        <Drawer open={open === "workouts"} onClose={() => setOpen(null)} title="Workout builder">
          <p style={{ color: tokens.colors.textMuted }}>
            Phase 6 embeds your existing workout-builder HTML directly.
            Paste the contents of <code>workout-builder-v2*.html</code>{" "}
            into the form — we extract the React component and wrap it in
            the Workouts tab without restyling.
          </p>
          <p style={{ color: tokens.colors.textDim, fontSize: 12, marginTop: 8 }}>
            Field activates in Phase 6.
          </p>
        </Drawer>
      </div>
    );
  }

  function PendingItem({ title, status, cta, onClick }) {
    return (
      <Card padding={16}>
        <div className="cc-settings__pending-item">
          <div>
            <div className="cc-settings__pending-title">{title}</div>
            <div className="cc-settings__pending-status">{status}</div>
          </div>
          <Button variant="ghost" onClick={onClick}>
            {cta}
          </Button>
        </div>
      </Card>
    );
  }

  function SheetStatus() {
    const [meta, setMeta] = useState(members.meta());
    useEffect(() => members.subscribe((_, m) => setMeta(m)), []);
    if (meta.source === "sheet") {
      return (
        <span className="cc-settings__status cc-settings__status--ok">
          {Icons.check(12)} Connected · last refreshed {time.relative(meta.fetched_at)}
        </span>
      );
    }
    if (meta.error) {
      return (
        <span className="cc-settings__status cc-settings__status--err">
          {Icons.x(12)} {meta.error}
        </span>
      );
    }
    return (
      <span className="cc-settings__status cc-settings__status--idle">
        Showing placeholders · not connected
      </span>
    );
  }

  function SheetSetupDrawer({ open, onClose }) {
    const [cfg, setCfg] = useState(null);
    const [loading, setLoading] = useState(true);
    const [saving, setSaving] = useState(false);
    const [testing, setTesting] = useState(false);

    useEffect(() => {
      if (!open) return;
      setLoading(true);
      members.loadSheetConfig().then((existing) => {
        setCfg(
          existing || {
            sheet_id: "",
            tab_name: "",
            header_row: 5,
            column_map: members.DEFAULT_COLUMN_MAP,
          }
        );
        setLoading(false);
      });
    }, [open]);

    async function save() {
      if (!cfg) return;
      setSaving(true);
      try {
        await members.saveSheetConfig(cfg);
        showToast("Configuration saved.");
      } catch (e) {
        showToast("Couldn’t save.");
      } finally {
        setSaving(false);
      }
    }
    async function testConnection() {
      setTesting(true);
      try {
        const r = await members.refreshFromSheet();
        showToast(`Pulled ${r.count} members.`);
      } catch (e) {
        showToast(`Test failed: ${e.message || e}`);
      } finally {
        setTesting(false);
      }
    }

    if (!open) return null;
    return (
      <Drawer
        open={open}
        onClose={onClose}
        title="Member sheet"
        footer={
          <div style={{ display: "flex", gap: 8 }}>
            <Button
              variant="secondary"
              onClick={testConnection}
              loading={testing}
            >
              Test connection
            </Button>
            <Button onClick={save} loading={saving} fullWidth>
              Save
            </Button>
          </div>
        }
      >
        {loading || !cfg ? (
          <LoadingSpinner delay={0} />
        ) : (
          <div style={{ display: "grid", gap: 16 }}>
            <p style={{ margin: 0, fontSize: 14, color: tokens.colors.textMuted }}>
              Tomorrow you’ll run the OAuth flow on your other computer
              (instructions in <code>functions/setup-oauth.js</code>).
              Until then this form is functional but the live fetch will
              fail with a credential error — that’s expected.
            </p>

            <Input
              label="Sheet ID"
              value={cfg.sheet_id}
              onChange={(v) => setCfg({ ...cfg, sheet_id: v })}
              placeholder="from the sheet URL between /d/ and /edit"
            />
            <Input
              label="Tab name"
              value={cfg.tab_name}
              onChange={(v) => setCfg({ ...cfg, tab_name: v })}
              placeholder="e.g. Client Tracker"
            />
            <Input
              label="Header row"
              type="number"
              value={String(cfg.header_row)}
              onChange={(v) => setCfg({ ...cfg, header_row: Number(v) || 5 })}
            />

            <details className="cc-settings__details">
              <summary>Column mapping ({Object.keys(cfg.column_map).length})</summary>
              <p style={{ fontSize: 13, color: tokens.colors.textMuted, margin: "8px 0" }}>
                App field → header name in your sheet. Match by the value
                of the header cell (case-insensitive). Reorder the columns
                in the sheet without breaking the integration.
              </p>
              <div style={{ display: "grid", gap: 8 }}>
                {Object.entries(cfg.column_map).map(([field, header]) => (
                  <div
                    key={field}
                    style={{
                      display: "grid",
                      gridTemplateColumns: "120px 1fr",
                      gap: 8,
                      alignItems: "center",
                    }}
                  >
                    <span
                      style={{
                        fontFamily: tokens.typography.fontMono,
                        fontSize: 12,
                        color: tokens.colors.textMuted,
                      }}
                    >
                      {field}
                    </span>
                    <Input
                      value={header}
                      onChange={(v) =>
                        setCfg({
                          ...cfg,
                          column_map: { ...cfg.column_map, [field]: v },
                        })
                      }
                    />
                  </div>
                ))}
              </div>
            </details>
          </div>
        )}
      </Drawer>
    );
  }

  // ────────────────────────────────────────────────────────────
  // Equipment editor — drives the silent clash detector
  // ────────────────────────────────────────────────────────────
  function EquipmentEditor() {
    const [snap, setSnap] = useState(null);
    const [draft, setDraft] = useState("");
    useEffect(() => window.CC.workouts.subscribe(setSnap), []);

    const equipment = snap?.catalogue?.equipment || [];

    async function update(name, count) {
      const next = equipment.map((e) =>
        e.name === name ? { ...e, count } : e
      );
      await window.CC.workouts.saveCatalogue({ equipment: next });
    }
    async function remove(name) {
      await window.CC.workouts.saveCatalogue({
        equipment: equipment.filter((e) => e.name !== name),
      });
    }
    async function add() {
      const name = draft.trim();
      if (!name) return;
      if (equipment.find((e) => e.name === name)) {
        showToast("Already in the list.");
        return;
      }
      await window.CC.workouts.saveCatalogue({
        equipment: [...equipment, { name, count: 99 }],
      });
      setDraft("");
    }

    return (
      <div>
        <div style={{ marginBottom: 12 }}>
          <div style={{ fontWeight: 600, fontSize: 15 }}>Equipment inventory</div>
          <div
            style={{
              fontSize: 13,
              color: tokens.colors.textMuted,
              marginTop: 2,
            }}
          >
            Anything with a count of 1 triggers the silent clash detector — the
            generator won’t pick two exercises that need it at the same time.
          </div>
        </div>
        <ul className="cc-eq__list">
          {equipment.map((e) => (
            <li key={e.name}>
              <span className="cc-eq__name">{e.name}</span>
              <input
                type="number"
                min="1"
                value={e.count}
                onChange={(ev) => update(e.name, Number(ev.target.value) || 1)}
                className="cc-eq__count"
              />
              <button
                type="button"
                onClick={() => remove(e.name)}
                aria-label={`Remove ${e.name}`}
                className="cc-eq__rm"
              >
                {Icons.x(12)}
              </button>
            </li>
          ))}
        </ul>
        <div className="cc-lib__add" style={{ marginTop: 12 }}>
          <input
            type="text"
            placeholder="Add equipment…"
            value={draft}
            onChange={(e) => setDraft(e.target.value)}
            onKeyDown={(e) => e.key === "Enter" && add()}
          />
          <Button onClick={add} disabled={!draft.trim()}>
            Add
          </Button>
        </div>
      </div>
    );
  }

  // ────────────────────────────────────────────────────────────
  // Data export — JSON dump of everything under /coaches-copilot
  // ────────────────────────────────────────────────────────────
  function DataExport() {
    const [busy, setBusy] = useState(false);
    async function run() {
      setBusy(true);
      try {
        const all = await fb.once("");
        const blob = new Blob([JSON.stringify(all, null, 2)], {
          type: "application/json",
        });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        const ts = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
        a.href = url;
        a.download = `coaches-copilot-${ts}.json`;
        a.click();
        setTimeout(() => URL.revokeObjectURL(url), 2000);
        showToast("Export downloaded.");
      } catch (e) {
        showToast(`Export failed: ${e.message || e}`);
      }
      setBusy(false);
    }
    return (
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 16 }}>
        <div>
          <div style={{ fontWeight: 600, fontSize: 15 }}>Export everything</div>
          <div style={{ fontSize: 13, color: tokens.colors.textMuted, marginTop: 2 }}>
            Download all entries, events, meetings, and config as JSON.
          </div>
        </div>
        <Button variant="secondary" onClick={run} loading={busy}>
          {Icons.arrowDown(14)} Download
        </Button>
      </div>
    );
  }

  // ────────────────────────────────────────────────────────────
  // Firebase health probe
  // ────────────────────────────────────────────────────────────
  function FirebaseHealth() {
    const [state, setState] = useState({ ok: null, ts: null });
    useEffect(() => {
      // .info/connected is at the database root, not under our scope.
      const ref = fb.db.ref(".info/connected");
      const handler = ref.on("value", (snap) => {
        setState({ ok: !!snap.val(), ts: Date.now() });
      });
      return () => ref.off("value", handler);
    }, []);
    const ok = state.ok;
    return (
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 16 }}>
        <div>
          <div style={{ fontWeight: 600, fontSize: 15 }}>Firebase</div>
          <div style={{ fontSize: 13, color: tokens.colors.textMuted, marginTop: 2 }}>
            transformhub-ac09c · /coaches-copilot
          </div>
        </div>
        <span
          style={{
            display: "inline-flex",
            alignItems: "center",
            gap: 6,
            fontSize: 13,
            fontFamily: tokens.typography.fontMono,
            color:
              ok === true
                ? tokens.colors.status.onTrack
                : ok === false
                ? tokens.colors.status.lost
                : tokens.colors.textDim,
          }}
        >
          <span
            style={{
              width: 8,
              height: 8,
              borderRadius: "50%",
              background:
                ok === true
                  ? tokens.colors.status.onTrack
                  : ok === false
                  ? tokens.colors.status.lost
                  : tokens.colors.textDim,
            }}
          />
          {ok === true ? "connected" : ok === false ? "offline" : "checking…"}
        </span>
      </div>
    );
  }

  // ────────────────────────────────────────────────────────────
  // Meeting agenda template editor
  // ────────────────────────────────────────────────────────────
  function MeetingTemplateDrawer({ open, onClose }) {
    const [text, setText] = useState("");
    const [loading, setLoading] = useState(true);
    const [saving, setSaving] = useState(false);

    useEffect(() => {
      if (!open) return;
      setLoading(true);
      meetings.loadAgendaTemplate().then((sections) => {
        setText(sections.map((s) => s.title).join("\n"));
        setLoading(false);
      });
    }, [open]);

    async function save() {
      const sections = text
        .split("\n")
        .map((l) => l.trim())
        .filter(Boolean)
        .map((title, i) => ({
          id: title.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 24) || `section-${i}`,
          title,
        }));
      if (sections.length === 0) {
        showToast("Add at least one section.");
        return;
      }
      setSaving(true);
      try {
        await meetings.saveAgendaTemplate(sections);
        showToast(`Saved ${sections.length} sections.`);
        onClose();
      } catch (e) {
        showToast("Couldn’t save.");
      } finally {
        setSaving(false);
      }
    }

    async function reset() {
      const sections = meetings.DEFAULT_AGENDA;
      setText(sections.map((s) => s.title).join("\n"));
    }

    if (!open) return null;
    return (
      <Drawer
        open={open}
        onClose={onClose}
        title="Meeting agenda template"
        footer={
          <div style={{ display: "flex", gap: 8 }}>
            <Button variant="ghost" onClick={reset}>
              Reset to default
            </Button>
            <span style={{ flex: 1 }} />
            <Button onClick={save} loading={saving}>
              Save
            </Button>
          </div>
        }
      >
        {loading ? (
          <LoadingSpinner delay={0} />
        ) : (
          <>
            <p style={{ margin: 0, color: tokens.colors.textMuted, fontSize: 14 }}>
              One section per line. The order here is the order they
              appear in the recording view. “Carryover from last
              meeting” is auto-prepended whenever there are open items
              from the previous meeting — you don’t need to include it.
            </p>
            <textarea
              className="cc-settings__textarea"
              value={text}
              onChange={(e) => setText(e.target.value)}
              rows={12}
              autoFocus
              style={{ marginTop: 16 }}
            />
          </>
        )}
      </Drawer>
    );
  }

  window.CC = window.CC || {};
  window.CC.Settings = Settings;
})();
