<!-- @format -->
<script lang="ts">
  import {
    addTodoItem,
    addTodoItemBackend,
    getOrCreateTodoList,
    removeTodoItem,
    removeTodoItemBackend,
    serializeTodoList,
    setTodoList,
    toggleTodoItem,
    toggleTodoItemBackend,
    todosStore,
    type TodoItem,
    updateTodoItemText,
    updateTodoItemTextBackend,
  } from "$lib/stores/todos";
  import { get } from "svelte/store";

  export let openDocumentId = "";
  export let openDocumentName = "";
  export let openDocumentContent = "";
  export let onDocumentContentChange: (content: string) => void = () => {};

  let todoItems: TodoItem[] = [];
  let lastTodoDocumentId = "";
  let newTodoText = "";
  let editingTodoId: number | null = null;
  let editingTodoText = "";

  async function addTodo() {
    const text = newTodoText.trim();
    if (!text) return;
    newTodoText = "";
    const backendItem = await addTodoItemBackend(openDocumentId, text);
    if (backendItem) {
      todoItems = [backendItem, ...todoItems];
    } else {
      todoItems = addTodoItem(todoItems, text);
    }
    persistTodosForCurrentList();
  }

  async function toggleTodoDone(id: number) {
    const ok = await toggleTodoItemBackend(openDocumentId, id);
    if (!ok) {
      todoItems = toggleTodoItem(todoItems, id);
    } else {
      todoItems = todoItems.map((t) =>
        t.id === id ? { ...t, done: !t.done } : t,
      );
    }
    persistTodosForCurrentList();
  }

  function startEditTodo(id: number) {
    const todo = todoItems.find((item) => item.id === id);
    if (!todo) return;
    editingTodoId = id;
    editingTodoText = todo.text;
  }

  async function saveEditTodo() {
    if (editingTodoId === null) return;
    const text = editingTodoText.trim();
    if (!text) return;
    const id = editingTodoId;
    editingTodoId = null;
    editingTodoText = "";
    const ok = await updateTodoItemTextBackend(openDocumentId, id, text);
    if (!ok) {
      todoItems = updateTodoItemText(todoItems, id, text);
    } else {
      todoItems = todoItems.map((t) =>
        t.id === id ? { ...t, text: text.trim() } : t,
      );
    }
    persistTodosForCurrentList();
  }

  function cancelEditTodo() {
    editingTodoId = null;
    editingTodoText = "";
  }

  async function removeTodo(id: number) {
    if (editingTodoId === id) {
      cancelEditTodo();
    }
    const ok = await removeTodoItemBackend(openDocumentId, id);
    if (!ok) {
      todoItems = removeTodoItem(todoItems, id);
    } else {
      todoItems = todoItems.filter((t) => t.id !== id);
    }
    persistTodosForCurrentList();
  }

  function loadTodosForDocument(documentId: string) {
    if (!documentId) {
      todoItems = [];
      return;
    }

    const lists = get(todosStore);
    const result = getOrCreateTodoList(lists, documentId, openDocumentContent);
    if (result.lists !== lists) {
      todosStore.set(result.lists);
    }
    todoItems = result.todos;
  }

  function persistTodosForCurrentList() {
    if (!openDocumentId) return;
    const lists = get(todosStore);
    todosStore.set(setTodoList(lists, openDocumentId, todoItems));
    const markdown = serializeTodoList(openDocumentName, todoItems);
    onDocumentContentChange(markdown);
  }

  $: if (openDocumentId !== lastTodoDocumentId) {
    loadTodosForDocument(openDocumentId);
    editingTodoId = null;
    editingTodoText = "";
    newTodoText = "";
    lastTodoDocumentId = openDocumentId;
  }
</script>

<section class="todo-surface">
  <div class="todo-card">
    <form class="todo-create" on:submit|preventDefault={addTodo}>
      <input
        type="text"
        placeholder="Add a new to-do"
        bind:value={newTodoText}
        aria-label="Add to-do"
      />
      <button type="submit" class="todo-add-btn">Add</button>
    </form>

    <ul class="todo-list">
      {#each todoItems as todo}
        <li class="todo-item">
          <label class="todo-check">
            <input
              type="checkbox"
              checked={todo.done}
              on:change={() => toggleTodoDone(todo.id)}
            />
          </label>

          {#if editingTodoId === todo.id}
            <input
              type="text"
              class="todo-edit-input"
              bind:value={editingTodoText}
              on:keydown={(event) => {
                if (event.key === "Enter") saveEditTodo();
                if (event.key === "Escape") cancelEditTodo();
              }}
            />
            <div class="todo-actions">
              <button
                type="button"
                class="todo-btn save"
                on:click={saveEditTodo}>Save</button
              >
              <button
                type="button"
                class="todo-btn ghost"
                on:click={cancelEditTodo}>Cancel</button
              >
            </div>
          {:else}
            <span class="todo-text" class:is-done={todo.done}>{todo.text}</span>
            <div class="todo-actions">
              <button
                type="button"
                class="todo-btn ghost"
                on:click={() => startEditTodo(todo.id)}>Edit</button
              >
              <button
                type="button"
                class="todo-btn danger"
                on:click={() => removeTodo(todo.id)}>Remove</button
              >
            </div>
          {/if}
        </li>
      {/each}
    </ul>
  </div>
</section>

<style>
  .todo-surface {
    min-height: 0;
    flex: 1;
    overflow: auto;
    padding: 0 14px 14px;
  }

  .todo-card {
    width: min(100%, 920px);
    margin: 0 auto;
    border: none;
    border-radius: 0;
    background: transparent;
    padding: 28px 36px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    max-height: 100%;
    overflow: visible;
  }

  .todo-create {
    display: flex;
    gap: 8px;
  }

  .todo-create input,
  .todo-edit-input {
    width: 100%;
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    background: color-mix(in srgb, var(--surface-1) 88%, var(--bg-editor) 12%);
    color: var(--text-primary);
    padding: 10px 11px;
    font-size: 0.88rem;
  }

  .todo-add-btn {
    border-radius: 8px;
    border: 1px solid var(--border-strong);
    background: color-mix(in srgb, var(--surface-2) 84%, var(--bg-hover) 16%);
    color: var(--text-primary);
    padding: 9px 14px;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
  }

  .todo-add-btn:hover {
    background: var(--bg-hover);
  }

  .todo-list {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

  .todo-item {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 10px;
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    padding: 10px 12px;
    background: color-mix(in srgb, var(--surface-1) 90%, var(--bg-editor) 10%);
  }

  .todo-check {
    display: grid;
    place-items: center;
  }

  .todo-text {
    font-size: 0.9rem;
    color: var(--text-primary);
    line-height: 1.45;
  }

  .todo-text.is-done {
    color: var(--text-dim);
    text-decoration: line-through;
  }

  .todo-actions {
    display: flex;
    gap: 6px;
  }

  .todo-btn {
    border-radius: 7px;
    border: 1px solid var(--border-soft);
    background: color-mix(in srgb, var(--surface-1) 90%, var(--bg-editor) 10%);
    color: var(--text-muted);
    padding: 6px 10px;
    font-size: 0.78rem;
    cursor: pointer;
  }

  .todo-btn.save {
    border-color: var(--border-strong);
    background: color-mix(in srgb, var(--surface-2) 84%, var(--bg-hover) 16%);
    color: var(--text-primary);
  }

  .todo-btn.danger:hover,
  .todo-btn.ghost:hover,
  .todo-btn.save:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
  }

  @media (max-width: 980px) {
    .todo-surface {
      padding: 4px 8px 10px;
    }

    .todo-card {
      width: 100%;
      padding: 18px 16px;
    }

    .todo-create {
      flex-wrap: wrap;
    }

    .todo-add-btn {
      width: 100%;
    }

    .todo-item {
      grid-template-columns: auto minmax(0, 1fr);
      row-gap: 8px;
    }

    .todo-actions {
      grid-column: 1 / -1;
      justify-content: flex-end;
    }
  }
</style>
