<script setup>
import { computed, onMounted, ref } from 'vue'
import FileTree from '../components/FileTree.vue'
import FileContent from '../components/FileContent.vue'
import ContextMenu from '../components/ContextMenu.vue'
import { useFileSystem } from '../composables/useFileSystem'

const fs = useFileSystem()
const sidebarCollapsed = ref(false)
const confirmDialog = ref(null)

onMounted(() => {
  fs.load()
})

const selectedNode = computed(() => fs.getSelectedNode())
const breadcrumb = computed(() => (fs.selectedId.value ? fs.getBreadcrumbPath(fs.selectedId.value) : []))
const storageSummary = computed(() => {
  const bytes = fs.stats.value.usedBytes
  if (!bytes) return '0 B'
  const units = ['B', 'KB', 'MB', 'GB', 'TB']
  let value = bytes
  let index = 0
  while (value >= 1024 && index < units.length - 1) {
    value /= 1024
    index += 1
  }
  return `${value >= 100 || index === 0 ? value.toFixed(0) : value.toFixed(1)} ${units[index]}`
})

async function handleCreateFile(parentId, name = 'untitled.md') {
  await fs.createFile(parentId, name)
}

async function handleCreateFolder(parentId, name = '新建文件夹') {
  await fs.createFolder(parentId, name)
}

async function handleRename(id, newName) {
  await fs.rename(id, newName)
}

function findNode(nodes, id) {
  for (const node of nodes) {
    if (node.id === id) return node
    if (node.type === 'folder') {
      const found = findNode(node.children || [], id)
      if (found) return found
    }
  }
  return null
}

function handleDelete(id) {
  const node = findNode(fs.tree.value, id)
  if (!node) return
  confirmDialog.value = {
    id,
    name: node.name,
    type: node.type
  }
}

async function confirmDelete() {
  if (!confirmDialog.value) return
  await fs.remove(confirmDialog.value.id)
  confirmDialog.value = null
}

function handleContextMenu(x, y, node) {
  fs.showContextMenu(x, y, node)
}

async function handleDrop(draggedId, targetParentId) {
  if (draggedId === targetParentId) return
  fs.cut(draggedId)
  await fs.paste(targetParentId)
}

async function handleUploadFiles(files) {
  const parentId = selectedNode.value?.type === 'folder' ? selectedNode.value.id : selectedNode.value?.parentId || null
  const result = await fs.uploadFiles(files, parentId)
  if (result.failed.length > 0) {
    fs.error.value = result.failed.map((item) => `${item.name}：${item.reason}`).join('；')
  }
}

function closeConfirm() {
  confirmDialog.value = null
}
</script>

<template>
  <div class="docs-view">
    <div class="docs-layout">
      <aside v-show="!sidebarCollapsed" class="docs-sidebar">
        <FileTree
          :nodes="fs.tree.value"
          :selected-id="fs.selectedId.value"
          :expanded-ids="fs.expandedIds.value"
          :clipboard="fs.clipboard.value"
          :get-file-icon="fs.getFileIcon"
          :loading="fs.loading.value"
          :stats="fs.stats.value"
          @select="fs.select"
          @toggle="fs.toggleFolder"
          @create-file="handleCreateFile"
          @create-folder="handleCreateFolder"
          @rename="handleRename"
          @remove="handleDelete"
          @copy="fs.copy"
          @cut="fs.cut"
          @paste="fs.paste"
          @context-menu="handleContextMenu"
          @drop="handleDrop"
          @drag-start="() => {}"
          @drag-over="() => {}"
          @upload-files="handleUploadFiles"
        />
      </aside>

      <section class="docs-main">
        <header v-if="selectedNode?.type !== 'file'" class="docs-toolbar">
          <div class="toolbar-left">
            <button
              class="sidebar-toggle"
              type="button"
              :title="sidebarCollapsed ? '展开左侧栏' : '收起左侧栏'"
              @click="sidebarCollapsed = !sidebarCollapsed"
            >
              <svg viewBox="0 0 16 16" width="15" height="15" fill="currentColor"><path d="M2.75 2A1.75 1.75 0 001 3.75v8.5C1 13.216 1.784 14 2.75 14h10.5A1.75 1.75 0 0015 12.25v-8.5A1.75 1.75 0 0013.25 2H2.75zm0 1.5h2.5v9h-2.5a.25.25 0 01-.25-.25v-8.5a.25.25 0 01.25-.25zm4 9v-9h6.5a.25.25 0 01.25.25v8.5a.25.25 0 01-.25.25h-6.5z"/></svg>
            </button>
            <div class="toolbar-breadcrumb">
              <button class="crumb-link" type="button" @click="fs.select(null)">workspace</button>
              <template v-for="item in breadcrumb" :key="item.id">
                <span class="crumb-sep">/</span>
                <button
                  v-if="item.id !== selectedNode?.id"
                  class="crumb-link"
                  type="button"
                  @click="fs.select(item.id)"
                >
                  {{ item.name }}
                </button>
                <span v-else class="crumb-current">{{ item.name }}</span>
              </template>
            </div>
          </div>

          <div class="toolbar-right">
            <span class="storage-pill">文档空间 {{ storageSummary }}</span>
            <button
              v-if="fs.canPaste()"
              class="toolbar-btn"
              type="button"
              @click="fs.paste(selectedNode?.type === 'folder' ? selectedNode.id : selectedNode?.parentId || null)"
            >
              粘贴
            </button>
          </div>
        </header>

        <FileContent
          :node="selectedNode"
          :breadcrumb="breadcrumb"
          :root-nodes="fs.tree.value"
          :get-file-icon="fs.getFileIcon"
          :get-file-blob="fs.getFileBlob"
          :update-file="fs.updateFile"
          :show-sidebar-toggle="selectedNode?.type === 'file'"
          @navigate="fs.select"
          @toggle-sidebar="sidebarCollapsed = !sidebarCollapsed"
        />
      </section>
    </div>

    <ContextMenu
      :visible="!!fs.contextMenu.value"
      :x="fs.contextMenu.value?.x || 0"
      :y="fs.contextMenu.value?.y || 0"
      :node="fs.contextMenu.value?.node || null"
      :can-paste="fs.canPaste()"
      @close="fs.hideContextMenu()"
      @rename="fs.hideContextMenu()"
      @delete="(id) => { fs.hideContextMenu(); handleDelete(id) }"
      @copy="(id) => { fs.hideContextMenu(); fs.copy(id) }"
      @cut="(id) => { fs.hideContextMenu(); fs.cut(id) }"
      @paste="(parentId) => { fs.hideContextMenu(); fs.paste(parentId) }"
      @new-file="(parentId) => { fs.hideContextMenu(); handleCreateFile(parentId) }"
      @new-folder="(parentId) => { fs.hideContextMenu(); handleCreateFolder(parentId) }"
    />

    <Teleport to="body">
      <div v-if="confirmDialog" class="confirm-overlay">
        <div class="confirm-dialog">
          <h3>确认删除</h3>
          <p>
            确定要删除 <strong>{{ confirmDialog.name }}</strong>
            {{ confirmDialog.type === 'folder' ? ' 以及其中的全部内容' : '' }} 吗？
          </p>
          <div class="confirm-actions">
            <button class="btn btn-secondary" type="button" @click="closeConfirm">取消</button>
            <button class="btn btn-danger" type="button" @click="confirmDelete">删除</button>
          </div>
        </div>
      </div>
    </Teleport>

    <Teleport to="body">
      <div v-if="fs.error.value" class="error-toast">
        <div class="error-content">
          <span>{{ fs.error.value }}</span>
          <button class="error-close" type="button" @click="fs.error.value = null">×</button>
        </div>
      </div>
    </Teleport>
  </div>
</template>

<style scoped>
.docs-view {
  width: 100%;
  height: 100dvh;
  min-height: 0;
  overflow: hidden;
  background: var(--github-bg);
}

.docs-layout {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  height: 100%;
  min-height: 0;
}

.docs-sidebar {
  min-width: 0;
  overflow: auto;
  border-right: 1px solid var(--github-border);
  background: var(--github-bg);
}

.docs-main {
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.docs-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 56px;
  padding: 0 18px;
  border-bottom: 1px solid var(--github-border);
  background: var(--github-bg);
}

.toolbar-left,
.toolbar-right,
.toolbar-breadcrumb {
  display: flex;
  align-items: center;
  gap: 10px;
}

.toolbar-breadcrumb {
  min-width: 0;
  flex-wrap: wrap;
}

.sidebar-toggle,
.toolbar-btn,
.crumb-link {
  border: none;
  background: transparent;
  cursor: pointer;
}

.sidebar-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--github-border);
  border-radius: 8px;
  color: var(--github-text-secondary);
  background: var(--github-bg);
}

.sidebar-toggle:hover,
.toolbar-btn:hover {
  background: var(--github-hover);
}

.crumb-link {
  color: #0969da;
  font-size: 14px;
}

.crumb-current {
  color: var(--github-text);
  font-size: 14px;
  font-weight: 700;
}

.crumb-sep {
  color: var(--github-text-secondary);
}

.storage-pill {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--github-border);
  border-radius: 999px;
  background: var(--github-hover);
  color: var(--github-text-secondary);
  font-size: 12px;
  font-weight: 700;
}

.toolbar-btn {
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--github-border);
  border-radius: 8px;
  background: var(--github-bg);
  color: var(--github-text);
  font-size: 13px;
  font-weight: 600;
}

.confirm-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(15, 23, 42, 0.35);
  z-index: 10000;
}

.confirm-dialog {
  width: min(420px, calc(100vw - 32px));
  padding: 24px;
  border: 1px solid var(--github-border);
  border-radius: 16px;
  background: var(--github-bg);
  box-shadow: 0 28px 60px rgba(15, 23, 42, 0.22);
}

.confirm-dialog h3 {
  margin: 0 0 10px;
  font-size: 1.1rem;
}

.confirm-dialog p {
  margin: 0;
  color: var(--github-text-secondary);
  line-height: 1.7;
}

.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 18px;
}

.btn {
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--github-border);
  border-radius: 10px;
  font-weight: 700;
  cursor: pointer;
}

.btn-secondary {
  background: var(--github-bg);
  color: var(--github-text);
}

.btn-danger {
  border-color: #cf222e;
  background: #cf222e;
  color: #fff;
}

.error-toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 10001;
}

.error-content {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(720px, calc(100vw - 32px));
  padding: 12px 16px;
  border-radius: 12px;
  background: #cf222e;
  color: #fff;
  box-shadow: 0 18px 40px rgba(207, 34, 46, 0.28);
}

.error-close {
  border: none;
  background: transparent;
  color: inherit;
  font-size: 18px;
  cursor: pointer;
}

@media (max-width: 900px) {
  .docs-layout {
    grid-template-columns: minmax(0, 1fr);
  }

  .docs-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 999;
    width: min(88vw, 320px);
    overflow: auto;
    box-shadow: 20px 0 40px rgba(15, 23, 42, 0.16);
  }

  .docs-toolbar {
    padding: 10px 14px;
    align-items: flex-start;
    flex-direction: column;
  }
}
</style>
