<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed, nextTick } from "vue";
import { useRoute, useRouter, onBeforeRouteLeave } from "vue-router";
import { useTasksStore } from "@/stores/tasks";
import { useNotesStore } from "@/stores/notes";
import { useToastStore } from "@/stores/toast";
import { renderMarkdown } from "@/utils/markdown";
import { useAutocomplete } from "@/composables/useAutocomplete";
import type { TaskStatus, TaskPriority } from "@/types/task";
import MarkdownToolbar from "@/components/MarkdownToolbar.vue";

const route = useRoute();
const router = useRouter();
const store = useTasksStore();
const notesStore = useNotesStore();
const toast = useToastStore();

const title = ref("");
const body = ref("");
const status = ref<TaskStatus>("todo");
const priority = ref<TaskPriority>("none");
const dueDate = ref("");
const dirty = ref(false);
const saving = ref(false);
const showPreview = ref(false);
const textareaRef = ref<HTMLTextAreaElement | null>(null);

const taskId = computed(() =>
  route.params.id ? Number(route.params.id) : null
);
const isEditing = computed(() => taskId.value !== null);

const renderedPreview = computed(() => renderMarkdown(body.value));

// Autocomplete
const {
  acItems,
  acVisible,
  acIndex,
  acTop,
  acLeft,
  detectTrigger,
  accept: acAccept,
  dismiss: acDismiss,
  onKeydown: acOnKeydown,
} = useAutocomplete(textareaRef, body, (q) => notesStore.fetchAllTags(q));

let savedTitle = "";
let savedBody = "";
let savedStatus: TaskStatus = "todo";
let savedPriority: TaskPriority = "none";
let savedDueDate = "";

function markDirty() {
  dirty.value =
    title.value !== savedTitle ||
    body.value !== savedBody ||
    status.value !== savedStatus ||
    priority.value !== savedPriority ||
    dueDate.value !== savedDueDate;
}

function autoGrow() {
  const el = textareaRef.value;
  if (!el) return;
  el.style.height = "auto";
  el.style.height = Math.max(el.scrollHeight, 200) + "px";
}

function onBodyInput() {
  markDirty();
  autoGrow();
  detectTrigger();
}

function onTextareaKeydown(e: KeyboardEvent) {
  acOnKeydown(e);
}

function onTextareaBlur() {
  setTimeout(acDismiss, 150);
}

function insertAtCursor(before: string, after: string, placeholder: string) {
  const el = textareaRef.value;
  if (!el) return;
  showPreview.value = false;
  nextTick(() => {
    el.focus();
    const start = el.selectionStart;
    const end = el.selectionEnd;
    const selected = body.value.slice(start, end);
    const insert = selected || placeholder;
    body.value =
      body.value.slice(0, start) + before + insert + after + body.value.slice(end);
    markDirty();
    nextTick(() => {
      const newStart = start + before.length;
      const newEnd = newStart + insert.length;
      el.setSelectionRange(newStart, newEnd);
      el.focus();
      autoGrow();
    });
  });
}

onMounted(async () => {
  if (taskId.value) {
    await store.fetchTask(taskId.value);
    if (store.currentTask) {
      title.value = store.currentTask.title;
      body.value = store.currentTask.body;
      status.value = store.currentTask.status as TaskStatus;
      priority.value = store.currentTask.priority as TaskPriority;
      dueDate.value = store.currentTask.due_date || "";
      savedTitle = title.value;
      savedBody = body.value;
      savedStatus = status.value;
      savedPriority = priority.value;
      savedDueDate = dueDate.value;
    }
  }
  nextTick(autoGrow);
});

async function save() {
  if (saving.value) return;
  saving.value = true;
  try {
    const data = {
      title: title.value,
      body: body.value,
      status: status.value,
      priority: priority.value,
      due_date: dueDate.value || null,
    };
    if (isEditing.value) {
      await store.updateTask(taskId.value!, data);
      savedTitle = title.value;
      savedBody = body.value;
      savedStatus = status.value;
      savedPriority = priority.value;
      savedDueDate = dueDate.value;
      dirty.value = false;
      toast.show("Task saved");
    } else {
      const task = await store.createTask(data);
      dirty.value = false;
      toast.show("Task created");
      router.push(`/tasks/${task.id}`);
    }
  } catch {
    toast.show("Failed to save task", "error");
  } finally {
    saving.value = false;
  }
}

const showDeleteConfirm = ref(false);

function remove() {
  if (taskId.value) {
    showDeleteConfirm.value = true;
  }
}

async function confirmDelete() {
  showDeleteConfirm.value = false;
  if (!taskId.value) return;
  try {
    await store.deleteTask(taskId.value);
    dirty.value = false;
    toast.show("Task deleted");
    router.push("/tasks");
  } catch {
    toast.show("Failed to delete task", "error");
  }
}

function onKeydown(e: KeyboardEvent) {
  if ((e.ctrlKey || e.metaKey) && e.key === "s") {
    e.preventDefault();
    save();
  }
}

onMounted(() => document.addEventListener("keydown", onKeydown));
onUnmounted(() => document.removeEventListener("keydown", onKeydown));

onBeforeRouteLeave(() => {
  if (dirty.value) {
    return confirm("You have unsaved changes. Leave anyway?");
  }
});

function onBeforeUnload(e: BeforeUnloadEvent) {
  if (dirty.value) {
    e.preventDefault();
  }
}
onMounted(() => window.addEventListener("beforeunload", onBeforeUnload));
onUnmounted(() => window.removeEventListener("beforeunload", onBeforeUnload));
</script>

<template>
  <main class="editor">
    <div class="toolbar">
      <router-link to="/tasks" class="btn-back">Back</router-link>
      <button class="btn-save" @click="save" :disabled="saving">
        {{ saving ? "Saving..." : "Save" }}
      </button>
      <button v-if="isEditing" class="btn-delete" @click="remove">
        Delete
      </button>
    </div>
    <input
      v-model="title"
      type="text"
      placeholder="Task title"
      class="title-input"
      @input="markDirty"
    />

    <div class="editor-tabs">
      <button
        :class="['tab', { active: !showPreview }]"
        @click="showPreview = false"
      >
        Write
      </button>
      <button
        :class="['tab', { active: showPreview }]"
        @click="showPreview = true"
      >
        Preview
      </button>
    </div>

    <MarkdownToolbar v-show="!showPreview" @insert="insertAtCursor" />

    <div class="textarea-wrapper" v-show="!showPreview">
      <textarea
        ref="textareaRef"
        v-model="body"
        placeholder="Describe this task... Use #tags inline"
        class="body-input"
        @input="onBodyInput"
        @keydown="onTextareaKeydown"
        @blur="onTextareaBlur"
      ></textarea>

      <!-- Autocomplete dropdown -->
      <ul
        v-if="acVisible"
        class="ac-dropdown"
        :style="{ top: acTop + 'px', left: acLeft + 'px' }"
      >
        <li
          v-for="(item, i) in acItems"
          :key="item.value"
          :class="['ac-item', { active: i === acIndex }]"
          @mousedown.prevent="acAccept(i)"
        >
          {{ item.label }}
        </li>
      </ul>
    </div>

    <div
      v-show="showPreview"
      class="preview-pane prose"
      v-html="renderedPreview"
    ></div>

    <div class="field-row">
      <div class="field">
        <label>Status</label>
        <select v-model="status" @change="markDirty" class="field-select">
          <option value="todo">Todo</option>
          <option value="in_progress">In Progress</option>
          <option value="done">Done</option>
        </select>
      </div>
      <div class="field">
        <label>Priority</label>
        <select v-model="priority" @change="markDirty" class="field-select">
          <option value="none">None</option>
          <option value="low">Low</option>
          <option value="medium">Medium</option>
          <option value="high">High</option>
        </select>
      </div>
      <div class="field">
        <label>Due Date</label>
        <input
          v-model="dueDate"
          type="date"
          class="field-input"
          @input="markDirty"
        />
      </div>
    </div>

    <!-- Delete confirmation -->
    <teleport to="body">
      <div v-if="showDeleteConfirm" class="modal-overlay" @click="showDeleteConfirm = false">
        <div class="modal-card" @click.stop>
          <h3 class="modal-title">Delete Task</h3>
          <p class="modal-message">Are you sure you want to delete this task? This cannot be undone.</p>
          <div class="modal-actions">
            <button class="modal-btn" @click="showDeleteConfirm = false">Cancel</button>
            <button class="modal-btn modal-btn-danger" @click="confirmDelete">Delete</button>
          </div>
        </div>
      </div>
    </teleport>
  </main>
</template>

<style scoped>
.editor {
  max-width: 720px;
  margin: 2rem auto;
  padding: 0 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.toolbar {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}
.btn-back {
  text-decoration: none;
  color: var(--color-primary);
}
.btn-save {
  padding: 0.45rem 1rem;
  background: var(--color-primary);
  color: #fff;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.btn-save:disabled {
  opacity: 0.6;
  cursor: default;
}
.btn-delete {
  padding: 0.45rem 1rem;
  background: var(--color-danger);
  color: #fff;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  margin-left: auto;
}
.title-input {
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-sm);
  font-size: 1.25rem;
  font-weight: 600;
  background: var(--color-bg-card);
  color: var(--color-text);
}
.editor-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--color-border);
}
.tab {
  padding: 0.45rem 1rem;
  border: none;
  background: none;
  color: var(--color-text-secondary);
  cursor: pointer;
  font-size: 0.9rem;
  border-bottom: 2px solid transparent;
}
.tab.active {
  color: var(--color-primary);
  border-bottom-color: var(--color-primary);
}
.textarea-wrapper {
  position: relative;
}
.body-input {
  width: 100%;
  padding: 0.75rem;
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-sm);
  font-size: 1rem;
  font-family: monospace;
  min-height: 200px;
  resize: none;
  overflow: hidden;
  background: var(--color-bg-card);
  color: var(--color-text);
  box-sizing: border-box;
}
.preview-pane {
  padding: 0.75rem;
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-sm);
  min-height: 200px;
  background: var(--color-bg-card);
}
.ac-dropdown {
  position: fixed;
  z-index: 100;
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-card);
  box-shadow: 0 4px 12px var(--color-shadow);
  max-height: 200px;
  overflow-y: auto;
  min-width: 160px;
}
.ac-item {
  padding: 0.4rem 0.75rem;
  cursor: pointer;
  font-size: 0.9rem;
}
.ac-item:hover,
.ac-item.active {
  background: var(--color-bg-secondary);
}
.field-row {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}
.field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 0;
  flex: 1;
}
.field label {
  font-size: 0.85rem;
  color: var(--color-text-secondary);
  font-weight: 500;
}
.field-select,
.field-input {
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-card);
  color: var(--color-text);
  font-size: 0.9rem;
}
.modal-overlay {
  position: fixed;
  inset: 0;
  background: var(--color-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
}
.modal-card {
  background: var(--color-bg-card);
  border-radius: var(--radius-md);
  padding: 1.5rem;
  max-width: 400px;
  width: 90%;
  box-shadow: 0 8px 32px var(--color-shadow);
}
.modal-title {
  margin: 0 0 0.5rem;
  font-size: 1.1rem;
}
.modal-message {
  margin: 0 0 1.25rem;
  color: var(--color-text-secondary);
  font-size: 0.95rem;
}
.modal-actions {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
}
.modal-btn {
  padding: 0.45rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-card);
  color: var(--color-text);
  cursor: pointer;
  font-size: 0.9rem;
}
.modal-btn-danger {
  background: var(--color-danger);
  color: #fff;
  border-color: var(--color-danger);
}
</style>
