const defaultState = () => ({
  theme: "light",
  showShortcuts: false,
  showStatus: true,
  statusTheme: "paper-light",
  welcomeHintShown: false,
  hasDocument: true,
  checklistName: "",
  documentPath: "",
  documentCreatedAt: 0,
  documentUpdatedAt: 0,
  tasks: [],
});

const STATUS_THEMES = [
  { id: "pda-blue", label: "PDA blue" },
  { id: "paper-light", label: "Black on white" },
  { id: "inverse-dark", label: "White on black" },
  { id: "dos-green", label: "DOS green" },
  { id: "hyperpop-pink", label: "Hyperpop pink" },
];

let state = defaultState();
let searchQuery = "";
let visibleTaskIds = [];
let selectedTaskId = null;
let editingTaskId = null;
let draggedTaskId = null;
let activeDropRow = null;
let saveTimer = null;
let periodicSaveIntervalId = null;
let pendingTaskInputFocusId = null;
let voiceMessage = "Mic off";
let isListening = false;
let speechRecognition = null;
let speechBaseText = "";
let speechFinalText = "";
let micStream = null;
let micAudioContext = null;
let micAnalyser = null;
let micMeterData = null;
let micLevel = 0;
let micReady = false;
let micMeterFrameId = null;
let historyStack = [];
let showWelcomeHint = false;
let utilityLayoutFrameId = null;
let utilityResizeObserver = null;
let lastWindowLayoutMode = null;
let isEditingChecklistTitle = false;
let checklistTitleDraft = "";
let checklistRenameInFlight = false;

const UTILITY_DENSITIES = [
  { id: "default", searchPlaceholder: "Search tasks" },
  { id: "compact", searchPlaceholder: "Search tasks" },
  { id: "tight", searchPlaceholder: "Search" },
  { id: "micro", searchPlaceholder: "Search" },
  { id: "nano", searchPlaceholder: "Search" },
];

const elements = {
  checklistTitle: null,
  checklistTitleInput: null,
  taskCounter: null,
  windowBar: null,
  themeToggle: null,
  quickAddForm: null,
  quickAddInput: null,
  voiceButton: null,
  addButton: null,
  utilityRow: null,
  utilityMain: null,
  hideHintsButton: null,
  searchShell: null,
  searchInput: null,
  shortcutViewport: null,
  statusRadio: null,
  statusTicker: null,
  voiceStatus: null,
  voiceStatusClone: null,
  shortcutStrip: null,
  taskTree: null,
  emptyState: null,
};

document.addEventListener("DOMContentLoaded", () => {
  cacheElements();
  bindStaticEvents();
  bootstrap().catch((error) => {
    console.error(error);
    voiceMessage = "App failed to load cleanly";
    render();
  });
});

function cacheElements() {
  elements.checklistTitle = document.getElementById("checklistTitle");
  elements.checklistTitleInput = document.getElementById("checklistTitleInput");
  elements.taskCounter = document.getElementById("taskCounter");
  elements.windowBar = document.getElementById("windowBar");
  elements.themeToggle = document.getElementById("themeToggle");
  elements.quickAddForm = document.getElementById("quickAddForm");
  elements.quickAddInput = document.getElementById("quickAddInput");
  elements.voiceButton = document.getElementById("voiceButton");
  elements.addButton = document.getElementById("addButton");
  elements.utilityRow = document.getElementById("utilityRow");
  elements.utilityMain = document.getElementById("utilityMain");
  elements.hideHintsButton = document.getElementById("hideHintsButton");
  elements.searchShell = document.getElementById("searchShell");
  elements.searchInput = document.getElementById("searchInput");
  elements.shortcutViewport = document.getElementById("shortcutViewport");
  elements.statusRadio = document.getElementById("statusRadio");
  elements.statusTicker = document.getElementById("statusTicker");
  elements.voiceStatus = document.getElementById("voiceStatus");
  elements.voiceStatusClone = document.getElementById("voiceStatusClone");
  elements.shortcutStrip = document.getElementById("shortcutStrip");
  elements.taskTree = document.getElementById("taskTree");
  elements.emptyState = document.getElementById("emptyState");
}

function bindStaticEvents() {
  elements.checklistTitle.addEventListener("click", () => {
    startChecklistRename();
  });

  elements.checklistTitleInput.addEventListener("keydown", (event) => {
    if (event.key === "Enter") {
      event.preventDefault();
      void commitChecklistRename();
    } else if (event.key === "Escape") {
      event.preventDefault();
      cancelChecklistRename();
    }
  });

  elements.checklistTitleInput.addEventListener("input", () => {
    checklistTitleDraft = elements.checklistTitleInput.value;
  });

  elements.checklistTitleInput.addEventListener("blur", () => {
    if (isEditingChecklistTitle) {
      void commitChecklistRename();
    }
  });

  elements.quickAddForm.addEventListener("submit", (event) => {
    event.preventDefault();
    addTaskFromComposer();
  });

  elements.quickAddInput.addEventListener("input", () => {
    syncComposerControls();
  });

  elements.quickAddInput.addEventListener("keydown", (event) => {
    if (event.key === "Enter" && !event.shiftKey) {
      event.preventDefault();
      addTaskFromComposer();
    } else if (event.key === "Escape") {
      if (elements.quickAddInput.value) {
        elements.quickAddInput.value = "";
        syncComposerControls();
      } else {
        clearSelection();
      }
    }
  });

  elements.searchInput.addEventListener("input", () => {
    searchQuery = elements.searchInput.value.trim();
    render();
  });

  elements.voiceButton.addEventListener("click", () => {
    void toggleVoiceInput();
  });

  elements.themeToggle.addEventListener("click", () => {
    toggleTheme();
  });

  elements.statusRadio.addEventListener("click", () => {
    cycleStatusTheme();
  });

  elements.hideHintsButton.addEventListener("click", () => {
    toggleShortcutHints();
  });

  elements.taskTree.addEventListener("dragover", (event) => {
    if (!draggedTaskId || searchQuery) {
      return;
    }

    event.preventDefault();
    if (!event.target.closest(".task-main")) {
      elements.taskTree.classList.add("is-root-drop");
      clearDropIndicator();
    }
  });

  elements.taskTree.addEventListener("drop", (event) => {
    if (!draggedTaskId || searchQuery) {
      return;
    }

    event.preventDefault();
    elements.taskTree.classList.remove("is-root-drop");
    if (!event.target.closest(".task-main")) {
      moveTaskToRoot(draggedTaskId);
      draggedTaskId = null;
      clearDropIndicator();
      render();
    }
  });

  elements.taskTree.addEventListener("dragleave", (event) => {
    if (!event.relatedTarget || !elements.taskTree.contains(event.relatedTarget)) {
      elements.taskTree.classList.remove("is-root-drop");
      clearDropIndicator();
    }
  });

  document.addEventListener("keydown", handleGlobalKeydown, { capture: true });
  window.addEventListener("resize", queueUtilityLayoutSync);

  window.addEventListener("beforeunload", () => {
    disposeVoiceInput();
    void saveState();
  });
}

async function bootstrap() {
  state = sanitizeState(await loadState());
  ensureTaskIds(state.tasks);
  historyStack = [];
  if (!state.welcomeHintShown) {
    showWelcomeHint = true;
    state.welcomeHintShown = true;
    voiceMessage = "Press CTRL H.";
  }
  setupVoiceInput();
  setupUtilityLayoutObserver();
  ensurePeriodicSaveLoop();
  render();
  focusComposer();
}

async function loadState() {
  const browserDebugState = getDebugStateFromUrl();
  if (browserDebugState) {
    return browserDebugState;
  }

  const api = await waitForBridge();
  if (!api || typeof api.load_state !== "function") {
    return defaultState();
  }

  try {
    return await api.load_state();
  } catch (error) {
    console.error("Failed to load state", error);
    return defaultState();
  }
}

function waitForBridge() {
  return new Promise((resolve) => {
    if (window.pywebview && window.pywebview.api) {
      resolve(window.pywebview.api);
      return;
    }

    let settled = false;

    const finish = () => {
      if (settled) {
        return;
      }
      settled = true;
      resolve(window.pywebview ? window.pywebview.api : null);
    };

    window.addEventListener("pywebviewready", finish, { once: true });
    window.setTimeout(finish, 800);
  });
}

function getDebugStateFromUrl() {
  try {
    const params = new URLSearchParams(window.location.search);
    const encoded = params.get("debugState");
    if (!encoded) {
      return null;
    }

    const normalized = encoded.replace(/-/g, "+").replace(/_/g, "/");
    const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=");
    const json = atob(padded);
    return sanitizeState(JSON.parse(json));
  } catch (error) {
    console.error("Invalid debug state", error);
    return null;
  }
}

function sanitizeState(rawState) {
  const theme = rawState && rawState.theme === "dark" ? "dark" : "light";
  const showShortcuts = typeof rawState?.showShortcuts === "boolean" ? rawState.showShortcuts : false;
  const showStatus = typeof rawState?.showStatus === "boolean" ? rawState.showStatus : true;
  const statusTheme = STATUS_THEMES.some((themeOption) => themeOption.id === rawState?.statusTheme)
    ? rawState.statusTheme
    : "paper-light";
  const welcomeHintShown = typeof rawState?.welcomeHintShown === "boolean" ? rawState.welcomeHintShown : false;
  const documentPath = typeof rawState?.documentPath === "string" ? rawState.documentPath : "";
  const checklistName = typeof rawState?.checklistName === "string" && rawState.checklistName.trim()
    ? rawState.checklistName.trim()
    : "Checklist";
  const documentCreatedAt = Number.isFinite(rawState?.documentCreatedAt) ? Number(rawState.documentCreatedAt) : 0;
  const documentUpdatedAt = Number.isFinite(rawState?.documentUpdatedAt) ? Number(rawState.documentUpdatedAt) : 0;
  const tasks = Array.isArray(rawState?.tasks) ? rawState.tasks.map(sanitizeTask) : [];
  return {
    theme,
    showShortcuts,
    showStatus,
    statusTheme,
    welcomeHintShown,
    hasDocument: true,
    checklistName,
    documentPath,
    documentCreatedAt,
    documentUpdatedAt,
    tasks,
  };
}

function sanitizeTask(task) {
  const progress = Math.max(0, Math.min(100, Number.parseInt(task?.progress ?? 0, 10) || 0));
  const createdAt = Number.isFinite(task?.created_at) ? Number(task.created_at) : Date.now();
  const children = Array.isArray(task?.children) ? task.children.map(sanitizeTask) : [];
  return {
    id: typeof task?.id === "string" && task.id ? task.id : createId(),
    text: typeof task?.text === "string" ? task.text : "",
    done: Boolean(task?.done),
    progress,
    created_at: createdAt,
    collapsed: children.length > 0 ? Boolean(task?.collapsed) : false,
    children,
  };
}

function ensureTaskIds(tasks) {
  for (const task of tasks) {
    if (!task.id) {
      task.id = createId();
    }
    ensureTaskIds(task.children);
  }
}

function createId() {
  if (window.crypto && typeof window.crypto.randomUUID === "function") {
    return window.crypto.randomUUID();
  }
  return `task-${Date.now()}-${Math.random().toString(16).slice(2)}`;
}

function render() {
  document.body.dataset.theme = state.theme;
  document.body.classList.toggle("is-hints-hidden", !state.showShortcuts);
  elements.checklistTitle.textContent = state.checklistName || "Checklist";
  elements.checklistTitle.hidden = isEditingChecklistTitle;
  elements.checklistTitleInput.hidden = !isEditingChecklistTitle;
  if (isEditingChecklistTitle) {
    elements.checklistTitleInput.value = checklistTitleDraft || state.checklistName || "Checklist";
  }
  elements.windowBar.hidden = !state.showShortcuts;
  elements.utilityRow.hidden = !state.showShortcuts;
  elements.addButton.hidden = !state.showShortcuts;
  elements.taskCounter.textContent = `${countOpenTasks(state.tasks)} open`;
  const targetTheme = state.theme === "dark" ? "light" : "dark";
  elements.themeToggle.querySelectorAll(".theme-choice").forEach((option) => {
    option.classList.toggle("is-active", option.dataset.themeOption === state.theme);
  });
  elements.themeToggle.setAttribute("aria-label", `Current theme ${state.theme}. Click to switch to ${targetTheme}.`);
  elements.themeToggle.dataset.targetTheme = targetTheme;
  const statusDisplay = `STATUS: ${getStatusDisplay()}`;
  elements.voiceStatus.textContent = statusDisplay;
  elements.voiceStatusClone.textContent = statusDisplay;
  elements.statusRadio.hidden = !state.showStatus;
  elements.statusRadio.style.display = state.showStatus ? "" : "none";
  elements.statusRadio.dataset.statusTheme = state.statusTheme;
  elements.statusRadio.title = getStatusTitle();
  elements.shortcutStrip.hidden = !state.showShortcuts;
  elements.quickAddInput.placeholder = getComposerPlaceholder();
  syncVoiceChrome();
  syncStatusTicker();
  void syncWindowLayout(state.showShortcuts);
  queueUtilityLayoutSync();
  syncComposerControls();

  elements.taskTree.innerHTML = "";
  elements.taskTree.classList.remove("is-root-drop");

  const { tasks: filteredTasks } = filterTasks(state.tasks, searchQuery);
  visibleTaskIds = flattenTaskIds(filteredTasks, { includeCollapsedChildren: Boolean(searchQuery) });
  const selectedIsVisible = !selectedTaskId || visibleTaskIds.includes(selectedTaskId);

  if (filteredTasks.length === 0) {
    elements.emptyState.classList.remove("is-hidden");
  } else {
    elements.emptyState.classList.add("is-hidden");
  }

  for (const task of filteredTasks) {
    elements.taskTree.appendChild(renderTask(task, selectedIsVisible));
  }

  restoreEditingFocus();
}

function getComposerPlaceholder() {
  if (isListening) {
    return state.showShortcuts ? "Speak your task" : "";
  }

  if (state.showShortcuts) {
    return "Type a task and hit Enter";
  }

  return "Type a task. Press CTRL H.";
}

function startChecklistRename() {
  if (isEditingChecklistTitle || !state.checklistName) {
    return;
  }

  isEditingChecklistTitle = true;
  checklistTitleDraft = state.checklistName;
  render();
  requestAnimationFrame(() => {
    elements.checklistTitleInput.focus();
    elements.checklistTitleInput.select();
  });
}

function cancelChecklistRename() {
  isEditingChecklistTitle = false;
  checklistTitleDraft = "";
  render();
}

async function commitChecklistRename() {
  if (!isEditingChecklistTitle || checklistRenameInFlight) {
    return;
  }

  const requestedName = (elements.checklistTitleInput.value || "").trim();
  const fallbackName = state.checklistName || "Checklist";
  const nextName = requestedName || fallbackName;

  isEditingChecklistTitle = false;
  checklistTitleDraft = "";

  if (nextName === state.checklistName) {
    render();
    return;
  }

  checklistRenameInFlight = true;

  try {
    const api = await waitForBridge();
    if (api && typeof api.rename_checklist === "function") {
      state = sanitizeState(await api.rename_checklist(nextName, state));
    } else {
      state.checklistName = nextName;
      scheduleSave();
    }
    voiceMessage = `${state.checklistName} ready`;
  } catch (error) {
    console.error("Failed to rename checklist", error);
    voiceMessage = "Checklist rename hit a snag";
  } finally {
    checklistRenameInFlight = false;
    render();
    focusComposer();
  }
}

async function createNewChecklist() {
  const api = await waitForBridge();
  if (!api || typeof api.create_checklist !== "function") {
    return;
  }

  await saveState();
  const nextState = sanitizeState(await api.create_checklist("Checklist"));
  state = nextState;
  historyStack = [];
  searchQuery = "";
  selectedTaskId = null;
  editingTaskId = null;
  isEditingChecklistTitle = false;
  checklistTitleDraft = "";
  showWelcomeHint = false;
  voiceMessage = `${state.checklistName} ready`;
  render();
  focusComposer();
}

function setupUtilityLayoutObserver() {
  if (!elements.utilityMain) {
    return;
  }

  if (utilityResizeObserver) {
    utilityResizeObserver.disconnect();
  }

  if (typeof ResizeObserver === "function") {
    utilityResizeObserver = new ResizeObserver(() => {
      queueUtilityLayoutSync();
    });
    utilityResizeObserver.observe(elements.utilityMain);
  }
}

async function syncWindowLayout(showWideLayout = state.showShortcuts, force = false) {
  if (!force && lastWindowLayoutMode === showWideLayout) {
    return;
  }

  lastWindowLayoutMode = showWideLayout;
  const api = await waitForBridge();
  if (!api || typeof api.sync_window_layout !== "function") {
    return;
  }

  try {
    await api.sync_window_layout(showWideLayout);
  } catch (error) {
    console.error("Failed to sync window layout", error);
  }
}

function queueUtilityLayoutSync() {
  if (utilityLayoutFrameId) {
    window.cancelAnimationFrame(utilityLayoutFrameId);
  }

  utilityLayoutFrameId = window.requestAnimationFrame(() => {
    utilityLayoutFrameId = null;
    syncUtilityLayout();
  });
}

function syncUtilityLayout() {
  if (
    !elements.utilityMain ||
    !elements.searchInput ||
    !elements.searchShell ||
    !elements.shortcutViewport ||
    !elements.shortcutStrip ||
    !state.showShortcuts ||
    elements.utilityRow.hidden
  ) {
    return;
  }

  let chosenDensity = UTILITY_DENSITIES[UTILITY_DENSITIES.length - 1];
  let chosenScale = 1;

  for (const density of UTILITY_DENSITIES) {
    applyUtilityDensity(density);
    const nextScale = getShortcutScale();
    chosenDensity = density;
    chosenScale = nextScale;
    if (nextScale >= getShortcutScaleTarget(density.id)) {
      break;
    }
  }

  elements.searchInput.placeholder = chosenDensity.searchPlaceholder;
  elements.shortcutViewport.style.setProperty("--shortcut-scale", `${chosenScale}`);
  elements.shortcutViewport.dataset.scaled = chosenScale < 0.999 ? "true" : "false";
}

function applyUtilityDensity(density) {
  elements.utilityMain.dataset.density = density.id;
}

function getShortcutScale() {
  const viewportWidth = Math.floor(elements.shortcutViewport.clientWidth);
  const stripWidth = Math.ceil(elements.shortcutStrip.scrollWidth);
  if (!viewportWidth || !stripWidth) {
    return 1;
  }

  return Math.min(1, viewportWidth / stripWidth);
}

function getShortcutScaleTarget(densityId) {
  switch (densityId) {
    case "default":
      return 1;
    case "compact":
      return 1;
    case "tight":
      return 1;
    case "micro":
      return 0.94;
    default:
      return 0.86;
  }
}

function syncStatusTicker() {
  if (!elements.statusTicker || !elements.voiceStatus || !elements.voiceStatusClone || !elements.statusRadio) {
    return;
  }

  const text = elements.voiceStatus.textContent ?? "";
  elements.voiceStatusClone.textContent = text;

  if (elements.statusRadio.hidden || !text) {
    elements.statusTicker.classList.remove("is-scrolling");
    elements.statusTicker.style.removeProperty("--ticker-distance");
    elements.statusTicker.style.removeProperty("--ticker-duration");
    return;
  }

  requestAnimationFrame(() => {
    const visibleWidth = elements.statusRadio.querySelector(".status-screen")?.clientWidth ?? 0;
    const textWidth = Math.ceil(elements.voiceStatus.scrollWidth);
    const needsScroll = textWidth > visibleWidth - 8;

    elements.statusTicker.classList.toggle("is-scrolling", needsScroll);

    if (!needsScroll) {
      elements.statusTicker.style.removeProperty("--ticker-distance");
      elements.statusTicker.style.removeProperty("--ticker-duration");
      return;
    }

    const gap = 22;
    const distance = textWidth + gap;
    const duration = Math.max(6, distance / 22);
    elements.statusTicker.style.setProperty("--ticker-distance", `${distance}px`);
    elements.statusTicker.style.setProperty("--ticker-duration", `${duration}s`);
  });
}

function cloneSerializable(value) {
  if (typeof structuredClone === "function") {
    return structuredClone(value);
  }
  return JSON.parse(JSON.stringify(value));
}

function pushHistory() {
  historyStack.push({
    state: cloneSerializable(state),
    selectedTaskId,
  });

  if (historyStack.length > 160) {
    historyStack.shift();
  }
}

function syncComposerControls() {
  const hasText = Boolean(elements.quickAddInput.value.trim());
  elements.addButton.disabled = !hasText;
  syncComposerLayout();
}

function syncComposerLayout() {
  const input = elements.quickAddInput;
  input.style.height = "0px";
  const minHeight = 52;
  const maxHeight = 148;
  const nextHeight = Math.min(Math.max(input.scrollHeight, minHeight), maxHeight);
  input.style.height = `${nextHeight}px`;
}

function renderTask(task, selectedIsVisible) {
  const wrapper = document.createElement("article");
  wrapper.className = "task-item";
  const hasChildren = task.children.length > 0;
  wrapper.classList.toggle("is-parent-task", hasChildren);
  wrapper.classList.toggle("is-collapsed", hasChildren && task.collapsed);

  const main = document.createElement("div");
  main.className = "task-main";
  main.draggable = !searchQuery;
  main.classList.toggle("is-draggable", !searchQuery);
  main.classList.toggle("is-collapsible", hasChildren);
  main.classList.toggle("is-collapsed", hasChildren && task.collapsed);
  main.dataset.taskId = task.id;
  main.setAttribute("role", "button");
  main.tabIndex = -1;

  const visualProgress = getVisualProgress(task);
  if (task.done) {
    main.classList.add("is-done");
  }
  if (selectedIsVisible && selectedTaskId === task.id) {
    main.classList.add("is-selected");
  }
  if (draggedTaskId === task.id) {
    main.classList.add("is-dragging");
  }

  const progressWash = document.createElement("div");
  progressWash.className = "task-progress-wash";
  progressWash.style.setProperty("--progress-width", `${visualProgress}%`);
  progressWash.style.setProperty("--progress-color", getProgressColor(visualProgress));

  main.addEventListener("click", (event) => {
    if (event.target.closest(".task-toggle") || event.target.closest(".task-remove")) {
      return;
    }

    if (hasChildren && selectedTaskId === task.id && editingTaskId !== task.id && event.detail === 1) {
      toggleTaskCollapsed(task.id);
      return;
    }

    selectTask(task.id);
  });

  main.addEventListener("dblclick", (event) => {
    if (event.target.closest(".task-toggle") || event.target.closest(".task-remove")) {
      return;
    }
    startEditingTask(task.id);
  });

  main.addEventListener("dragstart", (event) => {
    if (searchQuery) {
      event.preventDefault();
      return;
    }

    draggedTaskId = task.id;
    document.body.classList.add("is-dragging-task");
    selectTask(task.id, { rerender: false });
    main.classList.add("is-dragging");
    event.dataTransfer.effectAllowed = "move";
    event.dataTransfer.setData("text/plain", task.id);
  });

  main.addEventListener("dragend", () => {
    draggedTaskId = null;
    document.body.classList.remove("is-dragging-task");
    elements.taskTree.classList.remove("is-root-drop");
    clearDropIndicator();
    render();
  });

  main.addEventListener("dragover", (event) => {
    if (!draggedTaskId || searchQuery) {
      return;
    }

    event.preventDefault();
    event.dataTransfer.dropEffect = "move";

    const position = getDropPosition(main, event.clientY);
    if (!canMoveTask(draggedTaskId, task.id, position)) {
      clearDropIndicator();
      return;
    }

    elements.taskTree.classList.remove("is-root-drop");
    setDropIndicator(main, position);
  });

  main.addEventListener("dragleave", (event) => {
    if (!main.contains(event.relatedTarget)) {
      clearDropIndicator();
    }
  });

  main.addEventListener("drop", (event) => {
    if (!draggedTaskId || searchQuery) {
      return;
    }

    event.preventDefault();
    const position = getDropPosition(main, event.clientY);
    if (moveTask(draggedTaskId, task.id, position)) {
      draggedTaskId = null;
      clearDropIndicator();
      render();
    }
  });

  const toggleButton = document.createElement("button");
  toggleButton.className = "task-toggle";
  toggleButton.type = "button";
  toggleButton.ariaLabel = task.done ? "Mark task active" : "Mark task done";
  toggleButton.addEventListener("click", () => {
    toggleTaskDone(task.id);
  });

  const content = document.createElement("div");
  content.className = "task-content";
  content.classList.toggle("is-leaf", !hasChildren);

  if (editingTaskId === task.id) {
    const editInput = document.createElement("input");
    editInput.className = "task-edit-input";
    editInput.type = "text";
    editInput.value = task.text;
    editInput.dataset.taskEditId = task.id;

    editInput.addEventListener("keydown", (event) => {
      if (event.key === "Enter") {
        event.preventDefault();
        commitEditingTask(task.id, editInput.value);
      } else if (event.key === "Escape") {
        event.preventDefault();
        cancelEditingTask();
      } else if (event.key === "Tab") {
        event.preventDefault();
        commitEditingTask(task.id, editInput.value, { rerender: false });
        if (event.shiftKey) {
          outdentTask(task.id);
        } else {
          moveTaskLevel(task.id);
        }
        render();
      }
    });

    editInput.addEventListener("blur", () => {
      commitEditingTask(task.id, editInput.value);
    });

    content.appendChild(editInput);
  } else {
    const label = document.createElement("span");
    label.className = "task-label";
    label.textContent = task.text;
    content.appendChild(label);
  }

  const progressBadge = document.createElement("span");
  progressBadge.className = "task-progress-badge";
  if (visualProgress === 0) {
    progressBadge.classList.add("is-hidden");
    progressBadge.textContent = "0%";
  } else {
    progressBadge.textContent = `${visualProgress}%`;
  }

  const removeButton = document.createElement("button");
  removeButton.className = "task-remove";
  removeButton.type = "button";
  removeButton.textContent = "x";
  removeButton.ariaLabel = "Delete task";
  removeButton.addEventListener("click", () => {
    removeTask(task.id);
  });

  const createdAt = document.createElement("span");
  createdAt.className = "task-created-at";
  createdAt.textContent = formatTaskTimestamp(task.created_at);

  main.append(progressWash, toggleButton, content, createdAt, progressBadge, removeButton);
  wrapper.appendChild(main);

  if (hasChildren && (!task.collapsed || searchQuery)) {
    const children = document.createElement("div");
    children.className = "task-children";
    for (const child of task.children) {
      children.appendChild(renderTask(child, selectedIsVisible));
    }
    wrapper.appendChild(children);
  }

  return wrapper;
}

function addTaskFromComposer() {
  const tasks = createTasksFromText(elements.quickAddInput.value);
  if (tasks.length === 0) {
    return;
  }

  pushHistory();
  state.tasks = tasks.concat(state.tasks);
  selectedTaskId = tasks[0].id;
  editingTaskId = null;
  elements.quickAddInput.value = "";
  voiceMessage = tasks.length === 1 ? "Task added" : `${tasks.length} tasks added`;
  syncComposerControls();
  scheduleSave();
  render();
  focusComposer();
}

function normalizeTaskText(text) {
  return String(text ?? "")
    .replace(/^\s*(?:[-*•]\s+|\d+[.)]\s+|\[\s?[xX]?\s?\]\s+)/, "")
    .replace(/\s+/g, " ")
    .replace(/[.]+$/, "")
    .trim();
}

function createTasksFromText(text) {
  return String(text ?? "")
    .split(/\r?\n/)
    .map((line) => normalizeTaskText(line))
    .filter(Boolean)
    .map((line) => ({
      id: createId(),
      text: line,
      done: false,
      progress: 0,
      created_at: Date.now(),
      collapsed: false,
      children: [],
    }));
}

function toggleTaskDone(taskId) {
  const meta = findTaskMeta(state.tasks, taskId);
  if (!meta) {
    return;
  }

  pushHistory();
  meta.task.done = !meta.task.done;
  selectedTaskId = taskId;
  voiceMessage = meta.task.done ? "Task crossed off" : "Task reopened";
  scheduleSave();
  render();
}

function incrementProgress(taskId) {
  const meta = findTaskMeta(state.tasks, taskId);
  if (!meta) {
    return;
  }

  pushHistory();
  meta.task.progress = Math.min(100, meta.task.progress + 10);
  if (meta.task.progress >= 100) {
    meta.task.done = true;
  }
  selectedTaskId = taskId;
  voiceMessage = `Progress ${meta.task.progress}%`;
  scheduleSave();
  render();
}

function decrementProgress(taskId) {
  const meta = findTaskMeta(state.tasks, taskId);
  if (!meta) {
    return;
  }

  const currentProgress = meta.task.done ? 100 : meta.task.progress;
  if (currentProgress <= 0) {
    voiceMessage = "Progress already 0%";
    render();
    return;
  }

  pushHistory();
  meta.task.progress = Math.max(0, currentProgress - 10);
  meta.task.done = meta.task.progress >= 100;
  selectedTaskId = taskId;
  voiceMessage = `Progress ${meta.task.progress}%`;
  scheduleSave();
  render();
}

function getVisualProgress(task) {
  return task.done ? 100 : task.progress;
}

function getProgressColor(progress) {
  if (!progress) {
    return "transparent";
  }

  let hue = 8;
  if (progress <= 50) {
    hue = 8 + (progress / 50) * 22;
  } else {
    hue = 30 + ((progress - 50) / 50) * 90;
  }

  return `hsl(${Math.round(hue)} 88% 52%)`;
}

function formatTaskTimestamp(createdAt) {
  if (!Number.isFinite(createdAt) || createdAt <= 0) {
    return "";
  }

  return new Intl.DateTimeFormat(undefined, {
    month: "numeric",
    day: "numeric",
    year: "numeric",
  }).format(createdAt);
}

function getStatusDisplay() {
  const selectedTask = selectedTaskId ? findTaskMeta(state.tasks, selectedTaskId)?.task ?? null : null;

  if (isListening) {
    return "MIC LIVE";
  }

  if (selectedTask?.done) {
    return "DONE";
  }

  if (selectedTask && selectedTask.progress > 0) {
    return `P ${selectedTask.progress}%`;
  }

  if (voiceMessage) {
    return voiceMessage;
  }

  return state.theme === "dark" ? "DARK" : "LIGHT";
}

function getStatusTitle() {
  const openCount = countOpenTasks(state.tasks);
  const selectedTask = selectedTaskId ? findTaskMeta(state.tasks, selectedTaskId)?.task ?? null : null;
  const parts = [];

  parts.push(state.theme === "dark" ? "Dark theme" : "Light theme");
  parts.push(`${openCount} open`);

  if (isListening) {
    parts.push("Microphone live");
  } else if (micReady) {
    parts.push("Mic ready");
  }

  if (selectedTask?.done) {
    parts.push("Selected task done");
  } else if (selectedTask && selectedTask.progress > 0) {
    parts.push(`Selected task ${selectedTask.progress}%`);
  }

  parts.push("Click to cycle palette");

  return parts.join(" | ");
}

function startEditingTask(taskId) {
  selectedTaskId = taskId;
  editingTaskId = taskId;
  pendingTaskInputFocusId = taskId;
  voiceMessage = "Editing task";
  render();
}

function commitEditingTask(taskId, nextText, options = {}) {
  if (editingTaskId !== taskId) {
    return;
  }

  const cleaned = normalizeTaskText(nextText);
  editingTaskId = null;
  pendingTaskInputFocusId = null;

  if (!cleaned) {
    removeTask(taskId, { rerender: options.rerender !== false });
    return;
  }

  const meta = findTaskMeta(state.tasks, taskId);
  if (!meta) {
    render();
    return;
  }

  if (meta.task.text !== cleaned) {
    pushHistory();
  }
  meta.task.text = cleaned;
  selectedTaskId = taskId;
  voiceMessage = "Task updated";
  scheduleSave();

  if (options.rerender !== false) {
    render();
  }
}

function cancelEditingTask() {
  editingTaskId = null;
  pendingTaskInputFocusId = null;
  voiceMessage = "Edit canceled";
  render();
}

function removeTask(taskId, options = {}) {
  const meta = findTaskMeta(state.tasks, taskId);
  if (!meta) {
    return false;
  }

  pushHistory();
  const removed = removeTaskById(state.tasks, taskId);
  if (!removed) {
    return false;
  }

  if (selectedTaskId === taskId) {
    selectedTaskId = null;
  }
  if (editingTaskId === taskId) {
    editingTaskId = null;
  }

  voiceMessage = "Task removed";
  scheduleSave();

  if (options.rerender !== false) {
    render();
  }

  return true;
}

function clearSelection() {
  selectedTaskId = null;
  editingTaskId = null;
  render();
}

function selectTask(taskId, options = {}) {
  selectedTaskId = taskId;
  if (options.rerender !== false) {
    render();
  }
}

function toggleTaskCollapsed(taskId) {
  const meta = findTaskMeta(state.tasks, taskId);
  if (!meta || meta.task.children.length === 0) {
    return false;
  }

  pushHistory();
  meta.task.collapsed = !meta.task.collapsed;
  selectedTaskId = taskId;
  voiceMessage = meta.task.collapsed ? "Drawer collapsed" : "Drawer expanded";
  scheduleSave();
  render();
  return true;
}

function toggleTheme() {
  pushHistory();
  state.theme = state.theme === "dark" ? "light" : "dark";
  voiceMessage = state.theme === "dark" ? "Dark theme" : "Light theme";
  scheduleSave();
  render();
}

function toggleShortcutHints() {
  pushHistory();
  state.showShortcuts = !state.showShortcuts;
  if (state.showShortcuts) {
    showWelcomeHint = false;
  }
  voiceMessage = state.showShortcuts ? "Shortcuts shown" : "Shortcuts hidden";
  scheduleSave();
  render();
}

function toggleStatusRadio() {
  pushHistory();
  state.showStatus = !state.showStatus;
  voiceMessage = state.showStatus ? "Status shown" : "Status hidden";
  scheduleSave();
  render();
}

function cycleStatusTheme() {
  const currentIndex = STATUS_THEMES.findIndex((themeOption) => themeOption.id === state.statusTheme);
  const nextIndex = currentIndex >= 0 ? (currentIndex + 1) % STATUS_THEMES.length : 0;
  pushHistory();
  state.statusTheme = STATUS_THEMES[nextIndex].id;
  voiceMessage = `Status palette ${STATUS_THEMES[nextIndex].label}`;
  scheduleSave();
  render();
}

function focusComposer(seedText = null) {
  const input = elements.quickAddInput;
  input.focus();
  if (seedText !== null) {
    input.value = seedText;
  }
  const length = input.value.length;
  input.setSelectionRange(length, length);
  syncComposerControls();
}

function focusSearch() {
  elements.searchInput.focus();
  const length = elements.searchInput.value.length;
  elements.searchInput.setSelectionRange(length, length);
}

function restoreEditingFocus() {
  if (pendingTaskInputFocusId) {
    const input = document.querySelector(`[data-task-edit-id="${pendingTaskInputFocusId}"]`);
    if (input) {
      input.focus();
      input.setSelectionRange(input.value.length, input.value.length);
    }
  }
}

function handleGlobalKeydown(event) {
  const target = event.target;
  const inTextField = isTextField(target);
  const key = event.key.toLowerCase();

  if (
    event.ctrlKey &&
    !event.shiftKey &&
    key === "z" &&
    (
      !inTextField ||
      (
        (target === elements.quickAddInput || target === elements.searchInput) &&
        target.value.trim() === ""
      )
    )
  ) {
    event.preventDefault();
    undoLastChange();
    return;
  }

  if (event.ctrlKey && key === "k") {
    event.preventDefault();
    focusComposer();
    return;
  }

  if (event.ctrlKey && !event.shiftKey && key === "n") {
    event.preventDefault();
    void createNewChecklist();
    return;
  }

  if (event.ctrlKey && key === "f") {
    event.preventDefault();
    focusSearch();
    return;
  }

  if (event.ctrlKey && key === "t") {
    event.preventDefault();
    toggleTheme();
    return;
  }

  if (event.ctrlKey && !event.shiftKey && key === "h") {
    event.preventDefault();
    event.stopPropagation();
    toggleShortcutHints();
    return;
  }

  if (event.ctrlKey && !event.shiftKey && key === "s") {
    event.preventDefault();
    event.stopPropagation();
    toggleStatusRadio();
    return;
  }

  if (inTextField) {
    return;
  }

  if (event.altKey && event.key === "ArrowUp") {
    event.preventDefault();
    moveSelectedWithinLevel(-1);
    return;
  }

  if (event.altKey && event.key === "ArrowDown") {
    event.preventDefault();
    moveSelectedWithinLevel(1);
    return;
  }

  if (event.key === "ArrowDown") {
    event.preventDefault();
    moveSelection(1);
    return;
  }

  if (event.key === "ArrowUp") {
    event.preventDefault();
    moveSelection(-1);
    return;
  }

  if (event.key === "Enter") {
    event.preventDefault();
    if (selectedTaskId) {
      startEditingTask(selectedTaskId);
    } else {
      focusComposer();
    }
    return;
  }

  if (event.key === " " && selectedTaskId) {
    event.preventDefault();
    incrementProgress(selectedTaskId);
    return;
  }

  if (event.key === "Backspace" && selectedTaskId) {
    event.preventDefault();
    decrementProgress(selectedTaskId);
    return;
  }

  if (event.key === "Delete" && selectedTaskId) {
    event.preventDefault();
    removeTask(selectedTaskId);
    return;
  }

  if (event.key === "Tab" && selectedTaskId) {
    event.preventDefault();
    if (event.shiftKey) {
      outdentTask(selectedTaskId);
    } else {
      moveTaskLevel(selectedTaskId);
    }
    render();
    return;
  }

  if (event.key === "Escape") {
    event.preventDefault();
    clearSelection();
    focusComposer();
    return;
  }

  if (!event.ctrlKey && !event.metaKey && !event.altKey && event.key.length === 1) {
    focusComposer(event.key);
    event.preventDefault();
  }
}

function isTextField(target) {
  return Boolean(target && (target.matches("input, textarea") || target.isContentEditable));
}

function moveSelection(direction) {
  if (visibleTaskIds.length === 0) {
    return;
  }

  if (!selectedTaskId || !visibleTaskIds.includes(selectedTaskId)) {
    selectedTaskId = direction > 0 ? visibleTaskIds[0] : visibleTaskIds[visibleTaskIds.length - 1];
    render();
    return;
  }

  const index = visibleTaskIds.indexOf(selectedTaskId);
  const nextIndex = Math.max(0, Math.min(visibleTaskIds.length - 1, index + direction));
  selectedTaskId = visibleTaskIds[nextIndex];
  render();
}

function flattenTaskIds(tasks, options = {}, result = []) {
  const includeCollapsedChildren = Boolean(options.includeCollapsedChildren);
  for (const task of tasks) {
    result.push(task.id);
    if (includeCollapsedChildren || !task.collapsed) {
      flattenTaskIds(task.children, options, result);
    }
  }
  return result;
}

function moveSelectedWithinLevel(direction) {
  if (!selectedTaskId) {
    return;
  }

  const meta = findTaskMeta(state.tasks, selectedTaskId);
  if (!meta) {
    return;
  }

  const nextIndex = meta.index + direction;
  if (nextIndex < 0 || nextIndex >= meta.parentList.length) {
    return;
  }

  pushHistory();
  const [task] = meta.parentList.splice(meta.index, 1);
  meta.parentList.splice(nextIndex, 0, task);
  voiceMessage = "Task moved";
  scheduleSave();
  render();
}

function indentTask(taskId) {
  const meta = findTaskMeta(state.tasks, taskId);
  if (!meta || meta.index === 0) {
    return false;
  }

  pushHistory();
  const previousSibling = meta.parentList[meta.index - 1];
  const [task] = meta.parentList.splice(meta.index, 1);
  previousSibling.children.push(task);
  previousSibling.collapsed = false;
  selectedTaskId = task.id;
  voiceMessage = "Nested under previous task";
  scheduleSave();
  return true;
}

function moveTaskLevel(taskId) {
  const meta = findTaskMeta(state.tasks, taskId);
  if (!meta) {
    return false;
  }

  if (meta.parentTask) {
    return outdentTask(taskId);
  }

  return indentTask(taskId);
}

function outdentTask(taskId) {
  const meta = findTaskMeta(state.tasks, taskId);
  if (!meta || !meta.parentTask) {
    return false;
  }

  pushHistory();
  const parentId = meta.parentTask.id;
  const [task] = meta.parentList.splice(meta.index, 1);
  const parentMeta = findTaskMeta(state.tasks, parentId);
  if (!parentMeta) {
    state.tasks.push(task);
  } else {
    parentMeta.parentList.splice(parentMeta.index + 1, 0, task);
  }
  selectedTaskId = task.id;
  voiceMessage = "Moved up one level";
  scheduleSave();
  return true;
}

function countOpenTasks(tasks) {
  return tasks.reduce((count, task) => {
    const ownCount = task.done ? 0 : 1;
    return count + ownCount + countOpenTasks(task.children);
  }, 0);
}

function undoLastChange() {
  const snapshot = historyStack.pop();
  if (!snapshot) {
    voiceMessage = "Nothing recent to undo";
    render();
    return;
  }

  state = sanitizeState(snapshot.state);
  ensureTaskIds(state.tasks);
  selectedTaskId = snapshot.selectedTaskId ?? null;
  editingTaskId = null;
  pendingTaskInputFocusId = null;
  voiceMessage = "Undid last change";
  scheduleSave();
  render();
}

function filterTasks(tasks, query) {
  const lowered = query.trim().toLowerCase();
  if (!lowered) {
    return { tasks };
  }

  const filtered = [];
  for (const task of tasks) {
    const match = filterTask(task, lowered);
    if (match) {
      filtered.push(match);
    }
  }
  return { tasks: filtered };
}

function filterTask(task, loweredQuery) {
  const childMatches = [];
  for (const child of task.children) {
    const match = filterTask(child, loweredQuery);
    if (match) {
      childMatches.push(match);
    }
  }

  if (task.text.toLowerCase().includes(loweredQuery) || childMatches.length > 0) {
    return { ...task, children: childMatches };
  }

  return null;
}

function findTaskMeta(tasks, taskId, parentTask = null, parentList = tasks) {
  for (let index = 0; index < tasks.length; index += 1) {
    const task = tasks[index];
    if (task.id === taskId) {
      return { task, index, parentTask, parentList };
    }

    const childResult = findTaskMeta(task.children, taskId, task, task.children);
    if (childResult) {
      return childResult;
    }
  }
  return null;
}

function removeTaskById(tasks, taskId) {
  for (let index = 0; index < tasks.length; index += 1) {
    const task = tasks[index];
    if (task.id === taskId) {
      return tasks.splice(index, 1)[0];
    }

    const removed = removeTaskById(task.children, taskId);
    if (removed) {
      return removed;
    }
  }
  return null;
}

function containsTask(task, taskId) {
  if (task.id === taskId) {
    return true;
  }
  return task.children.some((child) => containsTask(child, taskId));
}

function getDropPosition(row, clientY) {
  const rect = row.getBoundingClientRect();
  const ratio = (clientY - rect.top) / rect.height;
  if (ratio < 0.3) {
    return "before";
  }
  if (ratio > 0.7) {
    return "after";
  }
  return "inside";
}

function canMoveTask(dragId, targetId, position) {
  if (!dragId || !targetId || dragId === targetId) {
    return false;
  }

  const dragMeta = findTaskMeta(state.tasks, dragId);
  const targetMeta = findTaskMeta(state.tasks, targetId);
  if (!dragMeta || !targetMeta) {
    return false;
  }

  if (containsTask(dragMeta.task, targetId)) {
    return false;
  }

  if ((position === "before" || position === "after") && dragMeta.parentList === targetMeta.parentList) {
    if (position === "before" && dragMeta.index === targetMeta.index - 1) {
      return false;
    }
    if (position === "after" && dragMeta.index === targetMeta.index + 1) {
      return false;
    }
  }

  return true;
}

function moveTask(dragId, targetId, position) {
  if (!canMoveTask(dragId, targetId, position)) {
    return false;
  }

  pushHistory();
  const task = removeTaskById(state.tasks, dragId);
  const targetMeta = findTaskMeta(state.tasks, targetId);
  if (!task || !targetMeta) {
    return false;
  }

  if (position === "before") {
    targetMeta.parentList.splice(targetMeta.index, 0, task);
  } else if (position === "after") {
    targetMeta.parentList.splice(targetMeta.index + 1, 0, task);
  } else {
    targetMeta.task.children.unshift(task);
    targetMeta.task.collapsed = false;
  }

  selectedTaskId = task.id;
  voiceMessage = position === "inside" ? "Nested under task" : "Task moved";
  scheduleSave();
  return true;
}

function moveTaskToRoot(taskId) {
  const meta = findTaskMeta(state.tasks, taskId);
  if (!meta) {
    return;
  }

  pushHistory();
  const task = removeTaskById(state.tasks, taskId);
  if (!task) {
    return;
  }
  state.tasks.push(task);
  selectedTaskId = task.id;
  voiceMessage = "Moved to top level";
  scheduleSave();
}

function setDropIndicator(row, position) {
  if (activeDropRow && activeDropRow !== row) {
    activeDropRow.removeAttribute("data-drop-position");
  }
  activeDropRow = row;
  row.dataset.dropPosition = position;
}

function clearDropIndicator() {
  if (activeDropRow) {
    activeDropRow.removeAttribute("data-drop-position");
    activeDropRow = null;
  }
}

function scheduleSave() {
  window.clearTimeout(saveTimer);
  saveTimer = window.setTimeout(() => {
    saveState().catch((error) => console.error("Failed to save state", error));
  }, 5000);
}

function ensurePeriodicSaveLoop() {
  if (periodicSaveIntervalId) {
    return;
  }

  periodicSaveIntervalId = window.setInterval(() => {
    saveState().catch((error) => console.error("Failed to autosave state", error));
  }, 300000);
}

async function saveState() {
  const api = await waitForBridge();
  if (!api || typeof api.save_state !== "function") {
    return;
  }

  await api.save_state(state);
}

function setupVoiceInput() {
  const SpeechRecognitionCtor = window.SpeechRecognition || window.webkitSpeechRecognition;
  const hasMediaStream = Boolean(navigator.mediaDevices?.getUserMedia);

  if (!SpeechRecognitionCtor || !hasMediaStream) {
    voiceMessage = "Mic input is unavailable here";
    elements.voiceButton.disabled = true;
    syncVoiceChrome();
    return;
  }

  speechRecognition = new SpeechRecognitionCtor();
  speechRecognition.lang = navigator.language || "en-US";
  speechRecognition.interimResults = true;
  speechRecognition.continuous = false;
  speechRecognition.maxAlternatives = 1;

  speechRecognition.onstart = () => {
    isListening = true;
    speechBaseText = normalizeTaskText(elements.quickAddInput.value);
    speechFinalText = "";
    voiceMessage = "Listening live";
    render();
  };

  speechRecognition.onresult = (event) => {
    let finalText = "";
    let interimText = "";

    for (let index = 0; index < event.results.length; index += 1) {
      const result = event.results[index];
      const transcript = result[0]?.transcript ?? "";
      if (result.isFinal) {
        finalText += `${transcript} `;
      } else {
        interimText += `${transcript} `;
      }
    }

    speechFinalText = normalizeTaskText(finalText);
    const liveText = normalizeTaskText(`${speechFinalText} ${interimText}`);
    elements.quickAddInput.value = combineSpeechText(speechBaseText, liveText);
    voiceMessage = interimText ? "Adjusting as you talk" : "Refining final transcript";
    syncComposerControls();
  };

  speechRecognition.onerror = (event) => {
    isListening = false;
    setMicTracksEnabled(false);
    micLevel = 0;
    voiceMessage = event.error === "not-allowed" ? "Mic permission blocked" : "Voice capture hit a snag";
    render();
  };

  speechRecognition.onend = () => {
    isListening = false;
    setMicTracksEnabled(false);
    micLevel = 0;
    const refined = refineTranscript(speechFinalText);
    if (refined) {
      elements.quickAddInput.value = combineSpeechText(speechBaseText, refined);
      syncComposerControls();
      voiceMessage = "Transcript tightened. Press Enter.";
    } else {
      voiceMessage = micReady ? "Mic ready" : "Mic off";
    }
    render();
    focusComposer();
  };

  voiceMessage = "Mic ready when you need it";
}

function syncVoiceChrome() {
  elements.voiceButton.classList.toggle("is-ready", micReady);
  elements.voiceButton.classList.toggle("is-listening", isListening);
  elements.voiceButton.style.setProperty("--mic-level", `${Math.max(0, Math.min(100, Math.round(micLevel)))}%`);
}

async function ensureMicrophoneReady() {
  if (micStream) {
    await resumeMicAudioContext();
    return true;
  }

  try {
    micStream = await navigator.mediaDevices.getUserMedia({
      audio: {
        echoCancellation: true,
        noiseSuppression: true,
        autoGainControl: true,
      },
    });
  } catch (error) {
    console.error(error);
    voiceMessage = error?.name === "NotAllowedError" ? "Mic permission blocked" : "Microphone unavailable";
    render();
    return false;
  }

  micReady = true;
  setMicTracksEnabled(false);
  await ensureMicMeter();
  voiceMessage = "Mic ready";
  render();
  return true;
}

async function ensureMicMeter() {
  if (!micStream || micAudioContext) {
    await resumeMicAudioContext();
    if (!micMeterFrameId) {
      micMeterFrameId = window.requestAnimationFrame(updateMicMeter);
    }
    return;
  }

  const AudioContextCtor = window.AudioContext || window.webkitAudioContext;
  if (!AudioContextCtor) {
    return;
  }

  micAudioContext = new AudioContextCtor();
  const source = micAudioContext.createMediaStreamSource(micStream);
  micAnalyser = micAudioContext.createAnalyser();
  micAnalyser.fftSize = 256;
  micAnalyser.smoothingTimeConstant = 0.72;
  micMeterData = new Uint8Array(micAnalyser.fftSize);
  source.connect(micAnalyser);

  await resumeMicAudioContext();

  if (!micMeterFrameId) {
    micMeterFrameId = window.requestAnimationFrame(updateMicMeter);
  }
}

async function resumeMicAudioContext() {
  if (micAudioContext && micAudioContext.state === "suspended") {
    try {
      await micAudioContext.resume();
    } catch (error) {
      console.error(error);
    }
  }
}

function updateMicMeter() {
  if (micAnalyser && micMeterData) {
    micAnalyser.getByteTimeDomainData(micMeterData);

    let total = 0;
    for (let index = 0; index < micMeterData.length; index += 1) {
      const normalized = (micMeterData[index] - 128) / 128;
      total += normalized * normalized;
    }

    const rms = Math.sqrt(total / micMeterData.length);
    micLevel = rms > 0 ? Math.min(100, rms * 360) : 0;
  } else {
    micLevel = 0;
  }

  if (!isListening && micLevel < 1) {
    micLevel = 0;
  }

  syncVoiceChrome();
  micMeterFrameId = window.requestAnimationFrame(updateMicMeter);
}

function setMicTracksEnabled(enabled) {
  if (!micStream) {
    return;
  }

  for (const track of micStream.getAudioTracks()) {
    track.enabled = enabled;
  }

  if (!enabled) {
    micLevel = 0;
    syncVoiceChrome();
  }
}

async function toggleVoiceInput() {
  if (!speechRecognition) {
    voiceMessage = "Mic input is unavailable here";
    render();
    return;
  }

  focusComposer();
  if (isListening) {
    speechRecognition.stop();
    return;
  }

  const ready = await ensureMicrophoneReady();
  if (!ready) {
    return;
  }

  setMicTracksEnabled(true);

  try {
    speechRecognition.start();
  } catch (error) {
    console.error(error);
    setMicTracksEnabled(false);
    micLevel = 0;
    voiceMessage = "Mic is not ready yet";
    render();
  }
}

function disposeVoiceInput() {
  if (micMeterFrameId) {
    window.cancelAnimationFrame(micMeterFrameId);
    micMeterFrameId = null;
  }

  if (micStream) {
    for (const track of micStream.getTracks()) {
      track.stop();
    }
    micStream = null;
  }

  if (micAudioContext) {
    void micAudioContext.close().catch(() => {});
    micAudioContext = null;
  }
}

function combineSpeechText(prefix, spokenText) {
  if (!prefix) {
    return spokenText;
  }
  if (!spokenText) {
    return prefix;
  }
  return `${prefix} ${spokenText}`.trim();
}

function refineTranscript(text) {
  return normalizeTaskText(text);
}
