<template>
  <el-container class="home-page" :class="{'is-mobile': isMobile}">
    <!-- Sidebar -->
    <SidebarMenu
        :is-collapsed="isCollapsed"
        :is-mobile="isMobile"
        :active-menu="activeMenu"
        :category-tree="categoryTree"
        @toggle-collapse="isCollapsed = !isCollapsed"
        @show-create-group="showCreateGroupDialog = true"
        @select-file="handleSelectFile"
        @show-rename-dialog="openRenameDialog"
        @group-deleted="handleGroupDeleted"
        @show-system-settings="showSystemSettingsDialog = true"
        @show-update-password="showUpdatePasswordDialog = true"
        @logout="handleLogout"
    />

    <!-- Main Content -->
    <el-container>
      <el-main class="content">
        <!-- Note Editor View -->
        <NoteEditor
            v-if="showEditor"
            :edit-data="editData"
            @back="handleEditorBack"
            @update:edit-data="handleSaveSuccess"
        />

        <!-- Note Preview View -->
        <NotePreview
            v-else-if="selectedFile"
            :file="selectedFile"
            :is-mobile="isMobile"
            :is-user-logged-in="userStore.isLoggedIn"
            @back="selectedFile = null"
            @edit="editNote(selectedFile)"
            @delete="deleteNote(selectedFile)"
            @open-rename-dialog="openRenameDialog"
            @show-move-note-dialog="showMoveNoteDialog = true"
            @show-privacy-dialog="showPrivacyDialog = true"
            @export="handleExport"
        />

        <!-- Home/List View -->
        <div v-else class="list-view-container">
          <HomeHeader
              :is-mobile="isMobile"
              v-model:search-keyword="searchKeyword"
              @search="handleSearch"
              @reset-view="resetToHomeView"
              @logout="handleLogout"
              @show-update-password="showUpdatePasswordDialog = true"
              @show-system-settings="showSystemSettingsDialog = true"
              @show-create-note="showCreateNoteDialog = true"
              @upload-markdown="handleMarkdownUpload"
              @toggle-collapse="isCollapsed = !isCollapsed"
          />
          <div class="note-list-wrapper" ref="noteListWrapper" @scroll="handleScroll">
            <NoteList
                :files="displayedFiles"
                :is-user-logged-in="userStore.isLoggedIn"
                @preview="previewFile"
            />
            <div v-if="isLoadingMore" class="loading-more">
              <el-icon class="is-loading"><Loading /></el-icon>
              <span>加载中...</span>
            </div>
            <div v-else-if="hasMoreFiles && !showEditor && !selectedFile" class="load-more-trigger">
              <el-button @click="loadMoreFiles" type="primary" plain>加载更多</el-button>
            </div>
          </div>
        </div>
      </el-main>
    </el-container>

    <!-- Sidebar Overlay for Mobile -->
    <div v-if="isMobile && !isCollapsed" class="sidebar-overlay" @click="isCollapsed = true"></div>

    <!-- Mobile FAB for creating note -->
    <el-button
        v-if="isMobile && userStore.isLoggedIn && !showEditor && !selectedFile"
        class="fab"
        type="primary"
        circle
        @click="showCreateNoteDialog = true"
    >
      <el-icon><Plus /></el-icon>
    </el-button>

    <!-- Dialogs -->
    <CreateGroupDialog
        v-model:visible="showCreateGroupDialog"
        :category-options="categoryTree"
        @group-created="fetchGroupings"
    />
    <CreateNoteDialog
        v-model:visible="showCreateNoteDialog"
        :category-options="categoryTree"
        @create-note="handleCreateNote"
    />
    <RenameDialog
        v-model:visible="showRenameDialog"
        :item="itemToRename"
        @renamed="handleRenamed"
    />
    <SelectGroupDialog
        v-model:visible="showSelectGroupDialog"
        :category-options="categoryTree"
        :file-to-import="fileToImport"
        @import-success="handleImportSuccess"
    />
    <MoveNoteDialog
        v-model:visible="showMoveNoteDialog"
        :category-options="categoryTree"
        :note-to-move="selectedFile"
        @move-success="handleMoveSuccess"
    />
    <SystemSettingsDialog v-model:visible="showSystemSettingsDialog" />
    <UpdatePasswordDialog
        v-model:visible="showUpdatePasswordDialog"
        @password-updated="handleLogout"
    />
    <PrivacyDialog
        v-model:visible="showPrivacyDialog"
        :note="selectedFile"
        @privacy-changed="handlePrivacyChanged"
    />
  </el-container>
</template>

<script setup>
import { onMounted, ref, nextTick, watch, computed, onBeforeUnmount } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import Vditor from 'vditor';
import 'vditor/dist/index.css';
import {
  groupingAll,
  markdownList,
  Preview,
  updateMarkdown,
  searchMarkdown,
  deleteMarkdown,
  getRecentFiles,
  validateToken,
} from '@/api/CommonApi.js';
import { useUserStore } from '../stores/user';
import { useRouter } from 'vue-router';
import { privateNoteContent } from '../utils/privateNoteContent.js';
import jsPDF from 'jspdf';
import html2canvas from 'html2canvas';

// Import Components
import SidebarMenu from './home/SidebarMenu.vue';
import HomeHeader from './home/HomeHeader.vue';
import NoteList from './home/NoteList.vue';
import NotePreview from './home/NotePreview.vue';
import NoteEditor from './home/NoteEditor.vue';
import CreateGroupDialog from './home/dialogs/CreateGroupDialog.vue';
import CreateNoteDialog from './home/dialogs/CreateNoteDialog.vue';
import RenameDialog from './home/dialogs/RenameDialog.vue';
import SelectGroupDialog from './home/dialogs/SelectGroupDialog.vue';
import MoveNoteDialog from './home/dialogs/MoveNoteDialog.vue';
import SystemSettingsDialog from './home/dialogs/SystemSettingsDialog.vue';
import UpdatePasswordDialog from './home/dialogs/UpdatePasswordDialog.vue';
import PrivacyDialog from './home/dialogs/PrivacyDialog.vue';
import { Plus, Loading } from "@element-plus/icons-vue";

// Basic Setup
const userStore = useUserStore();
const router = useRouter();

// State
const searchKeyword = ref('');
const categoryTree = ref([]);
const groupMarkdownFiles = ref([]);
const displayedFiles = ref([]);
const currentPage = ref(0);
const pageSize = ref(16);
const isLoadingMore = ref(false);
const noteListWrapper = ref(null);
const showEditor = ref(false);
const selectedFile = ref(null);
const editData = ref(null);
const activeMenu = ref('all');
const isCollapsed = ref(window.innerWidth < 768);
const isMobile = ref(window.innerWidth < 768);

// Dialog visibility
const showCreateGroupDialog = ref(false);
const showCreateNoteDialog = ref(false);
const showRenameDialog = ref(false);
const showSelectGroupDialog = ref(false);
const showMoveNoteDialog = ref(false);
const showSystemSettingsDialog = ref(false);
const showUpdatePasswordDialog = ref(false);
const showPrivacyDialog = ref(false);

// Data for dialogs
const itemToRename = ref(null);
const fileToImport = ref(null);

const hasMoreFiles = computed(() => {
  return displayedFiles.value.length < groupMarkdownFiles.value.length;
});

const resetEdit = () => {
  editData.value = null;
};

// --- Core Logic ---

// Data Fetching
const fetchGroupings = async () => {
  try {
    const allCategories = await groupingAll("");
    categoryTree.value = buildTree(allCategories || []);
  } catch (error) {
    categoryTree.value = [];
  }
};

const buildTree = (items) => {
  const tree = [];
  const itemMap = new Map();
  items.forEach(item => {
    itemMap.set(String(item.id), { ...item, children: [] });
  });
  itemMap.forEach(item => {
    const parentId = String(item.parentId);
    if (parentId !== '0' && itemMap.has(parentId)) {
      itemMap.get(parentId).children.push(item);
    } else {
      tree.push(item);
    }
  });
  const cleanTree = (nodes) => {
    nodes.forEach(node => {
      if (node.children.length === 0) delete node.children;
      else cleanTree(node.children);
    });
  };
  cleanTree(tree);
  return tree;
};

const resetToHomeView = async () => {
  resetEdit();
  selectedFile.value = null;
  showEditor.value = false;
  searchKeyword.value = '';
  activeMenu.value = 'all';
  currentPage.value = 0;
  try {
    groupMarkdownFiles.value = await getRecentFiles(100) || [];
    updateDisplayedFiles();
  } catch (error) {
    ElMessage.error('获取最近文件失败: ' + error.message);
    groupMarkdownFiles.value = [];
    displayedFiles.value = [];
  }
};

const updateDisplayedFiles = () => {
  const start = 0;
  const end = (currentPage.value + 1) * pageSize.value;
  displayedFiles.value = groupMarkdownFiles.value.slice(start, end);
};

const loadMoreFiles = () => {
  if (isLoadingMore.value || !hasMoreFiles.value) return;
  isLoadingMore.value = true;
  
  setTimeout(() => {
    currentPage.value++;
    updateDisplayedFiles();
    isLoadingMore.value = false;
  }, 300);
};

const handleScroll = (e) => {
  const { scrollTop, scrollHeight, clientHeight } = e.target;
  if (scrollHeight - scrollTop - clientHeight < 100 && hasMoreFiles.value && !isLoadingMore.value) {
    loadMoreFiles();
  }
};

// Event Handlers from Components
const handleSelectFile = async (data) => {
  resetEdit();
  try {
    const files = await markdownList(data.id);
    groupMarkdownFiles.value = files || [];
    currentPage.value = 0;
    updateDisplayedFiles();
    selectedFile.value = null;
    showEditor.value = false;
    activeMenu.value = `group-${data.id}`;
  } catch (error) {
    ElMessage.error('获取笔记列表失败: ' + error.message);
    groupMarkdownFiles.value = [];
    displayedFiles.value = [];
  }
};

const handleGroupDeleted = async () => {
  await fetchGroupings();
  await resetToHomeView();
};

const handleCreateNote = (payload) => {
  resetEdit();
  // 直接设置编辑数据，ID将在第一次保存时由后端生成
  editData.value = payload;
  showEditor.value = true;
  selectedFile.value = null; // Ensure preview is hidden
};

const handleEditorBack = (data) => {
  showEditor.value = false;
  if (data && data.id) {
    const fileWithGrouping = {
      ...data,
      groupingName: data.groupingName || getCategoryName(data.groupingId)
    };
    selectedFile.value = fileWithGrouping;
  } else {
    selectedFile.value = null;
    resetToHomeView();
  }
};

const getCategoryName = (groupId) => {
  if (!groupId) return '';
  const findName = (items) => {
    for (const item of items) {
      if (item.id === groupId) return item.grouping;
      if (item.children) {
        const name = findName(item.children);
        if (name) return name;
      }
    }
    return null;
  };
  return findName(categoryTree.value) || '';
};

const handleSaveSuccess = (updatedFile) => {
  selectedFile.value = updatedFile;

  const index = groupMarkdownFiles.value.findIndex(f => f.id === updatedFile.id);
  if (index !== -1) {
    groupMarkdownFiles.value[index] = updatedFile;
  } else {
    groupMarkdownFiles.value.unshift(updatedFile);
  }
  
  updateDisplayedFiles();
  fetchGroupings();
};

const previewFile = async (file) => {
  resetEdit();
  if (!file || file.id === null) {
    editData.value = file;
    selectedFile.value = null;
    return;
  }
  try {
    const content = await Preview(file.id) || '';
    selectedFile.value = { ...file, content };
    showEditor.value = false;
  } catch (error) {
    ElMessage.error('获取笔记内容失败: ' + error.message);
    selectedFile.value = null;
  }
};

const editNote = (file) => {
  editData.value = { ...file };
  showEditor.value = true;
  isCollapsed.value = true; // Collapse sidebar on mobile when editing
};

const deleteNote = (file) => {
  ElMessageBox.confirm(`确定要删除笔记 “${file.title}” 吗？`, '警告', {
    confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning',
  }).then(async () => {
    try {
      await deleteMarkdown(file.id);
      ElMessage.success('笔记已删除');
      selectedFile.value = null;
      await fetchGroupings();
      await resetToHomeView();
    } catch (error) {
      ElMessage.error('删除笔记失败: ' + error.message);
    }
  });
};

const openRenameDialog = (item, type) => {
  itemToRename.value = { ...item, type };
  showRenameDialog.value = true;
};

const handleRenamed = async (newName) => {
  await fetchGroupings();
  if (selectedFile.value && itemToRename.value.type === 'file' && selectedFile.value.id === itemToRename.value.id) {
    // 直接更新当前选中文件的标题
    selectedFile.value.title = newName;
    // 更新笔记列表中的对应项
    const index = groupMarkdownFiles.value.findIndex(f => f.id === selectedFile.value.id);
    if (index !== -1) {
      groupMarkdownFiles.value[index].title = newName;
    }
    // 重新获取文件内容以确保是最新的
    previewFile(selectedFile.value); // Refresh preview
  } else {
    resetToHomeView();
  }
};

const handleMarkdownUpload = (file) => {
  fileToImport.value = file;
  showSelectGroupDialog.value = true;
};

const handleImportSuccess = async () => {
  await fetchGroupings();
  await resetToHomeView();
};

const handleMoveSuccess = async () => {
  selectedFile.value = null;
  await fetchGroupings();
  await resetToHomeView();
};

const handlePrivacyChanged = (updatedFile) => {
  selectedFile.value = updatedFile;
  const index = groupMarkdownFiles.value.findIndex(f => f.id === updatedFile.id);
  if (index !== -1) {
    groupMarkdownFiles.value[index] = updatedFile;
  }
};

const handleSearch = async () => {
  if (!searchKeyword.value.trim()) {
    await resetToHomeView();
    return;
  }
  try {
    groupMarkdownFiles.value = await searchMarkdown(searchKeyword.value) || [];
    currentPage.value = 0;
    updateDisplayedFiles();
    selectedFile.value = null;
    showEditor.value = false;
    activeMenu.value = 'search';
  } catch (error) {
    ElMessage.error('搜索失败: ' + error.message);
  }
};

const handleLogout = () => {
  userStore.logout();
  ElMessage.success('已退出登录');
  router.push('/login');
};

// Export Logic
const handleExport = async (format) => {
  if (!selectedFile.value) return;
  try {
    await validateToken();
  } catch {
    ElMessage.error('登录已过期，请重新登录');
    handleLogout();
    return;
  }

  const title = (selectedFile.value.title || '未命名笔记').replace(/[<>:"/\\|?*]/g, '_');
  const content = selectedFile.value.content;
  const previewElement = document.querySelector('.markdown-preview');

  if (!previewElement) {
    ElMessage.error('无法找到预览区域');
    return;
  }

  ElMessage.info(`正在导出为 ${format.toUpperCase()}...`);

  try {
    if (format === 'md') {
      const blob = new Blob([content], { type: 'text/markdown;charset=utf-8' });
      downloadBlob(blob, `${title}.md`);
    } else if (format === 'html') {
        const fullHtml = `<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><title>${title}</title><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.1.0/github-markdown.min.css"><style>body{box-sizing:border-box;min-width:200px;max-width:980px;margin:0 auto;padding:45px;}</style></head><body class="markdown-body"><h1>${title}</h1>${previewElement.innerHTML}</body></html>`;
        const blob = new Blob([fullHtml], { type: 'text/html;charset=utf-8' });
        downloadBlob(blob, `${title}.html`);
    } else if (format === 'pdf') {
        const canvas = await html2canvas(previewElement, { scale: 2, useCORS: true });
        const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' });
        const pageHeight = pdf.internal.pageSize.getHeight() - 20;
        const pageWidth = pdf.internal.pageSize.getWidth() - 20;
        const imgHeight = (canvas.height * pageWidth) / canvas.width;
        let heightLeft = imgHeight;
        let position = 10;
        const imgData = canvas.toDataURL('image/png');
        pdf.addImage(imgData, 'PNG', 10, position, pageWidth, imgHeight);
        heightLeft -= pageHeight;
        while (heightLeft > 0) {
            position = -pageHeight * (pdf.internal.getNumberOfPages()) + 10;
            pdf.addPage();
            pdf.addImage(imgData, 'PNG', 10, position, pageWidth, imgHeight);
            heightLeft -= pageHeight;
        }
        pdf.save(`${title}.pdf`);
    }
    ElMessage.success(`${format.toUpperCase()} 导出成功`);
  } catch (error) {
    ElMessage.error(`导出失败: ${error.message}`);
  }
};

const downloadBlob = (blob, filename) => {
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = filename;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
};


// Lifecycle and Watchers
onMounted(async () => {
  await fetchGroupings();
  await resetToHomeView();
  window.addEventListener('resize', handleResize);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize);
});

const handleResize = () => {
  isMobile.value = window.innerWidth < 768;
  if (isMobile.value) {
    isCollapsed.value = true;
  }
};

// 使用防抖优化 Vditor 渲染
let renderTimeout = null;
let lastRenderedId = null;

watch([selectedFile, showEditor], ([newFile, newShowEditor]) => {
  if (newFile && !newShowEditor) {
    // 如果同一个文件已经渲染过，跳过
    if (lastRenderedId === newFile.id) return;
    
    clearTimeout(renderTimeout);
    renderTimeout = setTimeout(() => {
      nextTick(() => {
        const previewElement = document.querySelector('.markdown-preview');
        if (previewElement) {
          const contentToRender = (newFile.isPrivate === 1 && !userStore.isLoggedIn) ? privateNoteContent : newFile.content;
          Vditor.preview(previewElement, contentToRender || '', {
            mode: 'light',
            hljs: { enable: true, style: 'github' }
          });
          lastRenderedId = newFile.id;
        }
      });
    }, 50); // 50ms 防抖
  }
}, { deep: true });

</script>

<style>
/* Global styles can remain if they are truly global */
.hide-popper {
  display: none !important;
}
.markdown-preview .vditor-reset pre {
  max-height: none !important;
  overflow: visible !important;
}
.markdown-preview .vditor-reset pre code {
  max-height: none !important;
  overflow-y: visible !important;
  word-break: break-all !important;
  white-space: pre-wrap !important;
  display: block;
}
</style>

<style scoped>
.list-view-container {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.note-list-wrapper {
  flex: 1;
  overflow-y: auto;
}

.home-page {
  height: 100vh;
  overflow: hidden;
  background: var(--bg-gradient);
  background-attachment: fixed;
}

.content {
  padding: 1.5rem;
  background-color: transparent;
  height: 100vh;
  overflow-y: auto;
}

.sidebar-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 1000;
}

.fab {
  position: fixed;
  bottom: 80px;
  right: 20px;
  z-index: 100;
  width: 56px;
  height: 56px;
  box-shadow: 0 4px 12px rgba(0,0,0,.15);
}

.loading-more {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  gap: 8px;
  color: var(--text-color-secondary);
}

.load-more-trigger {
  display: flex;
  justify-content: center;
  padding: 20px;
}
</style>