<template>
    <div class="dashboard-container">
        <nav ref="navbarRef" class="navbar navbar-dark bg-dark sticky-top">
            <div class="container-fluid app-navbar">
                <div class="navbar-left d-flex align-items-center gap-2">
                    <button v-if="currentUser && currentSpace" class="btn btn-outline-light d-md-none nav-menu-toggle" type="button" aria-label="Toggle sidebar" @click="showSidebar = !showSidebar">
                        <i class="mdi mdi-menu" aria-hidden="true"></i>
                    </button>

                    <span class="navbar-brand mb-0 h1 d-flex align-items-center gap-2 app-brand">
                        <i class="mdi mdi-notebook-outline" aria-hidden="true"></i>
                        <span>Notely</span>
                    </span>
                </div>

                <div class="navbar-controls d-flex align-items-center gap-3">
                    <!-- Space Selector Dropdown -->
                    <div ref="spaceDropdownRef" class="dropdown nav-space-selector" v-if="currentUser" @mouseleave="showSpaceDropdown = false">
                        <button class="btn btn-outline-light dropdown-toggle" type="button" @click="toggleSpaceDropdown">
                            <span v-if="currentSpace">{{ currentSpace.name }}</span>
                            <span v-else>Select Space</span>
                        </button>
                        <ul class="dropdown-menu" :class="{ show: showSpaceDropdown }">
                            <li v-for="space in spaces" :key="space.id">
                                <a class="dropdown-item" @click="selectSpace(space)">
                                    {{ space.name }}
                                </a>
                            </li>
                            <li><hr class="dropdown-divider" /></li>
                            <li>
                                <button v-if="canCreateSpaces" class="dropdown-item" @click="showCreateSpaceModal = true">
                                    <i class="mdi mdi-plus-circle-outline me-1" aria-hidden="true"></i>
                                    New Space
                                </button>
                            </li>
                        </ul>
                    </div>

                    <!-- Search -->
                    <div class="search-box nav-search">
                        <input type="text" class="form-control" placeholder="Search notes & task lists..." v-model="searchQuery" @keyup.enter="performSearch" />
                    </div>

                    <!-- Theme Toggle -->
                    <button
                        class="btn btn-outline-light theme-toggle"
                        type="button"
                        :aria-label="isDarkMode ? 'Switch to light mode' : 'Switch to dark mode'"
                        :title="isDarkMode ? 'Switch to light mode' : 'Switch to dark mode'"
                        @click="isDarkMode = !isDarkMode"
                    >
                        <i :class="isDarkMode ? 'mdi mdi-weather-sunny' : 'mdi mdi-weather-night'" aria-hidden="true"></i>
                    </button>

                    <!-- User Menu -->
                    <div ref="userDropdownRef" class="dropdown nav-user-menu" v-if="currentUser" @mouseleave="showUserMenu = false">
                        <button class="btn btn-outline-light dropdown-toggle" type="button" @click="toggleUserMenu">
                            {{ currentUser.username }}
                        </button>
                        <ul class="dropdown-menu dropdown-menu-end" :class="{ show: showUserMenu }">
                            <li v-if="authStore.isAdmin"><button class="dropdown-item" @click="openAdminPanel">Admin Panel</button></li>
                            <li v-if="authStore.isAdmin"><hr class="dropdown-divider" /></li>
                            <li><a class="dropdown-item" @click="logout">Logout</a></li>
                        </ul>
                    </div>
                </div>
            </div>
        </nav>

        <div class="app-main d-flex" v-if="currentSpace">
            <!-- Mobile backdrop -->
            <div v-if="showSidebar" class="sidebar-backdrop" :style="offcanvasOffsetStyle" @click="showSidebar = false"></div>

            <!-- Sidebar -->
            <aside class="sidebar bg-light border-end" :class="{ open: showSidebar }" :style="offcanvasOffsetStyle">
                <div class="sidebar-header p-3">
                    <h6 class="mb-0">Categories</h6>
                    <button v-if="canCreateCategories" class="btn btn-sm btn-outline-primary mt-2 w-100" @click="openCreateCategoryModal">
                        <i class="mdi mdi-folder-plus-outline me-1" aria-hidden="true"></i>
                        New Category
                    </button>
                </div>

                <div class="sidebar-content p-2">
                    <CategoryTree
                        :categories="categoryTree"
                        :on-select-note="selectNote"
                        :on-select-category="selectCategory"
                        :on-add-subcategory="openCreateSubcategoryModal"
                        :on-edit-category="openEditCategoryModal"
                        :on-delete-category="requestRemoveCategory"
                        :on-select-task-list="selectTaskList"
                        :can-create-categories="canCreateCategories"
                        :can-edit-categories="canEditCategories"
                        :can-delete-categories="canDeleteCategories"
                    />
                </div>

                <div v-if="canManageSpaceSettings" class="sidebar-footer p-2 border-top">
                    <button class="btn btn-sm btn-outline-secondary w-100" @click="showSpaceSettingsModal = true">
                        <i class="mdi mdi-cog-outline me-1" aria-hidden="true"></i>
                        Space Settings
                    </button>
                </div>
            </aside>

            <!-- Main Content -->
            <main class="main-content flex-grow-1">
                <div class="toolbar p-3 border-bottom">
                    <div class="row align-items-center">
                        <div class="col">
                            <h5 class="mb-0 breadcrumb-title">
                                <template v-for="(crumb, index) in breadcrumbItems" :key="`${crumb.label}-${index}`">
                                    <button v-if="crumb.clickable" type="button" class="breadcrumb-link" @click="crumb.onClick">
                                        {{ crumb.label }}
                                    </button>
                                    <span v-else>{{ crumb.label }}</span>
                                    <span v-if="index < breadcrumbItems.length - 1" class="breadcrumb-separator"> / </span>
                                </template>
                            </h5>
                        </div>
                        <div class="col-auto d-flex align-items-center">
                            <div
                                v-if="(activeView === 'notes' || activeView === 'tasks') && (canCreateNotes || canCreateTasks)"
                                ref="createDropdownRef"
                                class="dropdown me-2"
                                @mouseleave="showCreateMenu = false"
                            >
                                <button class="btn btn-primary dropdown-toggle action-button" type="button" aria-label="Create" title="Create" @click="toggleCreateMenu">
                                    <i class="mdi mdi-plus-circle-outline me-1" aria-hidden="true"></i>
                                    <span class="action-label">Create</span>
                                </button>
                                <ul class="dropdown-menu dropdown-menu-end" :class="{ show: showCreateMenu }">
                                    <li v-if="activeView === 'notes' && canCreateNotes">
                                        <button class="dropdown-item" type="button" @click="openCreateNoteModalFromMenu">
                                            <i class="mdi mdi-note-plus-outline me-1" aria-hidden="true"></i>
                                            New Note
                                        </button>
                                    </li>
                                    <li v-if="activeView === 'notes' && canCreateTasks">
                                        <button class="dropdown-item" type="button" @click="openCreateTaskListModalFromMenu">
                                            <i class="mdi mdi-format-list-checkbox me-1" aria-hidden="true"></i>
                                            New Task List
                                        </button>
                                    </li>
                                    <li v-if="activeView === 'tasks' && canCreateTasks">
                                        <button class="dropdown-item" type="button" @click="openTaskCreateModal">
                                            <i class="mdi mdi-checkbox-marked-circle-plus-outline me-1" aria-hidden="true"></i>
                                            New Task
                                        </button>
                                    </li>
                                </ul>
                            </div>
                            <div v-if="activeView === 'notes' && (!selectedNote || isSearchRoute)" class="btn-group me-2 d-none d-md-flex" role="group" aria-label="View mode">
                                <button
                                    type="button"
                                    class="btn action-button"
                                    :class="noteViewMode === 'grid' ? 'btn-secondary' : 'btn-outline-secondary'"
                                    aria-label="Grid view"
                                    title="Grid view"
                                    @click="noteViewMode = 'grid'"
                                >
                                    <i class="mdi mdi-view-grid-outline" aria-hidden="true"></i>
                                </button>
                                <button
                                    type="button"
                                    class="btn action-button"
                                    :class="noteViewMode === 'list' ? 'btn-secondary' : 'btn-outline-secondary'"
                                    aria-label="List view"
                                    title="List view"
                                    @click="noteViewMode = 'list'"
                                >
                                    <i class="mdi mdi-view-list-outline" aria-hidden="true"></i>
                                </button>
                            </div>
                            <button
                                v-if="activeView === 'notes' && canEditNotes && selectedNote && !isEditingNote && !isSearchRoute"
                                class="btn btn-outline-secondary me-2 action-button"
                                aria-label="Edit note"
                                title="Edit note"
                                @click="startEditingNote"
                            >
                                <i class="mdi mdi-pencil-outline me-1" aria-hidden="true"></i>
                                <span class="action-label">Edit Note</span>
                            </button>
                            <button
                                v-if="activeView === 'notes' && canShareSelectedNote && !isEditingNote && !isSearchRoute"
                                class="btn btn-outline-primary me-2 action-button"
                                :aria-label="shareCopied ? 'Link copied' : 'Share note'"
                                :title="shareCopied ? 'Link copied' : 'Share note'"
                                @click="copyShareLink"
                            >
                                <i class="mdi mdi-share-variant-outline me-1" aria-hidden="true"></i>
                                <span class="action-label">{{ shareCopied ? "Copied" : "Share" }}</span>
                            </button>
                        </div>
                    </div>
                </div>

                <AppWorkspaceContent
                    :active-view="activeView"
                    :tasks="tasks"
                    :task-statuses="taskStatuses"
                    :selected-task-list="selectedTaskList"
                    :is-search-route="isSearchRoute"
                    :search-items="searchItems"
                    :search-query="searchQuery"
                    :search-page="searchPage"
                    :search-page-size="searchPageSize"
                    :note-view-mode="noteViewMode"
                    :selected-note="selectedNote"
                    :is-editing-note="isEditingNote"
                    :category-options="categoryOptions"
                    :can-delete-notes="canDeleteNotes"
                    :current-space-id="currentSpace?.id"
                    :linked-tasks-for-selected-note="linkedTasksForSelectedNote"
                    :displayed-items="displayedItems"
                    :can-load-more-main-notes="canLoadMoreMainNotes"
                    :is-loading-more-main-notes="spaceStore.notesLoading"
                    @select-task="openTaskDetail"
                    @filter-change="applyTaskFilters"
                    @update-task-status="updateTaskStatusFromBoard"
                    @edit-task-list="showEditTaskListModal = true"
                    @select-note="selectSearchResultNote"
                    @select-task-list="selectTaskList"
                    @page-change="setSearchPage"
                    @save-note="updateNote"
                    @delete-note="deleteNote"
                    @cancel-edit-note="cancelEditingNote"
                    @open-linked-task="openLinkedTaskFromNote"
                    @load-more="loadMoreMainNotes"
                />
            </main>
        </div>

        <div v-else-if="spaces.length === 0" class="d-flex align-items-center justify-content-center min-vh-100">
            <div class="text-center">
                <i class="mdi mdi-folder-outline" style="font-size: 5rem; color: #6c757d; margin-bottom: 1rem; display: block"></i>
                <h2 class="text-muted mb-3">No Spaces Yet</h2>
                <p class="text-muted mb-4" style="font-size: 1.1rem">Create a space to start organizing your notes</p>
                <button v-if="canCreateSpaces" class="btn btn-primary" @click="showCreateSpaceModal = true">
                    <i class="mdi mdi-plus-circle-outline me-2" aria-hidden="true"></i>
                    Create Your First Space
                </button>
            </div>
        </div>

        <AppModalHost
            :show-create-space-modal="showCreateSpaceModal"
            :show-create-category-modal="showCreateCategoryModal"
            :editing-category="editingCategory"
            :category-parent-options="categoryParentOptions"
            :category-modal-parent-id="categoryModalParentId"
            :show-create-note-modal="showCreateNoteModal"
            :category-options="categoryOptions"
            :selected-category-id="selectedCategory?.id || null"
            :show-create-task-list-modal="showCreateTaskListModal"
            :show-space-settings-modal="showSpaceSettingsModal"
            :current-space="currentSpace"
            :can-manage-space-settings="canManageSpaceSettings"
            :show-task-modal="showTaskModal"
            :task-modal-draft="taskModalDraft"
            :task-statuses="taskStatuses"
            :task-parent-options="taskParentOptions"
            :task-detail-subtasks="taskDetail?.subtasks || []"
            @close-create-space="showCreateSpaceModal = false"
            @create-space="createSpace"
            @close-create-category="closeCategoryModal"
            @submit-category="submitCategory"
            @close-create-note="showCreateNoteModal = false"
            @create-note="createNote"
            @close-create-task-list="showCreateTaskListModal = false"
            @create-task-list="createTaskList"
            @close-space-settings="showSpaceSettingsModal = false"
            @saved-space="applyUpdatedSpace"
            @deleted-space="handleSpaceDeleted"
            @close-task-modal="showTaskModal = false"
            @save-task="saveTask"
            @delete-task="requestRemoveTask"
            @transition-task="transitionTaskStatus"
            @create-subtask="createSubtask"
            @open-task="openTaskDetail"
        />

        <teleport to="body">
            <div v-if="showUnlockModal" class="modal fade show d-block" tabindex="-1" role="dialog" aria-modal="true" @click.self="closeUnlockModal">
                <div class="modal-dialog modal-dialog-centered" role="document">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title d-flex align-items-center gap-2 mb-0">
                                <i class="mdi mdi-lock-outline" aria-hidden="true"></i>
                                <span>Unlock Note</span>
                            </h5>
                            <button type="button" class="btn-close" aria-label="Close" @click="closeUnlockModal"></button>
                        </div>
                        <div class="modal-body">
                            <p class="text-muted mb-3">
                                Enter the password to view <strong>{{ unlockTargetNote?.title }}</strong
                                >.
                            </p>
                            <label class="form-label" for="unlockNotePassword">Password</label>
                            <input id="unlockNotePassword" v-model="unlockPassword" type="password" class="form-control" maxlength="128" @keyup.enter="unlockProtectedNote" />
                            <div v-if="unlockError" class="text-danger small mt-2">{{ unlockError }}</div>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-outline-secondary" @click="closeUnlockModal">Cancel</button>
                            <button type="button" class="btn btn-primary" :disabled="unlockingNote" @click="unlockProtectedNote">
                                {{ unlockingNote ? "Unlocking..." : "Unlock" }}
                            </button>
                        </div>
                    </div>
                </div>
            </div>
            <div v-if="showUnlockModal" class="modal-backdrop fade show"></div>
        </teleport>

        <EditTaskListModal
            v-if="showEditTaskListModal && selectedTaskList"
            :task-list="selectedTaskList"
            :statuses="taskStatuses"
            :category-options="categoryOptions"
            :can-delete-task-list="canDeleteTasks"
            @close="showEditTaskListModal = false"
            @update-task-list="updateTaskListFromModal"
            @reorder-status="reorderTaskStatuses"
            @create-status="createTaskStatus"
            @rename-status="renameTaskStatus"
            @delete-status="requestDeleteTaskStatus"
            @delete-task-list="requestRemoveTaskList"
        />

        <ConfirmActionModal
            :visible="showTaskDeleteConfirmModal"
            :title="taskDeleteConfirmTitle"
            :message="taskDeleteConfirmMessage"
            :busy="taskDeleteConfirmBusy"
            @close="closeTaskDeleteConfirmModal"
            @confirm="confirmTaskDeleteAction"
        />
    </div>
</template>

<script setup>
import { ref, computed, nextTick, onBeforeUnmount, onMounted, watch } from "vue";
import { useRouter, useRoute } from "vue-router";
import { useAuthStore } from "../stores/authStore";
import { useSpaceStore } from "../stores/spaceStore";
import CategoryTree from "../components/CategoryTree.vue";
import AppWorkspaceContent from "../components/app/AppWorkspaceContent.vue";
import AppModalHost from "../components/app/AppModalHost.vue";
import ConfirmActionModal from "../components/ConfirmActionModal.vue";
import EditTaskListModal from "../components/EditTaskListModal.vue";
import { sortNotesByPriority } from "../utils/noteSort";
import apiClient from "../services/apiClient";

const router = useRouter();
const route = useRoute();
const authStore = useAuthStore();
const spaceStore = useSpaceStore();

const showSpaceDropdown = ref(false);
const showUserMenu = ref(false);
const showSpaceSettingsModal = ref(false);
const showCreateSpaceModal = ref(false);
const showCreateCategoryModal = ref(false);
const showCreateNoteModal = ref(false);
const showCreateTaskListModal = ref(false);
const showEditTaskListModal = ref(false);
const showSidebar = ref(false);
const navbarRef = ref(null);
const navbarHeight = ref(56);
const spaceDropdownRef = ref(null);
const userDropdownRef = ref(null);
const createDropdownRef = ref(null);
const searchQuery = ref("");
const selectedNote = ref(null);
const selectedCategory = ref(null);
const isEditingNote = ref(false);
const editingCategory = ref(null);
const categoryModalParentId = ref(null);
const shareCopied = ref(false);
const shareCopyTimeout = ref(null);
const noteViewMode = ref(localStorage.getItem("noteViewMode") || "grid");
watch(noteViewMode, (val) => localStorage.setItem("noteViewMode", val));
const isDarkMode = ref(localStorage.getItem("theme") === "dark");
const applyTheme = (dark) => {
    document.documentElement.setAttribute("data-bs-theme", dark ? "dark" : "light");
    localStorage.setItem("theme", dark ? "dark" : "light");
};
watch(isDarkMode, applyTheme);
applyTheme(isDarkMode.value);
const showUnlockModal = ref(false);
const unlockTargetNote = ref(null);
const unlockPassword = ref("");
const unlockError = ref("");
const unlockingNote = ref(false);
const taskFilters = ref({
    taskListId: null,
    statusId: null,
    parentTaskId: null,
});
const selectedTaskList = ref(null);
const showTaskModal = ref(false);
const taskDetail = ref(null);
const taskModalDraft = ref(null);
const linkedTasksForSelectedNote = ref([]);
const showCreateMenu = ref(false);
const showTaskDeleteConfirmModal = ref(false);
const taskDeleteConfirmBusy = ref(false);
const taskDeleteIntent = ref({
    type: "",
    payload: null,
});

const currentUser = computed(() => authStore.user);
const isSearchRoute = computed(() => route.name === "Search");
const isDashboardTaskRoute = computed(() => route.name === "DashboardTaskList");
const activeView = computed(() => (isDashboardTaskRoute.value ? "tasks" : "notes"));
const spaces = computed(() => spaceStore.spaces);
const currentSpace = computed(() => spaceStore.currentSpace);
const searchResults = computed(() => sortNotesByPriority(spaceStore.searchResults));
const searchItems = computed(() => {
    const query = searchQuery.value.toLowerCase();
    const noteItems = searchResults.value.map((note) => ({
        ...note,
        kind: "note",
    }));
    const matchingTaskLists = (spaceStore.taskLists || []).filter((tl) => tl.name.toLowerCase().includes(query));
    const taskListItems = matchingTaskLists.map((tl) => ({
        ...tl,
        kind: "task-list",
    }));
    return [...taskListItems, ...noteItems];
});
const searchPageSize = 12;
const searchPage = computed(() => {
    const pageValue = Number.parseInt(route.query.page || "1", 10);
    if (Number.isNaN(pageValue) || pageValue < 1) {
        return 1;
    }
    return pageValue;
});
const categoryTree = computed(() => spaceStore.categoryTree);
const canCreateSpaces = computed(() => authStore.hasPermission("space.create"));
const canCreateCategories = computed(() => authStore.hasSpacePermission(currentSpace.value, "category.create"));
const canEditCategories = computed(() => authStore.hasSpacePermission(currentSpace.value, "category.edit"));
const canDeleteCategories = computed(() => authStore.hasSpacePermission(currentSpace.value, "category.delete"));
const canCreateNotes = computed(() => authStore.hasSpacePermission(currentSpace.value, "note.create"));
const canEditNotes = computed(() => authStore.hasSpacePermission(currentSpace.value, "note.edit"));
const canDeleteNotes = computed(() => authStore.hasSpacePermission(currentSpace.value, "note.delete"));
const canCreateTasks = computed(() => authStore.hasSpacePermission(currentSpace.value, "tasks.create"));
const canEditTasks = computed(() => authStore.hasSpacePermission(currentSpace.value, "tasks.edit"));
const canDeleteTasks = computed(() => authStore.hasSpacePermission(currentSpace.value, "tasks.delete"));
const canShareSelectedNote = computed(() => !!selectedNote.value?.is_public && !!currentSpace.value?.id && !!selectedNote.value?.id);
const offcanvasOffsetStyle = computed(() => ({
    top: `${navbarHeight.value}px`,
}));
const canManageSpaceSettings = computed(
    () =>
        authStore.hasPermission("space.edit") ||
        authStore.hasSpacePermission(currentSpace.value, "settings.edit") ||
        authStore.hasSpacePermission(currentSpace.value, "settings.member.manage") ||
        authStore.hasSpacePermission(currentSpace.value, "settings.member.view"),
);

const flattenCategories = (items, trail = []) =>
    items.flatMap((category) => {
        const nextTrail = [...trail, category.name];
        const label = nextTrail.join("/");
        return [{ id: category.id, name: category.name, label }, ...(category.subcategories?.length ? flattenCategories(category.subcategories, nextTrail) : [])];
    });

const categoryOptions = computed(() => flattenCategories(categoryTree.value));
const categoryParentOptions = computed(() => {
    if (!editingCategory.value) {
        return categoryOptions.value;
    }
    return categoryOptions.value.filter((category) => category.id !== editingCategory.value.id);
});

const collectNotesFromCategory = (category, bucket = []) => {
    if (!category) {
        return bucket;
    }
    if (Array.isArray(category.notes) && category.notes.length) {
        bucket.push(...category.notes);
    }
    for (const subcategory of category.subcategories || []) {
        collectNotesFromCategory(subcategory, bucket);
    }
    return bucket;
};

const collectTaskListsFromCategory = (category, bucket = []) => {
    if (!category) {
        return bucket;
    }
    if (Array.isArray(category.task_lists) && category.task_lists.length) {
        bucket.push(...category.task_lists);
    }
    for (const subcategory of category.subcategories || []) {
        collectTaskListsFromCategory(subcategory, bucket);
    }
    return bucket;
};

const displayedNotes = computed(() => {
    if (!selectedCategory.value) {
        return sortNotesByPriority(spaceStore.notes);
    }
    return sortNotesByPriority(collectNotesFromCategory(selectedCategory.value, []));
});

const displayedTaskLists = computed(() => {
    if (!selectedCategory.value) {
        return [...(spaceStore.taskLists || [])].sort((left, right) => left.name.localeCompare(right.name));
    }
    return [...collectTaskListsFromCategory(selectedCategory.value, [])].sort((left, right) => left.name.localeCompare(right.name));
});

const displayedItems = computed(() => {
    const taskListItems = displayedTaskLists.value.map((taskList) => ({
        ...taskList,
        kind: "task-list",
    }));
    const noteItems = displayedNotes.value.map((note) => ({
        ...note,
        kind: "note",
    }));
    return [...taskListItems, ...noteItems];
});
const tasks = computed(() => spaceStore.tasks || []);
const taskLists = computed(() => spaceStore.taskLists || []);
const taskStatuses = computed(() => spaceStore.taskStatuses || []);
const taskDeleteConfirmTitle = computed(() => {
    if (taskDeleteIntent.value.type === "task-status") {
        return "Delete Task Status";
    }
    if (taskDeleteIntent.value.type === "task-list") {
        return "Delete Task List";
    }
    if (taskDeleteIntent.value.type === "task") {
        return "Delete Task";
    }
    if (taskDeleteIntent.value.type === "category") {
        return "Delete Category";
    }
    return "Confirm Deletion";
});
const taskDeleteConfirmMessage = computed(() => {
    if (taskDeleteIntent.value.type === "task-status") {
        const name = taskDeleteIntent.value.payload?.name || "this status";
        return `Delete status "${name}"? This action cannot be undone.`;
    }
    if (taskDeleteIntent.value.type === "task-list") {
        const name = taskDeleteIntent.value.payload?.name || "this task list";
        return `Delete task list "${name}" and all associated tasks? This action cannot be undone.`;
    }
    if (taskDeleteIntent.value.type === "task") {
        const title = taskDeleteIntent.value.payload?.title || "this task";
        return `Delete task "${title}"? This action cannot be undone.`;
    }
    if (taskDeleteIntent.value.type === "category") {
        const name = taskDeleteIntent.value.payload?.name || "this category";
        return `Delete category "${name}"? Notes will be moved to uncategorized.`;
    }
    return "Are you sure you want to continue?";
});
const initialTaskStatusId = computed(() => {
    if (!taskStatuses.value.length) {
        return null;
    }
    return [...taskStatuses.value].sort((a, b) => (a.order ?? 0) - (b.order ?? 0))[0]?.id || null;
});
const taskParentOptions = computed(() => tasks.value.filter((task) => task.depth < 2));

const dashboardNoteRoute = (spaceId, noteId = undefined) => ({
    name: "DashboardNote",
    params: {
        spaceId,
        ...(noteId ? { noteId } : {}),
    },
});

const dashboardTaskRoute = (spaceId, taskListId) => ({
    name: "DashboardTaskList",
    params: { spaceId, taskListId },
});

const canLoadMoreMainNotes = computed(() => {
    if (selectedCategory.value || selectedNote.value) {
        return false;
    }
    if (isSearchRoute.value) {
        return false;
    }
    return spaceStore.notesHasMore;
});

const findCategoryPath = (categories, categoryId, trail = []) => {
    for (const category of categories || []) {
        const nextTrail = [...trail, category];
        if (category.id === categoryId) {
            return nextTrail;
        }
        const nested = findCategoryPath(category.subcategories || [], categoryId, nextTrail);
        if (nested) {
            return nested;
        }
    }
    return null;
};

const openSpaceHome = () => {
    selectedNote.value = null;
    selectedCategory.value = null;
    isEditingNote.value = false;
    showUnlockModal.value = false;
    unlockTargetNote.value = null;
    unlockPassword.value = "";
    unlockError.value = "";
    searchQuery.value = "";
    selectedTaskList.value = null;
    taskFilters.value = {
        taskListId: null,
        statusId: null,
        parentTaskId: null,
    };
    spaceStore.clearSearchResults();
    if (currentSpace.value?.id) {
        router.push(dashboardNoteRoute(currentSpace.value.id));
    }
    if (currentSpace.value?.id) {
        spaceStore.fetchNotes(currentSpace.value.id, { reset: true });
    }
};

const openCategoryFromBreadcrumb = (category) => {
    selectCategory(category);
};

const breadcrumbItems = computed(() => {
    if (!currentSpace.value) {
        return [];
    }

    if (isSearchRoute.value) {
        return [
            {
                label: currentSpace.value.name,
                clickable: true,
                onClick: openSpaceHome,
            },
            {
                label: searchQuery.value.trim() ? `Search: ${searchQuery.value.trim()}` : "Search",
                clickable: false,
                onClick: null,
            },
        ];
    }

    const items = [
        {
            label: currentSpace.value.name,
            clickable: !!(selectedNote.value || selectedCategory.value),
            onClick: openSpaceHome,
        },
    ];

    if (selectedNote.value) {
        const noteCategoryId = selectedNote.value.category_id;
        if (noteCategoryId) {
            const categoryTrail = findCategoryPath(categoryTree.value, noteCategoryId) || [];
            for (const category of categoryTrail) {
                items.push({
                    label: category.name,
                    clickable: true,
                    onClick: () => openCategoryFromBreadcrumb(category),
                });
            }
        }

        items.push({
            label: selectedNote.value.title,
            clickable: false,
            onClick: null,
        });
        return items;
    }

    if (isDashboardTaskRoute.value && selectedTaskList.value) {
        const taskListCategoryId = selectedTaskList.value.category_id;
        if (taskListCategoryId) {
            const categoryTrail = findCategoryPath(categoryTree.value, taskListCategoryId) || [];
            for (const category of categoryTrail) {
                items.push({
                    label: category.name,
                    clickable: true,
                    onClick: () => openCategoryFromBreadcrumb(category),
                });
            }
        }

        items.push({
            label: selectedTaskList.value.name,
            clickable: false,
            onClick: null,
        });
        return items;
    }

    if (selectedCategory.value) {
        const categoryTrail = findCategoryPath(categoryTree.value, selectedCategory.value.id) || [selectedCategory.value];
        for (let i = 0; i < categoryTrail.length; i++) {
            const category = categoryTrail[i];
            items.push({
                label: category.name,
                clickable: i < categoryTrail.length - 1,
                onClick: () => openCategoryFromBreadcrumb(category),
            });
        }
    }

    return items;
});

const bootstrapSpaces = async () => {
    await spaceStore.fetchSpaces();
    if (spaceStore.spaces.length === 0) {
        return;
    }

    const routeSpaceId = typeof route.params.spaceId === "string" ? route.params.spaceId : "";
    const storedSpaceId = localStorage.getItem("currentSpaceId");
    const targetSpace = spaceStore.spaces.find((space) => space.id === routeSpaceId) || spaceStore.spaces.find((space) => space.id === storedSpaceId) || spaceStore.spaces[0];
    if (targetSpace) {
        await spaceStore.selectSpace(targetSpace.id);
    }
};

onMounted(async () => {
    document.addEventListener("click", handleDocumentClick);
    document.addEventListener("keydown", handleEscapeKey);
    window.addEventListener("resize", updateNavbarHeight);
    await nextTick();
    updateNavbarHeight();

    if (authStore.isAuthenticated) {
        await bootstrapSpaces();
        await nextTick();
        updateNavbarHeight();
    }
});

onBeforeUnmount(() => {
    document.removeEventListener("click", handleDocumentClick);
    document.removeEventListener("keydown", handleEscapeKey);
    window.removeEventListener("resize", updateNavbarHeight);
    clearTimeout(shareCopyTimeout.value);
});

watch(
    () => authStore.isAuthenticated,
    async (isAuthenticated) => {
        if (!isAuthenticated) {
            return;
        }
        await bootstrapSpaces();
        await nextTick();
        updateNavbarHeight();
    },
);

watch(
    () => route.fullPath,
    async () => {
        await nextTick();
        updateNavbarHeight();
    },
);

watch(
    [() => route.path, () => route.query.q, () => currentSpace.value?.id],
    async ([path, routeQuery, spaceId]) => {
        if (path !== "/search") {
            return;
        }

        selectedNote.value = null;
        selectedCategory.value = null;
        isEditingNote.value = false;

        const q = typeof routeQuery === "string" ? routeQuery.trim() : "";
        searchQuery.value = q;

        if (!spaceId || !q) {
            spaceStore.clearSearchResults();
            return;
        }

        await spaceStore.searchNotes(q);
    },
    { immediate: true },
);

watch(
    [() => route.name, () => route.params.spaceId, () => route.params.noteId, () => route.params.taskListId, () => currentSpace.value?.id],
    async ([routeName, routeSpaceId, routeNoteId, routeTaskListId, currentSpaceId]) => {
        if (routeName !== "DashboardNote" && routeName !== "DashboardTaskList") {
            return;
        }

        const spaceId = typeof routeSpaceId === "string" ? routeSpaceId : "";
        if (!spaceId) {
            return;
        }

        if (spaceId !== currentSpaceId) {
            await spaceStore.selectSpace(spaceId);
            localStorage.setItem("currentSpaceId", spaceId);
            return;
        }

        if (routeName === "DashboardTaskList") {
            const taskListId = typeof routeTaskListId === "string" ? routeTaskListId : "";
            if (!taskListId) {
                return;
            }

            selectedNote.value = null;
            isEditingNote.value = false;
            selectedCategory.value = null;
            selectedTaskList.value = taskLists.value.find((list) => list.id === taskListId) || null;
            await spaceStore.fetchTaskStatuses(currentSpace.value?.id, taskListId);
            await applyTaskFilters({ taskListId });
            return;
        }

        const noteId = typeof routeNoteId === "string" ? routeNoteId : "";
        selectedTaskList.value = null;
        isEditingNote.value = false;
        showTaskModal.value = false;

        if (!noteId) {
            selectedNote.value = null;
            return;
        }

        if (selectedNote.value?.id === noteId) {
            return;
        }

        try {
            const response = await apiClient.get(`/api/v1/spaces/${spaceId}/notes/${noteId}`);
            if (response.data?.is_password_protected) {
                unlockTargetNote.value = response.data;
                unlockPassword.value = "";
                unlockError.value = "";
                showUnlockModal.value = true;
                selectedNote.value = null;
                selectedCategory.value = null;
                router.push(dashboardNoteRoute(spaceId));
                return;
            }
            selectedNote.value = response.data;
            selectedCategory.value = null;
        } catch {
            selectedNote.value = null;
        }
    },
    { immediate: true },
);

watch(
    () => selectedNote.value?.id,
    async (noteId) => {
        shareCopied.value = false;
        clearTimeout(shareCopyTimeout.value);

        if (!noteId || !currentSpace.value?.id) {
            linkedTasksForSelectedNote.value = [];
            return;
        }

        try {
            linkedTasksForSelectedNote.value = await spaceStore.fetchTasksForNote(currentSpace.value.id, noteId);
        } catch {
            linkedTasksForSelectedNote.value = [];
        }
    },
);

const toggleCreateMenu = () => {
    showCreateMenu.value = !showCreateMenu.value;
    if (showCreateMenu.value) {
        showSpaceDropdown.value = false;
        showUserMenu.value = false;
    }
};

const toggleSpaceDropdown = () => {
    showSpaceDropdown.value = !showSpaceDropdown.value;
    if (showSpaceDropdown.value) {
        showUserMenu.value = false;
    }
};

const toggleUserMenu = () => {
    showUserMenu.value = !showUserMenu.value;
    if (showUserMenu.value) {
        showSpaceDropdown.value = false;
    }
};

const updateNavbarHeight = () => {
    navbarHeight.value = navbarRef.value?.offsetHeight || 56;
};

const handleDocumentClick = (event) => {
    const target = event.target;

    if (showSpaceDropdown.value && spaceDropdownRef.value && !spaceDropdownRef.value.contains(target)) {
        showSpaceDropdown.value = false;
    }

    if (showUserMenu.value && userDropdownRef.value && !userDropdownRef.value.contains(target)) {
        showUserMenu.value = false;
    }

    if (showCreateMenu.value && createDropdownRef.value && !createDropdownRef.value.contains(target)) {
        showCreateMenu.value = false;
    }
};

const handleEscapeKey = (event) => {
    if (event.key !== "Escape") {
        return;
    }
    showSpaceDropdown.value = false;
    showUserMenu.value = false;
    showCreateMenu.value = false;
    showSidebar.value = false;
};

const copyShareLink = async () => {
    if (!canShareSelectedNote.value) {
        return;
    }

    const shareUrl = `${window.location.origin}/s/${currentSpace.value.id}/n/${selectedNote.value.id}`;

    try {
        if (navigator.clipboard?.writeText) {
            await navigator.clipboard.writeText(shareUrl);
        } else {
            const textArea = document.createElement("textarea");
            textArea.value = shareUrl;
            textArea.setAttribute("readonly", "");
            textArea.style.position = "fixed";
            textArea.style.opacity = "0";
            document.body.appendChild(textArea);
            textArea.select();
            document.execCommand("copy");
            document.body.removeChild(textArea);
        }

        shareCopied.value = true;
        clearTimeout(shareCopyTimeout.value);
        shareCopyTimeout.value = setTimeout(() => {
            shareCopied.value = false;
        }, 1800);
    } catch {
        alert("Unable to copy share link.");
    }
};

const selectNote = async (note) => {
    if (note?.is_password_protected) {
        unlockTargetNote.value = note;
        unlockPassword.value = "";
        unlockError.value = "";
        showUnlockModal.value = true;
        selectedNote.value = null;
        selectedCategory.value = null;
        selectedTaskList.value = null;
        isEditingNote.value = false;
        showSidebar.value = false;
        if (currentSpace.value?.id) {
            router.push(dashboardNoteRoute(currentSpace.value.id));
        }
        return;
    }

    if (!note?.id || !currentSpace.value?.id) {
        return;
    }

    try {
        const response = await apiClient.get(`/api/v1/spaces/${currentSpace.value.id}/notes/${note.id}`);
        selectedNote.value = response.data;
        selectedCategory.value = null;
        selectedTaskList.value = null;
        isEditingNote.value = false;
        showSidebar.value = false;
        if (currentSpace.value?.id) {
            router.push(dashboardNoteRoute(currentSpace.value.id, response.data.id));
        }
    } catch {
        alert("Unable to load note content.");
    }
};

const closeUnlockModal = () => {
    showUnlockModal.value = false;
    unlockTargetNote.value = null;
    unlockPassword.value = "";
    unlockError.value = "";
    unlockingNote.value = false;
};

const unlockProtectedNote = async () => {
    if (!unlockTargetNote.value?.id || !currentSpace.value?.id) {
        closeUnlockModal();
        return;
    }
    if (!unlockPassword.value.trim()) {
        unlockError.value = "Password is required.";
        return;
    }

    unlockingNote.value = true;
    unlockError.value = "";
    try {
        const response = await apiClient.post(`/api/v1/spaces/${currentSpace.value.id}/notes/${unlockTargetNote.value.id}/unlock`, {
            password: unlockPassword.value,
        });
        selectedNote.value = response.data;
        selectedCategory.value = null;
        selectedTaskList.value = null;
        isEditingNote.value = false;
        showSidebar.value = false;
        if (currentSpace.value?.id) {
            router.push(dashboardNoteRoute(currentSpace.value.id, response.data.id));
        }
        closeUnlockModal();
    } catch (error) {
        unlockError.value = error?.response?.data || "Invalid password.";
    } finally {
        unlockingNote.value = false;
    }
};

const selectCategory = (category) => {
    selectedCategory.value = category;
    selectedTaskList.value = null;
    selectedNote.value = null;
    isEditingNote.value = false;
    showSidebar.value = false;
    if (currentSpace.value?.id) {
        router.push(dashboardNoteRoute(currentSpace.value.id));
    }
};

const selectTaskList = async (taskList) => {
    selectedTaskList.value = taskList;
    selectedCategory.value = null;
    selectedNote.value = null;
    isEditingNote.value = false;
    showSidebar.value = false;
    if (currentSpace.value?.id && taskList?.id) {
        await router.push(dashboardTaskRoute(currentSpace.value.id, taskList.id));
        await spaceStore.fetchTaskStatuses(currentSpace.value.id, taskList.id);
    }

    await applyTaskFilters({
        ...taskFilters.value,
        taskListId: taskList?.id || null,
    });
};

const performSearch = async () => {
    const q = searchQuery.value.trim();
    if (!q) {
        spaceStore.clearSearchResults();
        if (currentSpace.value?.id) {
            await router.push(dashboardNoteRoute(currentSpace.value.id));
        }
        if (currentSpace.value?.id) {
            await spaceStore.fetchNotes(currentSpace.value.id, { reset: true });
        }
        return;
    }

    if (route.path !== "/search" || route.query.q !== q || route.query.page !== "1") {
        await router.push({
            path: "/search",
            query: {
                q,
                page: "1",
            },
        });
    } else {
        await spaceStore.searchNotes(q);
    }
};

const setSearchPage = async (page) => {
    const q = typeof route.query.q === "string" ? route.query.q : "";
    if (!q) {
        return;
    }
    await router.push({
        path: "/search",
        query: {
            q,
            page: String(page),
        },
    });
};

const selectSearchResultNote = async (note) => {
    if (!note) {
        return;
    }
    await selectNote(note);
};

const loadMoreMainNotes = async () => {
    if (!currentSpace.value?.id || !canLoadMoreMainNotes.value) {
        return;
    }
    await spaceStore.loadMoreNotes(currentSpace.value.id);
};

const applyTaskFilters = async (filters) => {
    taskFilters.value = {
        ...taskFilters.value,
        ...filters,
        taskListId: selectedTaskList.value?.id || taskFilters.value.taskListId || null,
    };
    if (!currentSpace.value?.id) {
        return;
    }
    await spaceStore.fetchTasks(currentSpace.value.id, taskFilters.value);
};

const openTaskCreateModal = () => {
    if (!canCreateTasks.value) {
        return;
    }
    if (!selectedTaskList.value?.id) {
        alert("Select a task list first.");
        return;
    }
    taskDetail.value = null;
    taskModalDraft.value = {
        title: "",
        description: "",
        task_list_id: selectedTaskList.value?.id || null,
        status_id: initialTaskStatusId.value,
        parent_task_id: null,
        note_links: selectedNote.value?.id ? [selectedNote.value.id] : [],
        depth: 0,
    };
    showTaskModal.value = true;
};

const openTaskDetail = async (task) => {
    if (!currentSpace.value?.id || !task?.id) {
        return;
    }
    try {
        taskDetail.value = await spaceStore.getTask(currentSpace.value.id, task.id);
        taskModalDraft.value = taskDetail.value;
        showTaskModal.value = true;
    } catch {
        alert("Unable to open task details.");
    }
};

const saveTask = async (payload) => {
    if (!currentSpace.value?.id) {
        return;
    }
    try {
        if (payload.id) {
            if (!canEditTasks.value) {
                return;
            }
            const updated = await spaceStore.updateTask(currentSpace.value.id, payload.id, payload);
            await openTaskDetail(updated);
        } else {
            if (!canCreateTasks.value) {
                return;
            }
            const created = await spaceStore.createTask(currentSpace.value.id, payload);
            await openTaskDetail(created);
        }
        if (selectedNote.value?.id) {
            linkedTasksForSelectedNote.value = await spaceStore.fetchTasksForNote(currentSpace.value.id, selectedNote.value.id);
        }
    } catch (error) {
        alert(error?.response?.data || "Failed to save task.");
    }
};

const requestRemoveTask = (task) => {
    if (!currentSpace.value?.id || !task?.id || !canDeleteTasks.value) {
        return;
    }
    showTaskModal.value = false;
    taskDeleteIntent.value = {
        type: "task",
        payload: task,
    };
    showTaskDeleteConfirmModal.value = true;
};

const removeTask = async (task) => {
    if (!currentSpace.value?.id || !task?.id || !canDeleteTasks.value) {
        return;
    }
    try {
        await spaceStore.deleteTask(currentSpace.value.id, task.id);
        showTaskModal.value = false;
        taskDetail.value = null;
        if (selectedNote.value?.id) {
            linkedTasksForSelectedNote.value = await spaceStore.fetchTasksForNote(currentSpace.value.id, selectedNote.value.id);
        }
    } catch (error) {
        alert(error?.response?.data || "Unable to delete task.");
        throw error;
    }
};

const transitionTaskStatus = async ({ taskId, direction }) => {
    if (!currentSpace.value?.id || !taskId) {
        return;
    }
    try {
        const updated = await spaceStore.transitionTask(currentSpace.value.id, taskId, direction);
        await openTaskDetail(updated);
        if (selectedNote.value?.id) {
            linkedTasksForSelectedNote.value = await spaceStore.fetchTasksForNote(currentSpace.value.id, selectedNote.value.id);
        }
    } catch (error) {
        alert(error?.response?.data || "Unable to change task status.");
    }
};

const createSubtask = (parentTask) => {
    if (!parentTask || (parentTask.depth ?? 0) >= 2) {
        alert("Maximum sub-task depth reached.");
        return;
    }
    taskDetail.value = null;
    taskModalDraft.value = {
        title: "",
        description: "",
        task_list_id: parentTask.task_list_id || selectedTaskList.value?.id || null,
        status_id: initialTaskStatusId.value,
        parent_task_id: parentTask.id,
        note_links: selectedNote.value?.id ? [selectedNote.value.id] : [],
        depth: Math.min((parentTask.depth ?? 0) + 1, 2),
    };
    showTaskModal.value = true;
};

const createTaskStatus = async (payload) => {
    if (!currentSpace.value?.id || !selectedTaskList.value?.id) {
        return;
    }
    try {
        await spaceStore.createTaskStatus(currentSpace.value.id, selectedTaskList.value.id, payload);
    } catch (error) {
        alert(error?.response?.data || "Unable to create status.");
    }
};

const renameTaskStatus = async (status) => {
    if (!currentSpace.value?.id || !selectedTaskList.value?.id || !status?.id) {
        return;
    }
    try {
        await spaceStore.updateTaskStatus(currentSpace.value.id, selectedTaskList.value.id, status.id, {
            name: status.name,
            color: status.color,
        });
    } catch (error) {
        alert(error?.response?.data || "Unable to update status.");
    }
};

const closeTaskDeleteConfirmModal = () => {
    if (taskDeleteConfirmBusy.value) {
        return;
    }
    showTaskDeleteConfirmModal.value = false;
    taskDeleteIntent.value = {
        type: "",
        payload: null,
    };
};

const requestDeleteTaskStatus = (status) => {
    if (!currentSpace.value?.id || !status?.id) {
        return;
    }
    taskDeleteIntent.value = {
        type: "task-status",
        payload: status,
    };
    showTaskDeleteConfirmModal.value = true;
};

const deleteTaskStatus = async (status) => {
    if (!currentSpace.value?.id || !selectedTaskList.value?.id || !status?.id) {
        return;
    }

    try {
        await spaceStore.deleteTaskStatus(currentSpace.value.id, selectedTaskList.value.id, status.id);
    } catch (error) {
        alert(error?.response?.data || "Unable to delete status.");
        throw error;
    }
};

const reorderTaskStatuses = async (orderedIds) => {
    if (!currentSpace.value?.id || !selectedTaskList.value?.id) {
        return;
    }
    try {
        await spaceStore.reorderTaskStatuses(currentSpace.value.id, selectedTaskList.value.id, orderedIds);
    } catch (error) {
        alert(error?.response?.data || "Unable to reorder statuses.");
    }
};

const updateTaskStatusFromBoard = async ({ taskId, currentStatusId, targetStatusId }) => {
    if (!currentSpace.value?.id || !taskId || !targetStatusId || currentStatusId === targetStatusId) {
        return;
    }

    const orderedStatuses = [...taskStatuses.value].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
    const currentIndex = orderedStatuses.findIndex((item) => item.id === currentStatusId);
    const targetIndex = orderedStatuses.findIndex((item) => item.id === targetStatusId);

    try {
        let updatedTask = null;
        if (currentIndex >= 0 && targetIndex >= 0) {
            const direction = targetIndex > currentIndex ? "forward" : "backward";
            const steps = Math.abs(targetIndex - currentIndex);
            for (let i = 0; i < steps; i++) {
                updatedTask = await spaceStore.transitionTask(currentSpace.value.id, taskId, direction);
            }
        } else {
            updatedTask = await spaceStore.updateTask(currentSpace.value.id, taskId, { status_id: targetStatusId });
        }

        if (updatedTask && taskDetail.value?.id === updatedTask.id) {
            await openTaskDetail(updatedTask);
        }
        if (selectedNote.value?.id) {
            linkedTasksForSelectedNote.value = await spaceStore.fetchTasksForNote(currentSpace.value.id, selectedNote.value.id);
        }
    } catch (error) {
        alert(error?.response?.data || "Unable to update task status.");
    }
};

const openLinkedTaskFromNote = async (task) => {
    selectedTaskList.value = taskLists.value.find((list) => list.id === task.task_list_id) || null;
    selectedNote.value = null;
    if (currentSpace.value?.id && selectedTaskList.value?.id) {
        await router.push(dashboardTaskRoute(currentSpace.value.id, selectedTaskList.value.id));
    }
    await applyTaskFilters({ taskListId: selectedTaskList.value?.id || null });
    await openTaskDetail(task);
};

const openCreateNoteModalFromMenu = () => {
    showCreateMenu.value = false;
    showCreateNoteModal.value = true;
};

const openCreateTaskListModalFromMenu = () => {
    showCreateMenu.value = false;
    showCreateTaskListModal.value = true;
};

const createTaskList = async (taskListData) => {
    if (!currentSpace.value?.id || !canCreateTasks.value) {
        showCreateTaskListModal.value = false;
        return;
    }

    try {
        const created = await spaceStore.createTaskList(currentSpace.value.id, taskListData);
        showCreateTaskListModal.value = false;
        await selectTaskList(created);
    } catch (error) {
        alert(error?.response?.data || "Unable to create task list.");
    }
};

const updateTaskListFromModal = async (payload) => {
    if (!currentSpace.value?.id || !selectedTaskList.value?.id) return;
    try {
        await spaceStore.updateTaskList(currentSpace.value.id, selectedTaskList.value.id, {
            name: payload.name,
            description: payload.description,
            category_id: payload.category_id,
        });
        selectedTaskList.value = { ...selectedTaskList.value, name: payload.name, category_id: payload.category_id };
    } catch (error) {
        alert(error?.response?.data || "Unable to update task list.");
    }
};

const requestRemoveTaskList = (taskList) => {
    if (!currentSpace.value?.id || !taskList?.id || !canDeleteTasks.value) {
        return;
    }
    showEditTaskListModal.value = false;
    taskDeleteIntent.value = {
        type: "task-list",
        payload: taskList,
    };
    showTaskDeleteConfirmModal.value = true;
};

const removeTaskList = async (taskList) => {
    if (!currentSpace.value?.id || !taskList?.id || !canDeleteTasks.value) {
        return;
    }

    try {
        await spaceStore.deleteTaskList(currentSpace.value.id, taskList.id);

        if (selectedTaskList.value?.id === taskList.id) {
            selectedTaskList.value = null;
            taskDetail.value = null;
            taskModalDraft.value = null;
            showTaskModal.value = false;
            taskFilters.value = {
                taskListId: null,
                statusId: null,
                parentTaskId: null,
            };
            await spaceStore.fetchTasks(currentSpace.value.id, taskFilters.value);
            await router.push(dashboardNoteRoute(currentSpace.value.id));
        }
    } catch (error) {
        alert(error?.response?.data || "Unable to delete task list.");
        throw error;
    }
};

const confirmTaskDeleteAction = async () => {
    if (taskDeleteConfirmBusy.value) {
        return;
    }

    const { type, payload } = taskDeleteIntent.value;
    if (!type || !payload) {
        return;
    }

    taskDeleteConfirmBusy.value = true;
    try {
        if (type === "task-status") {
            await deleteTaskStatus(payload);
        } else if (type === "task-list") {
            await removeTaskList(payload);
        } else if (type === "task") {
            await removeTask(payload);
        } else if (type === "category") {
            await removeCategory(payload);
        }

        showTaskDeleteConfirmModal.value = false;
        taskDeleteIntent.value = {
            type: "",
            payload: null,
        };
    } finally {
        taskDeleteConfirmBusy.value = false;
    }
};

const createSpace = async (spaceData) => {
    showCreateSpaceModal.value = false;
    await spaceStore.createSpace(spaceData);
};

const openCreateCategoryModal = () => {
    if (!canCreateCategories.value) {
        return;
    }
    editingCategory.value = null;
    categoryModalParentId.value = null;
    showCreateCategoryModal.value = true;
};

const submitCategory = async (categoryData) => {
    const canSubmit = editingCategory.value ? canEditCategories.value : canCreateCategories.value;
    if (!canSubmit) {
        closeCategoryModal();
        return;
    }
    if (!currentSpace.value) {
        return;
    }

    if (editingCategory.value) {
        await spaceStore.updateCategory(currentSpace.value.id, editingCategory.value.id, categoryData);
    } else {
        await spaceStore.createCategory(currentSpace.value.id, categoryData);
    }

    closeCategoryModal();
};

const createNote = async (noteData) => {
    if (!canCreateNotes.value) {
        showCreateNoteModal.value = false;
        return;
    }
    showCreateNoteModal.value = false;
    const createdNote = await spaceStore.createNote(currentSpace.value.id, noteData);
    selectedNote.value = createdNote;
    isEditingNote.value = false;
};

const updateNote = async (noteData) => {
    if (!canEditNotes.value) {
        isEditingNote.value = false;
        return;
    }
    const updatedNote = await spaceStore.updateNote(currentSpace.value.id, noteData);
    selectedNote.value = updatedNote;
};

const deleteNote = async (noteId) => {
    if (!canDeleteNotes.value) {
        return;
    }
    await spaceStore.deleteNote(currentSpace.value.id, noteId);
    selectedNote.value = null;
    isEditingNote.value = false;
    await spaceStore.fetchNotes(currentSpace.value.id, { reset: true });
};

const startEditingNote = () => {
    if (!canEditNotes.value) {
        return;
    }
    isEditingNote.value = true;
};

const cancelEditingNote = () => {
    isEditingNote.value = false;
};

const openCreateSubcategoryModal = (category) => {
    if (!canCreateCategories.value) {
        return;
    }
    editingCategory.value = null;
    categoryModalParentId.value = category.id;
    showCreateCategoryModal.value = true;
};

const openEditCategoryModal = (category) => {
    if (!canEditCategories.value) {
        return;
    }
    editingCategory.value = category;
    categoryModalParentId.value = category.parent_id || null;
    showCreateCategoryModal.value = true;
};

const requestRemoveCategory = (category) => {
    if (!canDeleteCategories.value) {
        return;
    }
    if (!currentSpace.value) {
        return;
    }
    if (!category?.id) {
        return;
    }

    taskDeleteIntent.value = {
        type: "category",
        payload: category,
    };
    showTaskDeleteConfirmModal.value = true;
};

const removeCategory = async (category) => {
    if (!canDeleteCategories.value || !currentSpace.value || !category?.id) {
        return;
    }

    await spaceStore.deleteCategory(currentSpace.value.id, category.id);

    if (selectedCategory.value?.id === category.id) {
        selectedCategory.value = null;
    }
};

const closeCategoryModal = () => {
    showCreateCategoryModal.value = false;
    editingCategory.value = null;
    categoryModalParentId.value = null;
};

const applyUpdatedSpace = (updatedSpace) => {
    if (!updatedSpace?.id) {
        return;
    }
    const index = spaceStore.spaces.findIndex((space) => space.id === updatedSpace.id);
    if (index !== -1) {
        spaceStore.spaces[index] = { ...spaceStore.spaces[index], ...updatedSpace };
    }
    if (spaceStore.currentSpace?.id === updatedSpace.id) {
        spaceStore.currentSpace = { ...spaceStore.currentSpace, ...updatedSpace };
    }
};

const handleSpaceDeleted = (deletedSpace) => {
    showSpaceSettingsModal.value = false;
    spaceStore.spaces = spaceStore.spaces.filter((space) => space.id !== deletedSpace.id);
    if (spaceStore.currentSpace?.id === deletedSpace.id) {
        spaceStore.currentSpace = null;
        selectedNote.value = null;
        selectedCategory.value = null;
    }
};

const selectSpace = async (space) => {
    showSpaceDropdown.value = false;
    await spaceStore.selectSpace(space.id);
    localStorage.setItem("currentSpaceId", space.id);
    selectedNote.value = null;
    selectedCategory.value = null;
    selectedTaskList.value = null;
    isEditingNote.value = false;
    linkedTasksForSelectedNote.value = [];
    await applyTaskFilters(taskFilters.value);
    await router.push(dashboardNoteRoute(space.id));
};

const openAdminPanel = () => {
    showUserMenu.value = false;
    router.push("/admin");
};

const logout = () => {
    authStore.logout();
    localStorage.removeItem("currentSpaceId");
    router.push("/login");
};
</script>

<style scoped>
.dashboard-container {
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow-x: hidden;
    overflow-y: visible;
}

.navbar {
    z-index: 1100;
    overflow: visible;
}

.app-navbar {
    align-items: center;
}

.navbar-left {
    min-width: 0;
}

.navbar-controls {
    min-width: 0;
}

.app-brand {
    white-space: nowrap;
}

.app-main {
    flex: 1;
    overflow: hidden;
}

.sidebar {
    width: 280px;
    overflow-y: auto;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
}

.sidebar-content {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

.sidebar-header {
    border-bottom: 1px solid var(--color-border);
}

.main-content {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.content {
    flex: 1;
    overflow-y: auto;
}

.breadcrumb-title {
    font-size: 1rem;
    color: #495057;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.breadcrumb-link {
    border: 0;
    background: transparent;
    padding: 0;
    color: var(--color-primary);
    text-decoration: none;
    cursor: pointer;
}

.breadcrumb-link:hover {
    text-decoration: underline;
}

.breadcrumb-separator {
    color: var(--color-text-muted);
}

.search-box {
    width: 300px;
}

.dropdown {
    position: relative;
}

.dropdown-menu {
    z-index: 1200;
    max-width: min(92vw, 320px);
}

.dropdown-menu-end {
    right: 0;
    left: auto;
}

.dropdown-menu.show {
    display: block;
}

@media (max-width: 768px) {
    .app-navbar {
        display: grid;
        grid-template-columns: 1fr auto;
        grid-template-areas:
            "left user"
            "space space"
            "search search";
        row-gap: 0.5rem;
        column-gap: 0.5rem;
        align-items: center;
    }

    .navbar-left {
        grid-area: left;
    }

    .navbar-controls {
        width: 100%;
    }

    .nav-user-menu {
        grid-area: user;
        justify-self: end;
    }

    .nav-space-selector {
        grid-area: space;
    }

    .nav-space-selector > .btn {
        width: 100%;
        text-align: left;
        display: flex;
        justify-content: space-between;
        align-items: center;
    }

    .nav-search {
        grid-area: search;
        width: 100%;
    }

    .nav-search .form-control {
        width: 100%;
    }

    .search-box {
        width: 100%;
    }

    .app-brand {
        font-size: 1.5rem;
    }

    .nav-menu-toggle {
        padding: 0.35rem 0.55rem;
    }

    .sidebar-backdrop {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: rgba(0, 0, 0, 0.5);
        z-index: 1090;
    }

    .sidebar {
        position: fixed;
        left: 0;
        bottom: 0;
        width: 280px;
        z-index: 1095;
        transform: translateX(-100%);
        transition: transform 0.3s ease-in-out;
        box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
        overflow-y: auto;
    }

    .sidebar.open {
        transform: translateX(0);
    }

    .toolbar {
        position: relative;
        z-index: 0;
    }

    .action-button {
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    .action-label {
        display: none;
    }

    .action-button .mdi {
        margin-right: 0 !important;
    }

    .col-auto .action-button {
        min-width: 2.75rem;
    }

    .app-main {
        flex-direction: column;
    }

    .main-content {
        width: 100%;
    }
}

:root[data-bs-theme="dark"] .sidebar-header {
    border-bottom-color: var(--color-border);
}

:root[data-bs-theme="dark"] .breadcrumb-title {
    color: #94a3b8;
}

:root[data-bs-theme="dark"] .breadcrumb-link {
    color: #7aa2f7;
}

:root[data-bs-theme="dark"] .breadcrumb-separator {
    color: #4a5568;
}
</style>
