<script setup lang="ts">
import {ref, watch, onMounted, onUnmounted, computed} from "vue";
import {listen} from "@tauri-apps/api/event";
import {invoke} from "@tauri-apps/api/core";
import MarkdownEditor from "./components/MarkdownEditor.vue";
import DirectorySidebar from "./components/DirectorySidebar.vue";

const content = ref("");
const wordCount = ref(0);
const charCount = ref(0);

// File state
const currentFilePath = ref<string | null>(null);
const saveStatus = ref("");

// Check if current file is a Markdown file (for display-mode toggle)
const isMarkdownFile = computed(() => {
  return currentFilePath.value?.toLowerCase().endsWith(".md") ?? false;
});

// Folder state
interface DirEntry {
  name: string;
  path: string;
  is_dir: boolean;
  children?: DirEntry[];
}

const folderPath = ref("");
const dirEntries = ref<DirEntry[]>([]);

// ---- editor zoom (Ctrl+scroll) ----
const ZOOM_MIN = 0.7;
const ZOOM_MAX = 1.5;
const ZOOM_STEP = 0.1;

function loadZoomPref(): number {
  try {
    const stored = localStorage.getItem("editor-zoom");
    if (stored) {
      const val = parseFloat(stored);
      if (!isNaN(val) && val >= ZOOM_MIN && val <= ZOOM_MAX) return val;
    }
  } catch { /* localStorage unavailable */
  }
  return 1.0;
}

const editorZoom = ref(loadZoomPref());
const showZoomIndicator = ref(false);
let zoomIndicatorTimer: ReturnType<typeof setTimeout> | null = null;

function applyZoomCssVars() {
  document.documentElement.style.setProperty("--editor-zoom", String(editorZoom.value));
}

function saveZoomPref() {
  try {
    localStorage.setItem("editor-zoom", String(editorZoom.value));
  } catch { /* noop */
  }
}

function onEditorWheel(e: WheelEvent) {
  if (!e.ctrlKey && !e.metaKey) return;
  e.preventDefault();
  const delta = e.deltaY < 0 ? ZOOM_STEP : -ZOOM_STEP;
  const next = Math.round((editorZoom.value + delta) * 10) / 10;
  editorZoom.value = Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, next));
  applyZoomCssVars();
  saveZoomPref();

  // Show zoom indicator and reset timer
  showZoomIndicator.value = true;
  if (zoomIndicatorTimer) clearTimeout(zoomIndicatorTimer);
  zoomIndicatorTimer = setTimeout(() => {
    showZoomIndicator.value = false;
  }, 1500);
}

// ---- full-width mode ----
function loadFullWidthPref(): boolean {
  try {
    return localStorage.getItem("editor-full-width") === "true";
  } catch {
    return false;
  }
}

const isFullWidth = ref(loadFullWidthPref());

function onToggleFullWidth(val: boolean) {
  isFullWidth.value = val;
  try {
    localStorage.setItem("editor-full-width", String(val));
  } catch { /* noop */
  }
}

// ---- display mode (split / wysiwyg) ----
type DisplayMode = "split" | "wysiwyg";

function loadDisplayModePref(): DisplayMode {
  try {
    const v = localStorage.getItem("editor-display-mode");
    if (v === "split" || v === "wysiwyg") return v;
  } catch { /* noop */
  }
  return "split";
}

const displayMode = ref<DisplayMode>(loadDisplayModePref());

function onToggleDisplayMode(val: DisplayMode) {
  displayMode.value = val;
  try {
    localStorage.setItem("editor-display-mode", val);
  } catch { /* noop */
  }
}

// ---- toolbar state ----
const showThumbnail = ref(true);
const previewOnly = ref(false);
const showMoreMenu = ref(false);

function toggleFullWidth() {
  isFullWidth.value = !isFullWidth.value;
  try {
    localStorage.setItem("editor-full-width", String(isFullWidth.value));
  } catch { /* noop */
  }
}

function toggleDisplayMode() {
  displayMode.value = displayMode.value === "split" ? "wysiwyg" : "split";
  try {
    localStorage.setItem("editor-display-mode", displayMode.value);
  } catch { /* noop */
  }
}

function handleExportPdf() {
  showMoreMenu.value = false;
  // TODO: implement PDF export
}

function closeMoreMenu() {
  showMoreMenu.value = false;
}

watch(showMoreMenu, (val) => {
  if (val) {
    setTimeout(() => {
      document.addEventListener("click", closeMoreMenu, {once: true});
    }, 0);
  }
});

onMounted(() => {
  applyZoomCssVars();
  window.addEventListener("wheel", onEditorWheel, {passive: false});
});

onUnmounted(() => {
  window.removeEventListener("wheel", onEditorWheel);
  if (zoomIndicatorTimer) clearTimeout(zoomIndicatorTimer);
});

function stripMarkdown(md: string): string {
  return md
      // Remove images ![alt](url)
      .replace(/!\[[^\]]*\]\([^)]*\)/g, "")
      // Convert links [text](url) to just text
      .replace(/\[([^\]]*)\]\([^)]*\)/g, "$1")
      // Remove heading markers
      .replace(/^#{1,6}\s+/gm, "")
      // Remove bold/italic markers
      .replace(/\*{1,3}|_{1,3}/g, "")
      // Remove strikethrough
      .replace(/~~/g, "")
      // Remove inline code markers
      .replace(/`+/g, "")
      // Remove blockquote markers
      .replace(/^>\s?/gm, "")
      // Remove list markers (-, *, +, or 1.)
      .replace(/^[\s]*[-*+]\s+/gm, "")
      .replace(/^[\s]*\d+\.\s+/gm, "")
      // Remove horizontal rules
      .replace(/^[-*_]{3,}\s*$/gm, "")
      .trim();
}

function onUpdate(md: string) {
  content.value = md;
  const text = stripMarkdown(md);
  charCount.value = text.length;
  wordCount.value = text.trim() ? text.trim().split(/\s+/).length : 0;
}

function onHeadingClick(heading: { text: string; level: number }) {
  const selector = `.markdown-preview h${heading.level}`;
  const headingEls = document.querySelectorAll(selector);
  for (const el of headingEls) {
    if (el.textContent?.trim() === heading.text) {
      el.scrollIntoView({behavior: "smooth", block: "start"});
      break;
    }
  }
}

async function loadDir(path: string) {
  folderPath.value = path;
  try {
    dirEntries.value = await invoke<DirEntry[]>("read_dir", {path});
  } catch (e) {
    console.error("Failed to read directory:", e);
    dirEntries.value = [];
  }
}

async function onOpenFolder() {
  try {
    const chosen = await invoke<string | null>("pick_folder");
    if (chosen) {
      await loadDir(chosen);
    }
  } catch (e) {
    console.error("Failed to pick folder:", e);
  }
}

function getFileName(path: string): string {
  return path.split(/[/\\]/).pop() || path;
}

// ---- file tree helpers ----
function findEntry(entries: DirEntry[], path: string): DirEntry | null {
  for (const entry of entries) {
    if (entry.path === path) return entry;
    if (entry.children) {
      const found = findEntry(entry.children, path);
      if (found) return found;
    }
  }
  return null;
}

async function onToggleFolder(path: string) {
  const entry = findEntry(dirEntries.value, path);
  if (!entry || entry.children !== undefined) return;
  try {
    const children = await invoke<DirEntry[]>("read_dir", {path});
    entry.children = children;
  } catch (e) {
    console.error("Failed to read subdirectory:", e);
  }
}

async function onOpenFile(path: string) {
  try {
    const fileContent = await invoke<string>("read_file", {path});
    content.value = fileContent;
    currentFilePath.value = path;
    saveStatus.value = "";
  } catch (e) {
    console.error("Failed to open file:", e);
  }
}

async function doSave() {
  if (!currentFilePath.value) {
    // No file path yet — prompt user to pick a save location
    try {
      const chosen = await invoke<string | null>("pick_save_file");
      if (!chosen) return; // user cancelled
      currentFilePath.value = chosen;
    } catch (e) {
      console.error("Save dialog failed:", e);
      return;
    }
  }

  try {
    await invoke("write_file", {path: currentFilePath.value, content: content.value});
    saveStatus.value = `已保存: ${getFileName(currentFilePath.value)}`;
    setTimeout(() => {
      saveStatus.value = "";
    }, 3000);
  } catch (e) {
    console.error("Save failed:", e);
    saveStatus.value = `保存失败: ${e}`;
  }
}

async function doSaveAs() {
  try {
    const chosen = await invoke<string | null>("pick_save_file");
    if (!chosen) return; // user cancelled
    currentFilePath.value = chosen;
    await invoke("write_file", {path: currentFilePath.value, content: content.value});
    saveStatus.value = `已保存: ${getFileName(currentFilePath.value)}`;
    setTimeout(() => {
      saveStatus.value = "";
    }, 3000);
  } catch (e) {
    console.error("Save failed:", e);
    saveStatus.value = `保存失败: ${e}`;
  }
}

function doNew() {
  content.value = "";
  currentFilePath.value = null;
  saveStatus.value = "";
}

// Listen for menu events from Rust
listen<string>("folder-opened", (event) => {
  loadDir(event.payload);
});

listen("menu-save", () => {
  doSave();
});

listen("menu-save-as", () => {
  doSaveAs();
});

listen("menu-new", () => {
  doNew();
});

listen("menu-event", (event) => {
  console.log("Menu event:", event.payload);
});
</script>

<template>
  <div class="h-screen bg-[#faf9f6] text-[#38342e] flex flex-col">
    <!-- Three-column body -->
    <div class="flex-1 flex overflow-hidden bg-[#faf9f6]">
      <!-- Left: Directory sidebar -->
      <DirectorySidebar
          :folder-path="folderPath"
          :entries="dirEntries"
          :content="content"
          :current-file-path="currentFilePath"
          :is-full-width="isFullWidth"
          :display-mode="displayMode"
          :is-markdown-file="isMarkdownFile"
          @heading-click="onHeadingClick"
          @open-folder="onOpenFolder"
          @toggle-folder="onToggleFolder"
          @open-file="onOpenFile"
          @toggle-full-width="onToggleFullWidth"
          @toggle-display-mode="onToggleDisplayMode"
      />

      <!-- Right: Editor area -->
      <main class="flex-1 flex flex-col overflow-hidden relative">
        <!-- ════════════════ Toolbar ════════════════ -->
        <div
            class="flex w-full items-center h-10 px-3 bg-[#faf9f6] border border-[#e0dbcf] border-b-0 select-none shrink-0"
        >
          <!-- Left: Thumbnail toggle -->
          <button
              class="toolbar-btn"
              :class="{ 'toolbar-btn-active': showThumbnail }"
              title="切换缩略图"
              @click="showThumbnail = !showThumbnail"
          >
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5">
              <rect x="1" y="1" width="6" height="6" rx="1"/>
              <rect x="9" y="1" width="6" height="6" rx="1"/>
              <rect x="1" y="9" width="6" height="6" rx="1"/>
              <rect x="9" y="9" width="6" height="6" rx="1"/>
            </svg>
          </button>

          <!-- Center: Filename -->
          <div class="flex-1 text-center text-sm text-[#8c877d] font-medium truncate px-3 select-none">
            {{ currentFilePath ? getFileName(currentFilePath) : '未命名文档' }}
          </div>

          <!-- Right: Actions -->
          <div class="flex items-center gap-0.5">
            <!-- Display mode toggle (only for .md files) -->
            <button
                v-if="isMarkdownFile"
                class="toolbar-btn"
                :title="displayMode === 'wysiwyg' ? '切换到双栏' : '切换到单栏'"
                @click="toggleDisplayMode"
            >
              <!-- Split icon (shown when single, meaning click to switch to split) -->
              <svg v-if="displayMode === 'wysiwyg'" width="16" height="16" viewBox="0 0 16 16" fill="none"
                   stroke="currentColor" stroke-width="1.5">
                <rect x="1" y="2" width="6" height="12" rx="1"/>
                <rect x="9" y="2" width="6" height="12" rx="1"/>
              </svg>
              <!-- Single icon -->
              <svg v-else width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor"
                   stroke-width="1.5">
                <rect x="3" y="2" width="10" height="12" rx="1"/>
              </svg>
            </button>

            <!-- Preview/Edit toggle -->
            <button
                class="toolbar-btn"
                :class="{ 'toolbar-btn-active': !previewOnly }"
                :title="previewOnly ? '切换到编辑模式' : '切换到预览模式'"
                @click="previewOnly = !previewOnly"
            >
              <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5">
                <path d="M11.5 1.5l3 3L5 14H2v-3L11.5 1.5z"/>
              </svg>
            </button>

            <!-- Full-width toggle -->
            <button
                class="toolbar-btn"
                :class="{ 'toolbar-btn-active': isFullWidth }"
                title="切换全宽"
                @click="toggleFullWidth"
            >
              <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5">
                <path d="M10 1h5v5M6 15H1v-5M15 1l-5 5M1 15l5-5"/>
              </svg>
            </button>

            <!-- More menu -->
            <div class="relative">
              <button
                  class="toolbar-btn"
                  title="更多"
                  @click="showMoreMenu = !showMoreMenu"
              >
                <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
                  <circle cx="3" cy="8" r="1.5"/>
                  <circle cx="8" cy="8" r="1.5"/>
                  <circle cx="13" cy="8" r="1.5"/>
                </svg>
              </button>
              <div
                  v-if="showMoreMenu"
                  class="dropdown-menu"
                  @click.stop
              >
                <button class="dropdown-item" @click="handleExportPdf">
                  <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5">
                    <path d="M5 1h6l4 4v9a1 1 0 01-1 1H2a1 1 0 01-1-1V2a1 1 0 011-1z"/>
                    <path d="M5 1v4h4"/>
                    <path d="M5 9h6M5 12h4"/>
                  </svg>
                  导出 PDF
                </button>
              </div>
            </div>
          </div>
        </div>
        <MarkdownEditor
            :model-value="content"
            :is-full-width="isFullWidth"
            :display-mode="displayMode"
            :preview-only="previewOnly"
            placeholder="输入 Markdown 内容... 支持标题、粗体、斜体、代码块等 ✨"
            @update:model-value="onUpdate"
            @save-shortcut="doSave"
            class="flex-1 w-full"
        />

        <!-- Zoom indicator -->
        <Transition name="zoom-fade">
          <div
              v-if="showZoomIndicator"
              class="fixed top-4 right-4 z-50 px-2.5 py-1 rounded-md bg-[#38342e]/80 text-white text-xs font-medium pointer-events-none select-none backdrop-blur-sm"
          >
            {{ Math.round(editorZoom * 100) }}%
          </div>
        </Transition>
      </main>
    </div>
    <footer class="border-t border-[#e8e4da] bg-[#f4f1eb]/60 backdrop-blur-sm">
      <div class="flex items-center gap-4 px-4 py-1.5">

        <!-- Current file / save status -->
        <span
            v-if="saveStatus"
            class="text-xs"
            :class="saveStatus.startsWith('保存失败') ? 'text-red-500' : 'text-emerald-600'"
        >{{ saveStatus }}</span>
        <span v-else-if="currentFilePath" class="text-xs text-[#8c877d]">
          {{ currentFilePath.split(/[/\\]/).pop() }}
        </span>
        <span v-else class="text-xs text-[#b8b3a8]">未保存</span>

        <span class="flex-1"/>

        <span class="text-xs text-[#8c877d]">{{ wordCount.toLocaleString() }} 词</span>
        <span class="w-px h-3 bg-[#d4cfc4]"/>
        <span class="text-xs text-[#8c877d]">{{ charCount.toLocaleString() }} 字</span>
      </div>
    </footer>
  </div>
</template>

<style>
.zoom-fade-enter-active,
.zoom-fade-leave-active {
  transition: opacity 0.2s ease;
}

.zoom-fade-enter-from,
.zoom-fade-leave-to {
  opacity: 0;
}

/* ── Toolbar ───────────────────────────────────────────────────── */

.toolbar-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 6px;
  color: #8c877d;
  background: transparent;
  border: none;
  cursor: pointer;
  transition: background-color 0.15s, color 0.15s;
  flex-shrink: 0;
}

.toolbar-btn:hover {
  background-color: #ede8dd;
  color: #38342e;
}

.toolbar-btn-active {
  color: #bf6a3b;
  background-color: #f4f1ea;
}

.dropdown-menu {
  position: absolute;
  right: 0;
  top: 100%;
  margin-top: 4px;
  background: white;
  border: 1px solid #e0dbcf;
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
  min-width: 140px;
  padding: 4px;
  z-index: 50;
}

.dropdown-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 10px;
  border-radius: 6px;
  font-size: 13px;
  color: #38342e;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
}

.dropdown-item:hover {
  background-color: #f4f1ea;
}
</style>


