<script>
  import { onMount, onDestroy } from "svelte";
  import { invoke } from "@tauri-apps/api/core";
  import { listen } from "@tauri-apps/api/event";
  import { settings, saveSettings, profiles, saveProfiles, templates, saveTemplates, page, addProfileTaskList, removeProfileTaskList } from "$lib/stores/page.svelte.js";
  import Card from "$lib/components/Card.svelte";
  import Toggle from "$lib/components/Toggle.svelte";
  import SegmentedButton from "$lib/components/SegmentedButton.svelte";
  import HotkeyRecorder from "$lib/components/HotkeyRecorder.svelte";
  import ZonePicker from "$lib/components/ZonePicker.svelte";
  import AccessibilityControls from "$lib/components/AccessibilityControls.svelte";
  import { getPreferences, updatePreferences } from "$lib/stores/preferences.svelte.js";
  import { clampTextLines } from "$lib/utils/textMeasure.js";
  import { bodyPretextLineHeight, pretextFontShorthand } from "$lib/utils/accessibilityTypography.js";
  import { Check, ChevronRight } from "lucide-svelte";

  const prefs = getPreferences();

  let engineStatus = $state("Checking...");
  let engineOk = $state(false);
  let downloadedModels = $state([]);
  let runtimeCapabilities = $state(null);
  let downloadingModel = $state("");
  let downloadProgress = $state(0);
  let unlisten = null;
  let outputFolderEl = $state(null);
  let outputFolderWidth = $state(0);

  // Parakeet state
  let parakeetStatus = $state("Checking...");
  let parakeetOk = $state(false);

  // Audio device picker (Settings → Audio → Microphone)
  let audioDevices = $state([]);
  let audioDevicesError = $state(null);

  async function refreshAudioDevices() {
    audioDevicesError = null;
    try {
      audioDevices = await invoke("list_audio_devices");
    } catch (err) {
      audioDevicesError = "Could not enumerate audio devices: " + (err?.message || err);
      audioDevices = [];
    }
  }

  // --- Custom vocabulary (dictionary) — Day 5 of upgrade plan ---
  // Backed by SQLite `dictionary` table via list_dictionary_command etc.
  // Terms get injected into the LLM cleanup prompt so the model preserves
  // the user's spellings (e.g. medication names, jargon, place names).
  let vocabulary = $state([]);
  let vocabularyError = $state(null);
  let newVocabTerm = $state("");
  let newVocabNote = $state("");

  async function refreshVocabulary() {
    vocabularyError = null;
    try {
      vocabulary = await invoke("list_dictionary_command");
    } catch (err) {
      vocabularyError = "Could not load vocabulary: " + (err?.message || err);
    }
  }

  async function addVocabTerm() {
    const term = newVocabTerm.trim();
    if (!term) return;
    try {
      await invoke("add_dictionary_entry_command", {
        term,
        note: newVocabNote.trim() || null,
      });
      newVocabTerm = "";
      newVocabNote = "";
      await refreshVocabulary();
    } catch (err) {
      vocabularyError = "Could not save term: " + (err?.message || err);
    }
  }

  async function deleteVocabTerm(id) {
    try {
      await invoke("delete_dictionary_entry_command", { id });
      await refreshVocabulary();
    } catch (err) {
      vocabularyError = "Could not delete term: " + (err?.message || err);
    }
  }

  // --- Diagnostics (Settings → About → Generate diagnostic report) ---
  // Layer 2 of the diagnostics plan: user previews exactly what would be
  // shared, then chooses to copy / save. Nothing leaves the machine
  // automatically.
  let diagnosticReport = $state("");
  let diagnosticReportError = $state(null);
  let diagnosticReportSavedTo = $state(null);
  let diagnosticReportLoading = $state(false);

  async function generateDiagnosticReport() {
    diagnosticReportError = null;
    diagnosticReportSavedTo = null;
    diagnosticReportLoading = true;
    try {
      diagnosticReport = await invoke("generate_diagnostic_report", {
        options: {
          includeRecentErrors: true,
          includeCrashes: true,
          includeSettings: true,
          includeLogTail: true,
        },
      });
    } catch (err) {
      diagnosticReportError = "Could not generate report: " + (err?.message || err);
    } finally {
      diagnosticReportLoading = false;
    }
  }

  async function copyDiagnosticReport() {
    if (!diagnosticReport) return;
    try {
      await navigator.clipboard.writeText(diagnosticReport);
      diagnosticReportSavedTo = "Copied to clipboard.";
    } catch (err) {
      diagnosticReportError = "Clipboard copy failed: " + (err?.message || err);
    }
  }

  async function saveDiagnosticReport() {
    diagnosticReportError = null;
    try {
      const path = await invoke("save_diagnostic_report", {
        options: {
          includeRecentErrors: true,
          includeCrashes: true,
          includeSettings: true,
          includeLogTail: true,
        },
      });
      diagnosticReportSavedTo = "Saved to " + path;
    } catch (err) {
      diagnosticReportError = "Save failed: " + (err?.message || err);
    }
  }

  let parakeetDownloaded = $state(false);
  let parakeetDownloading = $state(false);
  let parakeetProgress = $state(0);
  let unlistenParakeet = null;

  // Profiles & Templates
  let showProfiles = $state(false);
  let showTemplates = $state(false);
  let editingProfile = $state(-1);
  let editingTemplate = $state(-1);
  let newProfileName = $state("");
  let newTemplateName = $state("");
  let showNewProfile = $state(false);
  let showNewTemplate = $state(false);

  // Accordion state — first section open by default
  let openSection = $state('transcription');
  let settingsTextFont = $derived(pretextFontShorthand(prefs.accessibility, 11));
  let settingsPathLineHeight = $derived(bodyPretextLineHeight(prefs.accessibility, 11));
  let outputFolderPreview = $derived.by(() => {
    const text = settings.outputFolder || "Default (app data)";
    if (!text) return "";
    if (outputFolderWidth <= 0) {
      return text.length > 80 ? `${text.slice(0, 79)}…` : text;
    }
    return clampTextLines(
      text,
      settingsTextFont,
      Math.max(120, outputFolderWidth - 24),
      settingsPathLineHeight,
      2,
    ).text;
  });

  function whisperModelId(size) {
    const map = {
      Tiny: "whisper-tiny-en",
      Base: "whisper-base-en",
      Small: "whisper-small-en",
      Medium: "whisper-medium-en",
    };
    return map[size] || "whisper-base-en";
  }

  function selectedModelId() {
    return settings.engine === "parakeet"
      ? "parakeet-ctc-0.6b-int8"
      : whisperModelId(settings.modelSize);
  }

  function engineCapabilities(engineId) {
    return runtimeCapabilities?.engines?.find((engine) => engine.id === engineId) || null;
  }

  function selectedModelCapabilities() {
    return engineCapabilities(settings.engine)?.models?.find((model) => model.id === selectedModelId()) || null;
  }

  function whisperModelCapabilities(size) {
    return engineCapabilities("whisper")?.models?.find((model) => model.id === whisperModelId(size)) || null;
  }

  function currentModelIsEnglishOnly() {
    return selectedModelCapabilities()?.languageSupport?.kind === "english-only";
  }

  function hasGpuAcceleration() {
    return (runtimeCapabilities?.accelerators || []).some((accelerator) => accelerator !== "cpu");
  }

  async function refreshRuntimeCapabilities() {
    runtimeCapabilities = await invoke("get_runtime_capabilities");
  }

  onMount(async () => {
    try {
      await refreshRuntimeCapabilities();
      const loaded = await invoke("check_engine");
      engineOk = loaded;
      engineStatus = loaded ? "Model loaded" : "No model loaded";
    } catch {
      engineStatus = "Engine not ready";
    }

    // Populate audio device list so the Microphone picker is ready when
    // the user opens the Audio section.
    refreshAudioDevices();

    // Pre-load vocabulary too. Both lists are small; pre-fetching avoids
    // a flash of "no data" when the section opens.
    refreshVocabulary();

    try {
      downloadedModels = await invoke("list_models");
    } catch {}

    // Parakeet status
    try {
      parakeetOk = await invoke("check_parakeet_engine");
      parakeetDownloaded = await invoke("check_parakeet_model", { name: "ctc-int8" });
      parakeetStatus = parakeetOk ? "Model loaded" : parakeetDownloaded ? "Downloaded (not loaded)" : "Not downloaded";
    } catch {
      parakeetStatus = "Engine not ready";
    }

    unlisten = await listen("model-download-progress", (event) => {
      downloadProgress = event.payload.percent || event.payload.progress || 0;
    });

    unlistenParakeet = await listen("parakeet-download-progress", (event) => {
      parakeetProgress = event.payload.percent || event.payload.progress || 0;
    });
  });

  onDestroy(() => {
    if (unlisten) unlisten();
    if (unlistenParakeet) unlistenParakeet();
  });

  $effect(() => {
    if (!outputFolderEl) return;
    const ro = new ResizeObserver((entries) => {
      for (const entry of entries) {
        outputFolderWidth = entry.contentRect.width;
      }
    });
    ro.observe(outputFolderEl);
    return () => ro.disconnect();
  });

  // Auto-save on any settings change.
  // JSON.stringify subscribes to all properties on the reactive object.
  // Safe because `settings` only holds persistent preferences — no ephemeral state.
  $effect(() => {
    void JSON.stringify(settings);
    saveSettings();
  });


  $effect(() => {
    settings.engine;
    settings.modelSize;
    if (currentModelIsEnglishOnly() && settings.language !== "en") {
      settings.language = "en";
    }
    if (!hasGpuAcceleration() && settings.device !== "auto") {
      settings.device = "auto";
    }
  });

  async function downloadModel(size) {
    downloadingModel = size;
    downloadProgress = 0;
    try {
      await invoke("download_model", { size });
      downloadedModels = await invoke("list_models");
      await refreshRuntimeCapabilities();
      downloadingModel = "";
    } catch (err) {
      downloadingModel = "";
      engineStatus = typeof err === "string" ? err : "Download failed";
    }
  }

  async function loadSelectedModel() {
    const size = settings.modelSize.toLowerCase();
    engineStatus = "Loading...";
    engineOk = false;
    try {
      await invoke("load_model", { size });
      await refreshRuntimeCapabilities();
      engineOk = true;
      engineStatus = `${settings.modelSize} model loaded`;
    } catch (err) {
      engineOk = false;
      engineStatus = typeof err === "string" ? err : "Load failed";
    }
  }

  function isModelDownloaded(size) {
    const runtimeModel = whisperModelCapabilities(size);
    if (runtimeModel) {
      return runtimeModel.downloaded;
    }
    return downloadedModels.some((model) => model.toLowerCase() === size.toLowerCase());
  }

  function isModelLoaded(size) {
    const runtimeModel = whisperModelCapabilities(size);
    if (runtimeModel) {
      return runtimeModel.loaded;
    }
    return runtimeCapabilities?.engines?.some(
      (engine) => engine.id === "whisper" && engine.loadedModelId === whisperModelId(size),
    ) || false;
  }

  const modelDescriptions = {
    Tiny: "~75MB · fastest, lower accuracy",
    Base: "~150MB · balanced for most use",
    Small: "~500MB · noticeably more accurate",
    Medium: "~1.5GB · best quality, slower",
  };

  async function downloadParakeet() {
    parakeetDownloading = true;
    parakeetProgress = 0;
    try {
      await invoke("download_parakeet_model", { name: "ctc-int8" });
      await refreshRuntimeCapabilities();
      parakeetDownloaded = true;
      parakeetDownloading = false;
      parakeetStatus = "Downloaded (not loaded)";
    } catch (err) {
      parakeetDownloading = false;
      parakeetStatus = typeof err === "string" ? err : "Download failed";
    }
  }

  async function loadParakeet() {
    parakeetStatus = "Loading...";
    parakeetOk = false;
    try {
      await invoke("load_parakeet_model", { name: "ctc-int8" });
      await refreshRuntimeCapabilities();
      parakeetOk = true;
      parakeetStatus = "Model loaded";
    } catch (err) {
      parakeetOk = false;
      parakeetStatus = typeof err === "string" ? err : "Load failed";
    }
  }

  // --- Profile management ---
  function createProfile() {
    if (!newProfileName.trim()) return;
    const name = newProfileName.trim();
    profiles.push({ name, words: "" });
    saveProfiles();
    addProfileTaskList(name);
    newProfileName = "";
    showNewProfile = false;
    editingProfile = profiles.length - 1;
  }

  function deleteProfile(index) {
    const name = profiles[index].name;
    if (page.activeProfile === name) {
      page.activeProfile = "None";
    }
    removeProfileTaskList(name);
    profiles.splice(index, 1);
    saveProfiles();
    editingProfile = -1;
  }

  function profileWordCount(words) {
    return words ? words.split("\n").filter((w) => w.trim()).length : 0;
  }

  // --- Template management ---
  function createTemplate() {
    if (!newTemplateName.trim()) return;
    templates.push({ name: newTemplateName.trim(), sections: ["Section 1", "Section 2", "Section 3"] });
    saveTemplates();
    newTemplateName = "";
    showNewTemplate = false;
    editingTemplate = templates.length - 1;
  }

  function deleteTemplate(index) {
    templates.splice(index, 1);
    saveTemplates();
    editingTemplate = -1;
  }
</script>

<div class="flex flex-col h-full overflow-y-auto animate-fade-in">
  <!-- Title -->
  <h2 class="font-display text-[26px] italic text-text px-7 pt-6 pb-5">Settings</h2>

  <div class="px-7 pb-8">
    <Card>
      <!-- Audio (microphone selection) -->
      <div class="border-b border-border-subtle">
        <button
          class="flex items-center justify-between w-full py-4 px-5 text-left"
          onclick={() => openSection = openSection === 'audio' ? null : 'audio'}
        >
          <h3 class="font-display text-[18px] italic text-text">Audio</h3>
          <span class="text-text-tertiary text-[16px] leading-none">{openSection === 'audio' ? '−' : '+'}</span>
        </button>
        {#if openSection === 'audio'}
          <div class="px-5 pb-5 animate-fade-in">
            <div class="mb-6">
              <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">Microphone</p>
              <div class="flex items-center gap-3">
                <select
                  class="bg-bg-input border border-border rounded-lg px-3 py-2 text-[13px] text-text
                         focus:outline-none focus:border-accent focus:shadow-[0_0_0_3px_rgba(232,168,124,0.1)]
                         appearance-none cursor-pointer min-w-[280px] max-w-full"
                  bind:value={settings.microphoneDevice}
                  onfocus={refreshAudioDevices}
                >
                  <option value="">Auto (recommended) — let Kon pick the working mic</option>
                  {#each audioDevices as dev}
                    <option value={dev.name} disabled={dev.is_likely_monitor}>
                      {dev.name}
                      {dev.is_default ? " (system default)" : ""}
                      {dev.is_likely_monitor ? " — speaker monitor, skip" : ""}
                    </option>
                  {/each}
                </select>
                <button
                  class="px-3 py-2 text-[12px] text-text-secondary border border-border rounded-lg hover:border-accent hover:text-text"
                  onclick={refreshAudioDevices}
                  type="button"
                >Refresh</button>
              </div>
              {#if audioDevicesError}
                <p class="text-[11px] text-error mt-2">{audioDevicesError}</p>
              {:else if audioDevices.length === 0}
                <p class="text-[11px] text-text-tertiary mt-2">No input devices detected. Check that a microphone is connected and PulseAudio/PipeWire is running.</p>
              {:else}
                <p class="text-[11px] text-text-tertiary mt-2">
                  Auto mode tries the system default first, then any other real input. Speaker-monitor sources (loopback) are skipped because they record system audio rather than the microphone. If dictation is silent, pick the device explicitly here.
                </p>
              {/if}
            </div>
          </div>
        {/if}
      </div>

      <!-- Vocabulary (custom dictionary injected into LLM cleanup prompt) -->
      <div class="border-b border-border-subtle">
        <button
          class="flex items-center justify-between w-full py-4 px-5 text-left"
          onclick={() => openSection = openSection === 'vocabulary' ? null : 'vocabulary'}
        >
          <h3 class="font-display text-[18px] italic text-text">Vocabulary</h3>
          <span class="text-text-tertiary text-[16px] leading-none">{openSection === 'vocabulary' ? '−' : '+'}</span>
        </button>
        {#if openSection === 'vocabulary'}
          <div class="px-5 pb-5 animate-fade-in">
            <p class="text-[12px] text-text-tertiary mb-4">
              Words and phrases the AI cleanup pass should preserve exactly. Useful for medication names, place names, jargon, names of people in your support network, anything Whisper tends to mishear.
            </p>

            <div class="flex gap-2 mb-4">
              <input
                type="text"
                placeholder="Term (e.g. methylphenidate, Wren, Tartarus)"
                bind:value={newVocabTerm}
                onkeydown={(e) => { if (e.key === 'Enter') addVocabTerm(); }}
                class="flex-1 bg-bg-input border border-border rounded-lg px-3 py-2 text-[13px] text-text
                       focus:outline-none focus:border-accent focus:shadow-[0_0_0_3px_rgba(232,168,124,0.1)]"
              />
              <input
                type="text"
                placeholder="Note (optional)"
                bind:value={newVocabNote}
                onkeydown={(e) => { if (e.key === 'Enter') addVocabTerm(); }}
                class="flex-1 bg-bg-input border border-border rounded-lg px-3 py-2 text-[13px] text-text
                       focus:outline-none focus:border-accent focus:shadow-[0_0_0_3px_rgba(232,168,124,0.1)]"
              />
              <button
                type="button"
                onclick={addVocabTerm}
                disabled={!newVocabTerm.trim()}
                class="px-4 py-2 text-[13px] bg-accent text-bg rounded-lg disabled:opacity-50 disabled:cursor-not-allowed hover:bg-accent-hover"
              >Add</button>
            </div>

            {#if vocabularyError}
              <p class="text-[11px] text-error mb-3">{vocabularyError}</p>
            {/if}

            {#if vocabulary.length === 0}
              <p class="text-[11px] text-text-tertiary italic">No terms yet. Add one above.</p>
            {:else}
              <ul class="space-y-1">
                {#each vocabulary as entry (entry.id)}
                  <li class="flex items-center gap-3 py-2 px-3 bg-bg-input border border-border rounded-lg">
                    <div class="flex-1 min-w-0">
                      <div class="text-[13px] text-text font-medium truncate">{entry.term}</div>
                      {#if entry.note}
                        <div class="text-[11px] text-text-tertiary truncate">{entry.note}</div>
                      {/if}
                    </div>
                    <button
                      type="button"
                      onclick={() => deleteVocabTerm(entry.id)}
                      class="text-[12px] text-text-tertiary hover:text-error border border-border hover:border-error rounded px-2 py-1"
                      aria-label="Delete {entry.term}"
                    >Remove</button>
                  </li>
                {/each}
              </ul>
            {/if}
          </div>
        {/if}
      </div>

      <!-- Transcription -->
      <div class="border-b border-border-subtle">
        <button
          class="flex items-center justify-between w-full py-4 px-5 text-left"
          onclick={() => openSection = openSection === 'transcription' ? null : 'transcription'}
        >
          <h3 class="font-display text-[18px] italic text-text">Transcription</h3>
          <span class="text-text-tertiary text-[16px] leading-none">{openSection === 'transcription' ? '−' : '+'}</span>
        </button>
        {#if openSection === 'transcription'}
          <div class="px-5 pb-5 animate-fade-in">

            <!-- Engine selector -->
            <div class="mb-6">
              <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">Engine</p>
              <SegmentedButton options={["whisper", "parakeet"]} bind:value={settings.engine} />
              <p class="text-[11px] text-text-tertiary mt-2">
                {settings.engine === "whisper"
                  ? "Whisper with the currently shipped English-only models in this build"
                  : "Parakeet CTC 0.6B — English-only, fast when the model is installed"}
              </p>
            </div>

            <!-- Format mode -->
            <div class="mb-6">
              <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">Format Mode</p>
              <SegmentedButton options={["Raw", "Clean", "Smart"]} bind:value={settings.formatMode} />
              <p class="text-[11px] text-text-tertiary mt-2">
                {settings.formatMode === "Raw" ? "Exact Whisper output, no formatting" :
                 settings.formatMode === "Clean" ? "Grouped into paragraphs, punctuation tidied" :
                 "Structured with lists, headings, and sections"}
              </p>
            </div>

            <!-- Engine-specific model management -->
            {#if settings.engine === "whisper"}
              <div class="mb-6">
                <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">Whisper Model</p>
                <SegmentedButton options={["Tiny", "Base", "Small", "Medium"]} bind:value={settings.modelSize} />
                <p class="text-[11px] text-text-tertiary mt-2">{modelDescriptions[settings.modelSize]}</p>

                <div class="flex items-center gap-2 mt-3">
                  {#if isModelLoaded(settings.modelSize)}
                    <span class="inline-flex items-center gap-1.5 text-[11px] text-success">
                      <span class="w-[6px] h-[6px] rounded-full bg-success"></span>
                      Model loaded
                    </span>
                  {:else if isModelDownloaded(settings.modelSize)}
                    <span class="inline-flex items-center gap-1.5 text-[11px] text-success">
                      <span class="w-[6px] h-[6px] rounded-full bg-success"></span>
                      Downloaded
                    </span>
                    <button
                      class="text-[11px] text-text-tertiary hover:text-accent"
                      onclick={loadSelectedModel}
                    >Load model</button>
                  {:else if downloadingModel === settings.modelSize.toLowerCase()}
                    <span class="text-[11px] text-warning">{downloadProgress}% downloading...</span>
                  {:else}
                    <button
                      class="text-[11px] text-accent hover:text-accent-hover"
                      onclick={() => downloadModel(settings.modelSize.toLowerCase())}
                    >Download {settings.modelSize}</button>
                  {/if}
                </div>
              </div>
            {:else}
              <div class="mb-6">
                <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">Parakeet Model</p>
                <p class="text-[11px] text-text-tertiary mb-3">Parakeet CTC 0.6B (int8) — ~613MB, near-instant transcription</p>

                <div class="flex items-center gap-2">
                  {#if parakeetOk}
                    <span class="inline-flex items-center gap-1.5 text-[11px] text-success">
                      <span class="w-[6px] h-[6px] rounded-full bg-success"></span>
                      Model loaded
                    </span>
                  {:else if parakeetDownloaded}
                    <span class="inline-flex items-center gap-1.5 text-[11px] text-text-secondary">
                      <span class="w-[6px] h-[6px] rounded-full bg-text-tertiary"></span>
                      Downloaded
                    </span>
                    <button
                      class="text-[11px] text-text-tertiary hover:text-accent"
                      onclick={loadParakeet}
                    >Load model</button>
                  {:else if parakeetDownloading}
                    <span class="text-[11px] text-warning">{parakeetProgress}% downloading...</span>
                  {:else}
                    <button
                      class="text-[11px] text-accent hover:text-accent-hover"
                      onclick={downloadParakeet}
                    >Download Parakeet</button>
                  {/if}
                </div>
              </div>
            {/if}

            <!-- Compute device -->
            <div class="mb-6">
              <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">Compute Device</p>
              {#if hasGpuAcceleration()}
                <select
                  class="bg-bg-input border border-border rounded-lg px-3 py-2 text-[13px] text-text
                         focus:outline-none focus:border-accent focus:shadow-[0_0_0_3px_rgba(232,168,124,0.1)]
                         appearance-none cursor-pointer w-[220px]"
                  bind:value={settings.device}
                >
                  <option value="auto">Auto</option>
                  {#if runtimeCapabilities?.accelerators?.includes("cuda")}
                    <option value="cuda">CUDA (NVIDIA GPU)</option>
                  {/if}
                  {#if runtimeCapabilities?.accelerators?.includes("metal")}
                    <option value="metal">Metal (Apple GPU)</option>
                  {/if}
                  {#if runtimeCapabilities?.accelerators?.includes("vulkan")}
                    <option value="vulkan">Vulkan</option>
                  {/if}
                  <option value="cpu">CPU</option>
                </select>
                <p class="text-[11px] text-text-tertiary mt-2">Only accelerators built into this binary are shown here.</p>
              {:else}
                <div class="bg-bg-input border border-border rounded-lg px-3 py-2 text-[13px] text-text w-[320px]">
                  This build is CPU-only. GPU controls appear in GPU-enabled builds.
                </div>
              {/if}
            </div>

            <!-- Language -->
            <div>
              <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">Language</p>
              <div class="flex items-center gap-3">
                {#if currentModelIsEnglishOnly()}
                  <select
                    class="bg-bg-input border border-border rounded-lg px-3 py-2 text-[13px] text-text
                           focus:outline-none focus:border-accent focus:shadow-[0_0_0_3px_rgba(232,168,124,0.1)]
                           appearance-none cursor-not-allowed w-[220px]"
                    bind:value={settings.language}
                    disabled
                  >
                    <option value="en">English only</option>
                  </select>
                {:else}
                  <select
                    class="bg-bg-input border border-border rounded-lg px-3 py-2 text-[13px] text-text
                           focus:outline-none focus:border-accent focus:shadow-[0_0_0_3px_rgba(232,168,124,0.1)]
                           appearance-none cursor-pointer w-[140px]"
                    bind:value={settings.language}
                  >
                    <option value="en">English</option>
                    <option value="auto">Auto-detect</option>
                    <option value="fr">French</option>
                    <option value="de">German</option>
                    <option value="es">Spanish</option>
                    <option value="it">Italian</option>
                    <option value="pt">Portuguese</option>
                    <option value="nl">Dutch</option>
                    <option value="pl">Polish</option>
                    <option value="ja">Japanese</option>
                    <option value="ko">Korean</option>
                    <option value="zh">Chinese</option>
                  </select>
                {/if}
                {#if settings.language === "en"}
                  <button
                    class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-full text-[11px] border animate-fade-in
                      {settings.britishEnglish
                        ? 'bg-accent/10 border-accent/30 text-accent font-medium'
                        : 'bg-bg-input border-border text-text-tertiary hover:text-text-secondary'}"
                    onclick={() => { settings.britishEnglish = !settings.britishEnglish; }}
                    title={settings.britishEnglish ? "British English spelling active" : "Click to enable British English spelling"}
                  >
                    {#if settings.britishEnglish}
                      <Check class="w-3 h-3" strokeWidth={2.5} />
                    {/if}
                    British English
                  </button>
                {/if}
              </div>
              <p class="text-[11px] text-text-tertiary mt-2">
                {#if currentModelIsEnglishOnly()}
                  The selected model only supports English in this build.
                {:else}
                  Auto-detect is only meaningful with multilingual models.
                {/if}
              </p>
            </div>
          </div>
        {/if}
      </div>

      <!-- Processing -->
      <div class="border-b border-border-subtle">
        <button
          class="flex items-center justify-between w-full py-4 px-5 text-left"
          onclick={() => openSection = openSection === 'processing' ? null : 'processing'}
        >
          <h3 class="font-display text-[18px] italic text-text">Processing</h3>
          <span class="text-text-tertiary text-[16px] leading-none">{openSection === 'processing' ? '−' : '+'}</span>
        </button>
        {#if openSection === 'processing'}
          <div class="px-5 pb-5 animate-fade-in">
            <div class="space-y-0.5">
              <Toggle
                bind:checked={settings.removeFillers}
                label="Remove filler words"
                description="Strips um, uh, like, you know from output"
              />
              <Toggle
                bind:checked={settings.antiHallucination}
                label="Anti-hallucination shield"
                description="Detects phantom phrases Whisper generates during silence"
              />
            </div>
          </div>
        {/if}
      </div>

      <!-- AI Assistant -->
      <div class="border-b border-border-subtle">
        <button
          class="flex items-center justify-between w-full py-4 px-5 text-left"
          onclick={() => openSection = openSection === 'ai' ? null : 'ai'}
        >
          <h3 class="font-display text-[18px] italic text-text">AI Assistant</h3>
          <span class="text-text-tertiary text-[16px] leading-none">{openSection === 'ai' ? '−' : '+'}</span>
        </button>
        {#if openSection === 'ai'}
          <div class="px-5 pb-5 animate-fade-in">
            <p class="text-[11px] text-text-tertiary mb-4">Local LLM for smart task extraction, transcript cleanup, and formatting. Runs 100% offline.</p>
            <div class="bg-bg-input rounded-lg px-3 py-2.5 border border-border-subtle">
              <p class="text-[12px] text-text-secondary font-medium mb-1">Coming soon</p>
              <p class="text-[11px] text-text-tertiary">AI-powered cleanup and smart extraction are being rebuilt with a faster engine. Task extraction currently uses rule-based matching, which runs automatically after each recording.</p>
            </div>
          </div>
        {/if}
      </div>

      <!-- Profiles & Templates -->
      <div class="border-b border-border-subtle">
        <button
          class="flex items-center justify-between w-full py-4 px-5 text-left"
          onclick={() => openSection = openSection === 'profiles' ? null : 'profiles'}
        >
          <h3 class="font-display text-[18px] italic text-text">Profiles & Templates</h3>
          <span class="text-text-tertiary text-[16px] leading-none">{openSection === 'profiles' ? '−' : '+'}</span>
        </button>
        {#if openSection === 'profiles'}
          <div class="px-5 pb-5 animate-fade-in">
            <!-- Profiles section -->
            <button
              class="flex items-center gap-2 w-full text-left mb-1"
              onclick={() => showProfiles = !showProfiles}
            >
              <ChevronRight class="w-3 h-3 text-text-tertiary transition-transform duration-[var(--duration-ui)] {showProfiles ? 'rotate-90' : ''}" />
              <h3 class="text-[14px] font-semibold text-text">Profiles</h3>
              <span class="text-[10px] px-1.5 py-0.5 rounded-full bg-bg-elevated text-text-tertiary">
                {profiles.length}
              </span>
            </button>
            <p class="text-[11px] text-text-tertiary mb-3 ml-5">Custom vocabulary to improve transcription accuracy</p>

            {#if showProfiles}
              <div class="space-y-1.5 animate-fade-in ml-5">
                {#each profiles as profile, i}
                  <div class="group">
                    <div class="flex items-center gap-2 bg-bg-input rounded-lg px-3 h-[36px]">
                      <span class="text-[12px] text-text flex-1 truncate">{profile.name}</span>
                      <span class="text-[10px] px-1.5 py-0.5 rounded-full bg-bg-elevated text-text-tertiary">
                        {profileWordCount(profile.words)} words
                      </span>
                      <button
                        class="text-[10px] text-text-tertiary hover:text-accent opacity-0 group-hover:opacity-100"
                        onclick={() => editingProfile = editingProfile === i ? -1 : i}
                      >{editingProfile === i ? "Close" : "Edit"}</button>
                      <button
                        class="text-[10px] text-text-tertiary hover:text-danger opacity-0 group-hover:opacity-100"
                        onclick={() => deleteProfile(i)}
                      >Delete</button>
                    </div>
                    {#if editingProfile === i}
                      <div class="mt-1.5 animate-fade-in">
	                        <textarea
	                          class="w-full h-[120px] bg-bg-elevated border border-border-subtle rounded-lg px-3 py-2
	                                 text-[12px] text-text resize-none
	                                 focus:outline-none focus:border-accent"
                          placeholder="One word or phrase per line..."
                          bind:value={profile.words}
                          oninput={() => saveProfiles()}
                          data-no-transition
                        ></textarea>
                      </div>
                    {/if}
                  </div>
                {/each}

                {#if showNewProfile}
                  <div class="flex items-center gap-2 animate-fade-in">
                    <input
                      class="flex-1 bg-bg-input border border-border rounded-lg px-3 py-1.5 text-[12px] text-text
                             placeholder:text-text-tertiary focus:outline-none focus:border-accent"
                      placeholder="Profile name..."
                      bind:value={newProfileName}
                      onkeydown={(e) => e.key === "Enter" && createProfile()}
                      data-no-transition
                    />
                    <button class="text-[11px] text-accent hover:text-accent-hover" onclick={createProfile}>Create</button>
                    <button class="text-[11px] text-text-tertiary" onclick={() => { showNewProfile = false; newProfileName = ""; }}>Cancel</button>
                  </div>
                {:else}
                  <button class="text-[12px] text-accent hover:text-accent-hover" onclick={() => showNewProfile = true}>+ Add profile</button>
                {/if}
              </div>
            {/if}

            <div class="my-4 h-px bg-border-subtle"></div>

            <!-- Templates section -->
            <button
              class="flex items-center gap-2 w-full text-left mb-1"
              onclick={() => showTemplates = !showTemplates}
            >
              <ChevronRight class="w-3 h-3 text-text-tertiary transition-transform duration-[var(--duration-ui)] {showTemplates ? 'rotate-90' : ''}" />
              <h3 class="text-[14px] font-semibold text-text">Templates</h3>
              <span class="text-[10px] px-1.5 py-0.5 rounded-full bg-bg-elevated text-text-tertiary">
                {templates.length}
              </span>
            </button>
            <p class="text-[11px] text-text-tertiary mb-3 ml-5">Structured formats for dictation sessions</p>

            {#if showTemplates}
              <div class="space-y-1.5 animate-fade-in ml-5">
                {#each templates as template, i}
                  <div class="group">
                    <div class="flex items-center gap-2 bg-bg-input rounded-lg px-3 h-[36px]">
                      <span class="text-[12px] text-text flex-1 truncate">{template.name}</span>
                      <span class="text-[10px] px-1.5 py-0.5 rounded-full bg-bg-elevated text-text-tertiary">
                        {template.sections.length} sections
                      </span>
                      <button
                        class="text-[10px] text-text-tertiary hover:text-accent opacity-0 group-hover:opacity-100"
                        onclick={() => editingTemplate = editingTemplate === i ? -1 : i}
                      >{editingTemplate === i ? "Close" : "Edit"}</button>
                      <button
                        class="text-[10px] text-text-tertiary hover:text-danger opacity-0 group-hover:opacity-100"
                        onclick={() => deleteTemplate(i)}
                      >Delete</button>
                    </div>
                    {#if editingTemplate === i}
                      <div class="mt-1.5 animate-fade-in">
	                        <textarea
	                          class="w-full h-[100px] bg-bg-elevated border border-border-subtle rounded-lg px-3 py-2
	                                 text-[12px] text-text resize-none
	                                 focus:outline-none focus:border-accent"
                          placeholder="One section per line..."
                          value={template.sections.join("\n")}
                          oninput={(e) => { template.sections = e.target.value.split("\n").filter((s) => s.trim()); saveTemplates(); }}
                          data-no-transition
                        ></textarea>
                      </div>
                    {/if}
                  </div>
                {/each}

                {#if showNewTemplate}
                  <div class="flex items-center gap-2 animate-fade-in">
                    <input
                      class="flex-1 bg-bg-input border border-border rounded-lg px-3 py-1.5 text-[12px] text-text
                             placeholder:text-text-tertiary focus:outline-none focus:border-accent"
                      placeholder="Template name..."
                      bind:value={newTemplateName}
                      onkeydown={(e) => e.key === "Enter" && createTemplate()}
                      data-no-transition
                    />
                    <button class="text-[11px] text-accent hover:text-accent-hover" onclick={createTemplate}>Create</button>
                    <button class="text-[11px] text-text-tertiary" onclick={() => { showNewTemplate = false; newTemplateName = ""; }}>Cancel</button>
                  </div>
                {:else}
                  <button class="text-[12px] text-accent hover:text-accent-hover" onclick={() => showNewTemplate = true}>+ Add template</button>
                {/if}
              </div>
            {/if}
          </div>
        {/if}
      </div>

      <!-- Output -->
      <div class="border-b border-border-subtle">
        <button
          class="flex items-center justify-between w-full py-4 px-5 text-left"
          onclick={() => openSection = openSection === 'output' ? null : 'output'}
        >
          <h3 class="font-display text-[18px] italic text-text">Output</h3>
          <span class="text-text-tertiary text-[16px] leading-none">{openSection === 'output' ? '−' : '+'}</span>
        </button>
        {#if openSection === 'output'}
          <div class="px-5 pb-5 animate-fade-in">
            <div class="space-y-0.5">
              <Toggle bind:checked={settings.autoCopy} label="Auto-copy to clipboard" />
              <Toggle bind:checked={settings.includeTimestamps} label="Include timestamps in exports" />
              <Toggle
                bind:checked={settings.saveAudio}
                label="Save audio recordings"
                description="Saves raw audio as .wav files (~2MB per minute). Stored locally."
              />
              {#if settings.saveAudio}
                <div class="ml-[50px] mt-2 animate-fade-in">
	                  <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-1.5">Output Folder</p>
	                  <div class="flex items-center gap-2">
	                    <div bind:this={outputFolderEl} class="flex-1 bg-bg-input rounded-lg px-3 py-1.5 border border-border-subtle">
	                      <p class="text-[11px] text-text-secondary whitespace-pre-wrap break-words" style="line-height: {settingsPathLineHeight}px" title={settings.outputFolder || "Default (app data)"}>
	                        {outputFolderPreview}
	                      </p>
	                    </div>
                    <button
                      class="text-[11px] text-accent hover:text-accent-hover whitespace-nowrap"
                      onclick={async () => {
                        try {
                          const folder = await open({ directory: true, title: "Select output folder" });
                          if (folder) { settings.outputFolder = folder; saveSettings(); }
                        } catch {}
                      }}
                    >Change</button>
                    {#if settings.outputFolder}
                      <button
                        class="text-[11px] text-text-tertiary hover:text-text-secondary whitespace-nowrap"
                        onclick={() => { settings.outputFolder = ""; saveSettings(); }}
                      >Reset</button>
                    {/if}
                  </div>
                </div>
              {/if}
            </div>
          </div>
        {/if}
      </div>

      <!-- Hotkey -->
      <div class="border-b border-border-subtle">
        <button
          class="flex items-center justify-between w-full py-4 px-5 text-left"
          onclick={() => openSection = openSection === 'hotkey' ? null : 'hotkey'}
        >
          <h3 class="font-display text-[18px] italic text-text">Global Hotkey</h3>
          <span class="text-text-tertiary text-[16px] leading-none">{openSection === 'hotkey' ? '−' : '+'}</span>
        </button>
        {#if openSection === 'hotkey'}
          <div class="px-5 pb-5 animate-fade-in">
            <p class="text-[11px] text-text-tertiary mb-4">Toggle recording from anywhere. Click to change.</p>
            <HotkeyRecorder />
          </div>
        {/if}
      </div>

      <!-- Appearance -->
      <div class="border-b border-border-subtle">
        <button
          class="flex items-center justify-between w-full py-4 px-5 text-left"
          onclick={() => openSection = openSection === 'appearance' ? null : 'appearance'}
        >
          <h3 class="font-display text-[18px] italic text-text">Appearance</h3>
          <span class="text-text-tertiary text-[16px] leading-none">{openSection === 'appearance' ? '−' : '+'}</span>
        </button>
        {#if openSection === 'appearance'}
          <div class="px-5 pb-5 animate-fade-in">
            <div class="mb-6">
              <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">Theme</p>
              <SegmentedButton options={["Dark", "Light", "System"]} bind:value={settings.theme} />
            </div>

            <div class="mb-6">
              <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">Zone</p>
              <ZonePicker />
            </div>

            <div class="mb-6">
              <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">
                Font Size <span class="font-normal text-text-secondary ml-1">{settings.fontSize}px</span>
              </p>
              <input
                type="range" min="10" max="24" step="1"
                bind:value={settings.fontSize}
                class="w-[200px] accent-accent"
                data-no-transition
              />
            </div>
          </div>
        {/if}
      </div>

      <!-- Accessibility -->
      <div class="border-b border-border-subtle">
        <button
          class="flex items-center justify-between w-full py-4 px-5 text-left"
          onclick={() => openSection = openSection === 'accessibility' ? null : 'accessibility'}
        >
          <h3 class="font-display text-[18px] italic text-text">Accessibility</h3>
          <span class="text-text-tertiary text-[16px] leading-none">{openSection === 'accessibility' ? '−' : '+'}</span>
        </button>
        {#if openSection === 'accessibility'}
          <div class="px-5 pb-5 animate-fade-in">
            <AccessibilityControls />
          </div>
        {/if}
      </div>

      <!-- About -->
      <div>
        <button
          class="flex items-center justify-between w-full py-4 px-5 text-left"
          onclick={() => openSection = openSection === 'about' ? null : 'about'}
        >
          <h3 class="font-display text-[18px] italic text-text">About</h3>
          <span class="text-text-tertiary text-[16px] leading-none">{openSection === 'about' ? '−' : '+'}</span>
        </button>
        {#if openSection === 'about'}
          <div class="px-5 pb-5 animate-fade-in">
            <!-- Engine status -->
            <div class="flex items-center gap-2 mb-4">
              <span class="w-[7px] h-[7px] rounded-full {engineOk ? 'bg-success' : 'bg-warning'}"></span>
              <span class="text-[12px] text-text-secondary">{engineStatus}</span>
            </div>

            <div class="space-y-1.5">
              {#each [
                "100% offline — all processing on your machine",
                "No Python required — compiled Whisper engine",
                "No cloud — audio never leaves your computer",
                "No accounts — no sign-up, no tracking",
                "No telemetry — zero data collection",
              ] as item}
                <div class="flex items-start gap-2">
                  <Check class="w-3.5 h-3.5 text-success mt-0.5 flex-shrink-0" />
                  <p class="text-[11px] text-text-secondary">{item}</p>
                </div>
              {/each}
            </div>

            <p class="text-[11px] text-text-tertiary mt-5">Kon v1.0 · Powered by whisper.cpp · Built by CORBEL Ltd</p>

            <!-- Diagnostic report (privacy posture: local only until you share it) -->
            <div class="mt-6 pt-5 border-t border-border-subtle">
              <p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">Diagnostics</p>
              <p class="text-[11px] text-text-tertiary mb-3">
                If something goes wrong, generate a diagnostic report to share with the developer. The report contains your settings, recent errors, any crash dumps, and the tail of the log file. Nothing is sent automatically — you preview it first, then choose copy or save.
              </p>
              <div class="flex gap-2 mb-3">
                <button
                  type="button"
                  onclick={generateDiagnosticReport}
                  disabled={diagnosticReportLoading}
                  class="px-3 py-2 text-[12px] bg-accent text-bg rounded-lg disabled:opacity-50 hover:bg-accent-hover"
                >{diagnosticReportLoading ? "Generating…" : "Generate report"}</button>
                {#if diagnosticReport}
                  <button
                    type="button"
                    onclick={copyDiagnosticReport}
                    class="px-3 py-2 text-[12px] text-text border border-border rounded-lg hover:border-accent hover:text-accent"
                  >Copy to clipboard</button>
                  <button
                    type="button"
                    onclick={saveDiagnosticReport}
                    class="px-3 py-2 text-[12px] text-text border border-border rounded-lg hover:border-accent hover:text-accent"
                  >Save as file</button>
                {/if}
              </div>
              {#if diagnosticReportError}
                <p class="text-[11px] text-error mb-2">{diagnosticReportError}</p>
              {/if}
              {#if diagnosticReportSavedTo}
                <p class="text-[11px] text-success mb-2">{diagnosticReportSavedTo}</p>
              {/if}
              {#if diagnosticReport}
                <details class="text-[11px]">
                  <summary class="cursor-pointer text-text-secondary hover:text-text">Preview report ({diagnosticReport.length} chars)</summary>
                  <pre class="mt-2 p-3 bg-bg-input border border-border rounded-lg text-[10px] text-text-secondary overflow-auto max-h-[400px] whitespace-pre-wrap font-mono">{diagnosticReport}</pre>
                </details>
              {/if}
            </div>
          </div>
        {/if}
      </div>
    </Card>
  </div>
</div>
