// Settings — full local desktop behavior & processing defaults (faithful to the app).
function SettingsScreen() {
  const { Button, Badge } = window.ROKKORDesignSystem_4e99ef;
  const { PageHead } = window.RokkorScreens;
  const { Section, Inset, ToggleRow, Select, Field, Notice, RadioRow } = window.RokkorKit;
  const I = window.RokkorIcons;

  const [s, setS] = React.useState({
    autopaste: true, sounds: true, grammar: true, fast: true, live: true, selfcorr: true,
    whisper: false, trim: false, localgrammar: false, ptt: true, autodetect: false, secondlang: false,
    markdown: false, skipgrammar: false, launch: true, tray: true, updates: true, mute: false,
    ollama: true, autobackup: true, includeaudio: false, keepdata: true, indicator: "show",
  });
  const t = (k) => (v) => setS((p) => ({ ...p, [k]: v }));

  const fieldRow = { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 20 };

  return (
    <div style={{ maxWidth: "var(--content-max)" }}>
      <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between" }}>
        <PageHead title="Settings" subtitle="Local desktop behavior and processing defaults." />
        <div style={{ marginTop: 30 }}><Button variant="outline" icon={<I.Refresh size={15} />}>Refresh</Button></div>
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: 22 }}>
        {/* PERMISSIONS */}
        <Section icon={I.Mic} title="Permissions" desc="Current platform permission checks.">
          <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
            <Inset>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                <span style={{ font: "600 14px/1 var(--font-sans)", color: "var(--ink-900)" }}>Input devices</span>
                <span style={{ font: "600 13px/1 var(--font-mono)", color: "var(--ink-500)" }}>2</span>
              </div>
              <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: 12 }}>
                <span style={{ font: "400 14px/1.4 var(--font-sans)", color: "var(--ink-800)" }}>Analogue 1 + 2 (Focusrite USB Audio)</span>
                <Badge tone="neutral">Default</Badge>
              </div>
              <div style={{ font: "400 14px/1.4 var(--font-sans)", color: "var(--ink-800)", marginTop: 8 }}>Microphone (Steam Streaming Microphone)</div>
            </Inset>
            {[
              [I.Refresh, "Welcome setup", "Re-run the first-run welcome — review the privacy promise, re-check your microphone, pick your dictation language, and the optional Elite toggle.", "Re-run welcome"],
              [I.Waveform, "Voice calibration", "Read a few short lines so we learn how the Transcription Engine hears your voice and mic, then auto-correct the words it gets wrong. Re-run any time — it does not retrain the speech model.", "Re-run"],
              [I.Volume, "Audio pipeline calibration", "Measure your mic, background noise, and how loud you speak so ROKKOR can tune its audio cleanup — noise handling, auto-gain, and the silence gate — to your setup. Recalibrate any time. This adjusts input quality; it does not retrain the speech model.", "Recalibrate"],
            ].map(([Ic, title, desc, btn], i) => (
              <Inset key={i}>
                <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 16 }}>
                  <div>
                    <div style={{ display: "flex", alignItems: "center", gap: 8, font: "600 14px/1 var(--font-sans)", color: "var(--ink-900)" }}><Ic size={16} /> {title}</div>
                    <div style={{ font: "400 12.5px/1.5 var(--font-sans)", color: "var(--ink-500)", marginTop: 6, maxWidth: 640 }}>{desc}</div>
                  </div>
                  <div style={{ flex: "none" }}><Button variant="outline" size="sm">{btn}</Button></div>
                </div>
              </Inset>
            ))}
          </div>
        </Section>

        {/* GENERAL */}
        <Section title="General" desc="Saved in the local SQLite settings store.">
          <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
            <Select label="Interface language" value="English" options={["English", "Español", "Deutsch", "Français", "日本語"]} hint="Changes the app's UI language. Dictation language is set separately under Speech." />
            <div style={{ height: 8 }} />
            <ToggleRow label="Auto-paste at cursor" hint="Automatically inserts transcribed text where your cursor is" checked={s.autopaste} onChange={t("autopaste")} />
            <ToggleRow label="Play start and stop sounds" hint="Subtle audio feedback" checked={s.sounds} onChange={t("sounds")} divider />
            <ToggleRow label="Grammar post-processing" hint="Cleans grammar, punctuation and casing after transcription" checked={s.grammar} onChange={t("grammar")} divider />
            <div style={{ height: 10 }} />
            <Select label="Cleanup intensity" value="Context-aware — Reconstruct intent from fast/tired/slurred speech" options={["Raw — paste exactly as spoken", "Light — punctuation & capitalization only", "Standard — clean grammar & fillers", "Heavy — polish & rephrase", "Context-aware — Reconstruct intent from fast/tired/slurred speech"]} hint="Per-app overrides live in Style & Tone." />
            <div style={{ height: 8 }} />
            <ToggleRow label="Fast mode — skip LLM grammar cleanup on short phrases for lower latency, deterministic corrections still apply" checked={s.fast} onChange={t("fast")} />
            <ToggleRow label="Live transcript preview — start transcribing while you speak so long dictation lands instantly on release" hint="English captures only. Other languages transcribe on release as before." checked={s.live} onChange={t("live")} divider />
            <Notice tone="warning" style={{ margin: "8px 0" }}>During-speech streaming runs on the Standard engine only. The native Elite engine transcribes on release (offline, v1.0) — this toggle has no effect while Elite is active.</Notice>
            <ToggleRow label="Spoken self-corrections" hint='Removes the false start when you say "scratch that" or "no wait, I meant…"' checked={s.selfcorr} onChange={t("selfcorr")} />
            <ToggleRow label="Whisper mode (quiet speech)" hint="Boosts gain and lowers the voice threshold for very quiet dictation. Applies to the standard engine leg." checked={s.whisper} onChange={t("whisper")} divider />
            <ToggleRow label="Trim silence before transcription (Silero VAD)" hint="Requires the Silero model from the Models tab. Skips leading/trailing silence for faster transcription." checked={s.trim} onChange={t("trim")} divider />
            <ToggleRow label="Local grammar cleanup (no Ollama, CPU)" hint="Runs grammar cleanup fully on-device with a built-in 0.5B model — no Ollama or Docker required. Much slower than the GPU server path (seconds per phrase on CPU); turn on only if you want zero external runtime." checked={s.localgrammar} onChange={t("localgrammar")} divider />
            <ToggleRow label="Push to talk" checked={s.ptt} onChange={t("ptt")} divider />
            <div style={{ ...fieldRow, marginTop: 14 }}>
              <Field label="Push-to-talk hotkey (hold to talk)" value="Ctrl+Win" mono hint="Click, then hold your keys (default Ctrl+Win). Save, then restart to apply." />
              <Field label="Scratchpad hotkey (hold to dictate a note)" value="Ctrl+Alt+Win" mono hint="Appends dictation to the scratchpad work-queue. Save, then restart to apply." />
            </div>
            <div style={{ ...fieldRow, marginTop: 14 }}>
              <Field label="Override hotkey (hold to apply Next Capture)" placeholder="Click to set hotkey" mono hint="Records one capture with the Next Capture override applied, then auto-resets. Unset by default. Save, then restart to apply." />
              <Select label="Tier" value="Ultra" options={["Ultra", "Standard", "Power"]} />
            </div>
            <div style={{ height: 14 }} />
            <Select label="Dictation language" value="English" options={["English", "Spanish", "German", "French", "Japanese"]} hint="English: Standard or Elite. The other 13 languages: the Elite engine only — the Standard engine is English-only and refuses other languages rather than mis-transcribing." />
            <div style={{ height: 8 }} />
            <ToggleRow label="Auto-detect spoken language" hint="Detects the language you speak each time (native Elite engine; the Standard engine stays English). When off, dictation uses the language selected above." checked={s.autodetect} onChange={t("autodetect")} />
            <Inset style={{ marginTop: 8 }}><ToggleRow label="Second-language hotkey (advanced)" hint="Off by default. When on, a second hold key dictates one capture in another language. Save, then restart to apply the hotkey." checked={s.secondlang} onChange={t("secondlang")} /></Inset>
            <div style={{ ...fieldRow, marginTop: 16 }}>
              <Field label="Max correction examples" value="8" mono hint="How many taught corrections are retrieved per dictation. Feeds the deterministic correction pass plus the file-backend few-shot prompt. Default 8." />
              <div>
                <Field label="Grammar model" value="rokkor-catalog-grmr-v3-llama3-2-3b-q4-k-m" mono hint="Managed in the Models tab, which verifies the model is downloaded and registered before switching, so grammar never silently falls back to rules." />
                <Notice tone="warning" style={{ marginTop: 10 }}>Recommended for your language: <code>flowscribe-qwen2.5-0.5b-v2_K_M.gguf</code>. Activate it in the <b>Models tab</b> to download and register it.</Notice>
              </div>
            </div>
          </div>
        </Section>

        {/* CLOUD PROVIDERS */}
        <Section title="Cloud providers (bring your own key)" desc="Optional hosted STT and grammar cleanup. Local stays the default; cloud is used only after you pick a provider and add its API key.">
          <Notice tone="warning" style={{ marginBottom: 18 }}><b>Cloud providers send your audio and/or text to that provider over the network.</b> Your microphone audio (for cloud STT) and/or your transcript text (for cloud cleanup) leaves this device and is processed by the selected provider under their terms. Keys are stored in your operating system's credential vault, never in ROKKOR's settings file.</Notice>
          <div style={{ ...fieldRow }}>
            <Select label="Speech-to-text provider" value="OpenAI" options={["OpenAI", "Groq", "Self-hosted (LAN)"]} hint="Add this provider's API key below — dictation refuses loudly until a key is configured (your audio is never sent without one)." />
            <Select label="Grammar cleanup provider" value="OpenRouter" options={["OpenRouter", "OpenAI", "Anthropic", "Gemini", "Groq"]} hint="Add this provider's API key below — cleanup falls back to local rules until a key is configured." />
          </div>
          <div style={{ font: "600 13.5px/1 var(--font-sans)", color: "var(--ink-900)", margin: "22px 0 12px" }}>API keys</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
            {["OpenAI", "Anthropic", "Gemini", "Groq", "OpenRouter", "Self-hosted (LAN)"].map((p) => (
              <Inset key={p}>
                <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
                  <span style={{ font: "600 15px/1 var(--font-sans)", color: "var(--ink-900)" }}>{p}</span>
                  <Badge tone="neutral">Not configured</Badge>
                </div>
                <div style={{ display: "flex", gap: 8, marginTop: 12 }}>
                  <input placeholder={`${p} API key`} style={{ flex: 1, height: 40, padding: "0 13px", background: "var(--card)", border: "1px solid var(--border-strong)", borderRadius: "var(--radius-md)", font: "400 13.5px/1 var(--font-sans)", color: "var(--ink-900)", outline: "none" }} />
                  <Button variant="outline" size="sm">Save</Button>
                  <Button variant="ghost" size="sm">Clear</Button>
                </div>
              </Inset>
            ))}
          </div>

          {/* Choose a model */}
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", margin: "24px 0 10px" }}>
            <span style={{ font: "600 17px/1 var(--font-sans)", color: "var(--ink-900)" }}>Choose a model</span>
            <Button variant="outline" size="sm" icon={<I.Refresh size={14} />}>Model</Button>
          </div>
          <div style={{ font: "13px/1 var(--font-mono)", color: "var(--ink-600)", marginBottom: 12 }}>Model: <span style={{ color: "var(--ink-900)" }}>nvidia/nemotron-3-nano-30b-a3b:free</span></div>
          <Notice tone="warning" style={{ marginBottom: 14 }}>Free models are rate-limited per day; pick a cheap paid model (e.g. <code>meta-llama/llama-3.1-8b-instruct</code>) if free ones are exhausted.</Notice>
          <div style={{ display: "flex", gap: 12, alignItems: "center", marginBottom: 12 }}>
            <label style={{ display: "flex", alignItems: "center", gap: 7, font: "400 13px/1 var(--font-sans)", color: "var(--ink-700, var(--ink-800))" }}><input type="checkbox" /> Free only</label>
            <div style={{ position: "relative", flex: 1 }}>
              <span style={{ position: "absolute", left: 11, top: "50%", transform: "translateY(-50%)", color: "var(--ink-400)" }}><I.Search size={15} /></span>
              <input placeholder="Search models…" style={{ width: "100%", height: 40, padding: "0 13px 0 34px", background: "var(--card)", border: "1px solid var(--border-strong)", borderRadius: "var(--radius-md)", font: "400 13.5px/1 var(--font-sans)", outline: "none" }} />
            </div>
          </div>
          <Inset style={{ padding: 0, maxHeight: 220, overflow: "hidden" }}>
            {[
              ["cohere/north-mini-code:free", "Cohere: North Mini Code (free)"],
              ["openrouter/free", "Free Models Router"],
              ["google/gemma-4-26b-a4b-it:free", "Google: Gemma 4 26B A4B (free)"],
              ["google/gemma-4-31b-it:free", "Google: Gemma 4 31B (free)"],
              ["google/lyria-3-clip-preview", "Google: Lyria 3 Clip Preview"],
            ].map(([id, name], i) => (
              <div key={id} style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "13px 16px", borderTop: i ? "1px solid var(--border)" : "none" }}>
                <div><div style={{ font: "500 13px/1.3 var(--font-mono)", color: "var(--ink-900)" }}>{id}</div><div style={{ font: "400 12px/1.3 var(--font-sans)", color: "var(--ink-500)", marginTop: 3 }}>{name}</div></div>
                <Badge tone="success">Free</Badge>
              </div>
            ))}
          </Inset>
          <div style={{ display: "flex", alignItems: "center", gap: 12, marginTop: 14 }}>
            <Button variant="outline" size="sm" disabled>Test connection</Button>
            <span style={{ font: "400 13px/1 var(--font-sans)", color: "var(--ink-500)" }}>Add an OpenRouter API key above to test.</span>
          </div>
        </Section>

        {/* MARKDOWN */}
        <Section title="Save transcripts as Markdown files" desc="Mirror every finished transcript to a folder as a Markdown file with YAML frontmatter — point it at an Obsidian or Logseq vault to keep a searchable, plain-text copy of everything you dictate.">
          <ToggleRow label="Save transcripts as Markdown files" checked={s.markdown} onChange={t("markdown")} />
          <Field label="Vault folder" placeholder="Choose a folder (e.g. your Obsidian or Logseq vault)" right={<Button variant="outline" size="sm" icon={<I.Folder size={15} />}>Choose folder…</Button>} hint="Each transcript is written as <id>-<slug>.md with id/created/app/tier frontmatter. Works great with Obsidian and Logseq vaults." style={{ marginTop: 8 }} />
          <div style={{ marginTop: 14 }}><Button variant="outline" size="sm" icon={<I.Refresh size={15} />} disabled>Rebuild from recent transcripts</Button></div>
        </Section>

        {/* RECORDING INDICATOR */}
        <Section icon={I.Volume} title="Recording Indicator">
          <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
            {[["show", "Show while recording"], ["always", "Always show"], ["never", "Never show"]].map(([id, label]) => (
              <RadioRow key={id} checked={s.indicator === id} label={label} onChange={() => setS((p) => ({ ...p, indicator: id }))} />
            ))}
          </div>
        </Section>

        {/* NEXT CAPTURE */}
        <Section title="Next Capture" desc="One-off overrides for your next dictation only. Not saved to settings; resets after one capture.">
          <ToggleRow label="Skip grammar (paste raw transcript)" checked={s.skipgrammar} onChange={t("skipgrammar")} />
          <div style={{ marginTop: 12, display: "flex", flexDirection: "column", gap: 16 }}>
            <Select label="Send to" value="Paste at cursor (default)" options={["Paste at cursor (default)", "Scratchpad", "Clipboard only"]} />
            <Select label="Tone override" value="Use active context" options={["Use active context", "Formal", "Casual", "Very casual"]} />
            <div><Button variant="outline" size="sm">Reset to defaults</Button></div>
          </div>
        </Section>

        {/* SYSTEM & STARTUP */}
        <Section title="System & startup" desc="Launch behavior and the local Ollama grammar service.">
          <ToggleRow label="Launch ROKKOR at system startup" checked={s.launch} onChange={t("launch")} />
          <ToggleRow label="Close to system tray" hint="Closing the window hides ROKKOR to the system tray instead of quitting, so your hotkeys keep working. Use the tray menu to reopen the window or quit." checked={s.tray} onChange={t("tray")} divider />
          <ToggleRow label="Check for updates on launch" checked={s.updates} onChange={t("updates")} divider />
          <div style={{ display: "flex", alignItems: "center", gap: 12, padding: "4px 0 12px" }}><Button variant="outline" size="sm">Check for updates</Button><span style={{ font: "400 13px/1 var(--font-sans)", color: "var(--ink-500)" }}>Best-effort. Updates are downloaded only when you choose Install.</span></div>
          <ToggleRow label="Mute other audio while dictating" hint="Silences music, video, and other playback the moment you start dictating and restores it when you finish. Windows only for now." checked={s.mute} onChange={t("mute")} divider />
          <ToggleRow label="Start the Ollama grammar service on launch" hint="Starts the rokkor-ollama Docker container so the grammar model is ready. Best-effort — if Docker isn't running, grammar falls back to rule-based. Save applies the auto-start preference on next launch." checked={s.ollama} onChange={t("ollama")} divider />
          <div style={{ display: "flex", alignItems: "center", gap: 14, paddingTop: 4 }}><Button variant="outline" size="sm">Start Ollama now</Button></div>
          <div style={{ display: "flex", gap: 16, marginTop: 12, font: "400 12.5px/1.4 var(--font-sans)" }}>
            <span style={{ color: "var(--success-600)" }}>Grammar backend: Running (Ollama · GPU)</span>
            <span style={{ color: "var(--ink-400)" }}>Active model 'rokkor-grammar v3' — personal grammar, low-latency GPU path</span>
          </div>
        </Section>

        {/* BACKUP & SYNC */}
        <Section title="Backup &amp; Sync" desc="Back up your portable brain (vocabulary, corrections, snippets, settings) to storage you own — a folder, an SFTP server, or your own Dropbox / Google Drive. There is no ROKKOR cloud; nothing is sent to us.">
          <ToggleRow label="Automatic scheduled backups" checked={s.autobackup} onChange={t("autobackup")} />
          <div style={{ marginTop: 10, display: "flex", flexDirection: "column", gap: 16 }}>
            <Select label="Destination" value="Local / network folder (UNC, SMB, iCloud Drive)" options={["Local / network folder (UNC, SMB, iCloud Drive)", "SFTP server", "Dropbox", "Google Drive"]} />
            <Field label="Folder path" placeholder="C:\\Users\\you\\Backups\\ROKKOR  or  \\\\server\\share\\rokkor" mono hint="A local path, a network share (UNC / SMB), or your iCloud Drive folder — all just paths. The folder is created if it doesn't exist." />
            <div style={{ display: "flex", alignItems: "flex-end", gap: 14 }}>
              <Field label="Backup every (hours)" value="24" mono style={{ width: 200 }} />
              <span style={{ font: "400 13px/1 var(--font-sans)", color: "var(--ink-500)", paddingBottom: 12 }}>Last backup: <b>6/19/2026, 6:00 AM</b></span>
            </div>
            <ToggleRow label="Include recordings &amp; training audio in backups" checked={s.includeaudio} onChange={t("includeaudio")} />
            <Notice tone="warning">Off by default. Your backups normally contain only the text brain. Turning this on copies your raw dictation audio and training pairs into the bundle — only do this if you trust the destination, since that audio then leaves this device.</Notice>
            <div style={{ display: "flex", gap: 10 }}>
              <Button variant="default">Back up now</Button>
              <Button variant="outline">Test connection</Button>
              <Button variant="outline">List &amp; restore…</Button>
            </div>
          </div>
        </Section>

        {/* PRIVACY */}
        <Section title="Privacy" desc="Local data retention. Everything stays on this device.">
          <ToggleRow label="Keep recordings &amp; corrections for calibration" hint="Stores your dictation audio and (raw, corrected) text pairs locally to power calibration and future improvements. Off by default. This data never leaves your device — there is no upload, sync, or telemetry. Turn it off any time; existing recordings stay until you delete them." checked={s.keepdata} onChange={t("keepdata")} />
          <Inset style={{ marginTop: 12 }}>
            <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
              <span style={{ font: "600 14px/1 var(--font-sans)", color: "var(--ink-900)" }}>Local data on this device</span>
              <span style={{ color: "var(--ink-400)" }}><I.Refresh size={15} /></span>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 16, marginTop: 14 }}>
              {[["4,812", "recordings"], ["2.1 GB", "audio on disk"], ["4,812", "transcripts"], ["342", "corrections"]].map(([v, l]) => (
                <div key={l}><div style={{ font: "600 18px/1 var(--font-serif)", color: "var(--ink-900)" }}>{v}</div><div style={{ font: "400 12.5px/1.3 var(--font-sans)", color: "var(--ink-500)", marginTop: 5 }}>{l}</div></div>
              ))}
            </div>
          </Inset>
          <Notice tone="danger" style={{ marginTop: 14, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16 }}>
            <span><b style={{ color: "var(--oxblood-700)", display: "block", marginBottom: 3 }}>Delete all local data</b>Permanently erases every recording, transcript, correction, calibration, and custom setting, and resets ROKKOR to defaults. This cannot be undone.</span>
            <span style={{ flex: "none" }}><Button variant="default" style={{ background: "var(--oxblood-500)" }}>Delete &amp; reset…</Button></span>
          </Notice>
        </Section>
      </div>
    </div>
  );
}

window.RokkorScreens = Object.assign(window.RokkorScreens || {}, { SettingsScreen });
