<template>
  <section class="page preview-page">
    <div class="panel preview-layout">
      <aside class="structure-pane">
        <div class="panel-header">
          <h1 class="panel-title">项目结构</h1>
          <div class="toolbar">
            <el-button :icon="Refresh" :loading="loading" @click="loadStructures">刷新</el-button>
            <el-button type="primary" :icon="Download" :loading="downloading" @click="downloadSource">下载源码</el-button>
          </div>
        </div>
        <el-tabs v-model="activeType" class="type-tabs">
          <el-tab-pane
            v-for="type in templateTypes"
            :key="type.value"
            :label="type.label"
            :name="type.value"
          />
        </el-tabs>
        <div class="tree-wrap">
          <el-empty v-if="!currentTree.length && !loading" description="暂无项目结构" />
          <ProjectStructureTree v-else :data="currentTree" @file-select="handleFileSelect" />
        </div>
      </aside>

      <CodePreview :file-name="selectedFileName" :code="code" />
    </div>
  </section>
</template>

<script setup>
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
import { Download, Refresh } from '@element-plus/icons-vue'
import CodePreview from '@/components/CodePreview.vue'
import ProjectStructureTree from '@/components/ProjectStructureTree.vue'
import { downloadProject, getFileContent, getProject, getProjectStructure } from '@/api/project'
import { saveBlob, sourceZipName } from '@/utils/download'

const route = useRoute()
const projectId = computed(() => route.params.projectId)
const activeType = ref('backend')
const loading = ref(false)
const codeLoading = ref(false)
const downloading = ref(false)
const code = ref('')
const selectedFileName = ref('')
const projectConfig = ref({})
const structures = reactive({
  backend: [],
  frontend: [],
  admin_frontend: []
})

const templateTypes = computed(() => {
  const types = [{ label: '后端', value: 'backend' }]
  if (projectConfig.value.frontendEnabled !== '0') {
    types.push({ label: '前台', value: 'frontend' })
  }
  types.push({ label: '后台前端', value: 'admin_frontend' })
  return types
})

const currentTree = computed(() => structures[activeType.value] || [])

function unwrap(result) {
  return result?.data || result || []
}

function normalizeNodes(nodes, type, prefix = '') {
  return (Array.isArray(nodes) ? nodes : []).map((node, index) => {
    const label = node.label || node.name || node.path || `文件 ${index + 1}`
    const path = node.path || `${prefix}${label}`
    const children = normalizeNodes(node.children, type, `${path}/`)

    return {
      ...node,
      id: node.id || `${type}:${path}`,
      label,
      path,
      type: node.type || (children.length ? 'folder' : 'file'),
      children
    }
  })
}

function pickCodeContent(data) {
  if (typeof data === 'string') return data
  if (!data || typeof data !== 'object') return ''
  if (typeof data.content === 'string') return data.content
  const firstValue = Object.values(data).find((value) => typeof value === 'string')
  return firstValue || ''
}

async function loadType(type) {
  const result = await getProjectStructure(projectId.value, type)
  const data = unwrap(result)
  structures[type] = normalizeNodes(data, type)
}

async function loadProjectConfig() {
  const result = await getProject(projectId.value)
  projectConfig.value = unwrap(result) || {}
  if (!templateTypes.value.some((type) => type.value === activeType.value)) {
    activeType.value = 'backend'
  }
}

async function loadStructures() {
  loading.value = true
  try {
    await loadProjectConfig()
    structures.backend = []
    structures.frontend = []
    structures.admin_frontend = []
    await Promise.all(templateTypes.value.map((type) => loadType(type.value)))
  } catch (error) {
    ElMessage.error(error.message || '加载项目结构失败')
  } finally {
    loading.value = false
  }
}

async function handleFileSelect(file) {
  codeLoading.value = true
  selectedFileName.value = file.path || file.label
  code.value = ''
  try {
    const result = await getFileContent(projectId.value, {
      templateType: activeType.value,
      nodeId: file.id,
      tableId: file.tableId,
      category: file.category || file.path || file.label
    })
    const data = unwrap(result)
    code.value = pickCodeContent(data)
  } catch (error) {
    ElMessage.error(error.message || '加载文件内容失败')
  } finally {
    codeLoading.value = false
  }
}

async function downloadSource() {
  downloading.value = true
  try {
    const blob = await downloadProject(projectId.value)
    saveBlob(blob, sourceZipName({ projectId: projectId.value }))
    ElMessage.success('源码下载已开始')
  } catch (error) {
    ElMessage.error(error.message || '下载源码失败')
  } finally {
    downloading.value = false
  }
}

watch(activeType, () => {
  code.value = ''
  selectedFileName.value = ''
})

onMounted(loadStructures)
</script>

<style scoped lang="scss">
.preview-layout {
  display: grid;
  grid-template-columns: 360px minmax(0, 1fr);
  min-height: 620px;
  overflow: hidden;
}

.structure-pane {
  min-width: 0;
  background: #ffffff;
}

.type-tabs {
  padding: 0 16px;
}

.tree-wrap {
  padding: 0 12px 18px;
}

@media (max-width: 900px) {
  .preview-layout {
    grid-template-columns: 1fr;
  }
}
</style>
