<template>
  <section class="page module-diagram-editor-page" v-loading="loading">
    <div class="panel module-editor-shell">
      <div class="panel-header">
        <div>
          <h1 class="panel-title">功能模块图编辑器</h1>
          <p class="muted">{{ project.projectName || '输入缩进结构，生成论文风格功能模块图。' }}</p>
        </div>
        <div class="toolbar">
          <el-button v-if="projectId" @click="router.push(`/project/${projectId}/diagrams`)">返回图表中心</el-button>
          <el-button v-if="projectId" type="primary" :loading="saving" @click="saveEditorDiagram">保存到项目</el-button>
        </div>
      </div>

      <div class="module-editor-layout">
        <aside class="module-editor-side">
          <div class="module-editor-side-header">
            <strong>缩进结构</strong>
            <div class="module-editor-side-actions">
              <el-button text type="primary" @click="loadExampleOutline">示例</el-button>
              <el-button v-if="projectId" text type="primary" @click="useBlueprintOutline">使用项目蓝图</el-button>
            </div>
          </div>
          <el-input
            v-model="editableOutlineText"
            type="textarea"
            :rows="22"
            resize="none"
            spellcheck="false"
            placeholder="第一行写系统名称；第二层缩进 2 个空格；第三层及以下作为功能节点。"
          />
        </aside>

        <main class="module-editor-canvas">
          <AppModuleDiagramView
            v-model:source-mode="sourceMode"
            v-model:outline-text="outlineText"
            v-model:layout-options="layoutOptions"
            :blueprint="appBlueprint"
            :project-name="project.projectName"
            :editable="false"
          />
        </main>
      </div>
    </div>
  </section>
</template>

<script setup>
import { computed, onMounted, reactive, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import AppModuleDiagramView from '@/components/AppModuleDiagramView.vue'
import { getProject, listProjectDiagrams, saveProjectDiagram } from '@/api/project'
import { blueprintToModuleOutline, moduleOutlineToText, parseModuleOutlineText } from '@/utils/appModuleOutline'
import { buildAppModuleGraph } from '@/utils/appModuleGraph'

const EXAMPLE_OUTLINE = `学生社团管理系统
  管理员端
    注册登录
    用户管理
    社团管理
    成员管理
    活动管理
    公告管理
    系统管理
  普通用户端
    注册登录
    社团浏览
    社团申请
    活动浏览
    活动报名
    个人中心`

const route = useRoute()
const router = useRouter()
const projectId = computed(() => route.params.projectId || route.query.projectId || '')
const loading = ref(false)
const saving = ref(false)
const project = reactive({})
const savedDiagrams = ref([])
const sourceMode = ref('outline')
const outlineText = ref(EXAMPLE_OUTLINE)
const layoutOptions = ref({ density: 'standard', direction: 'horizontal', fontSize: 'standard' })

const appBlueprint = computed(() => parseJson(project.appBlueprint, { roles: [], frontendMenus: [], adminMenus: [] }))
const blueprintOutlineText = computed(() => moduleOutlineToText(blueprintToModuleOutline(appBlueprint.value, { projectName: project.projectName })))
const activeOutlineText = computed(() => sourceMode.value === 'blueprint' ? blueprintOutlineText.value : outlineText.value)
const currentGraph = computed(() => buildAppModuleGraph(parseModuleOutlineText(activeOutlineText.value).outline, layoutOptions.value))
const editableOutlineText = computed({
  get: () => outlineText.value,
  set: (value) => {
    outlineText.value = value
    sourceMode.value = 'outline'
  }
})

function parseJson(value, fallback) {
  if (!value) return fallback
  if (typeof value === 'object') return value
  try {
    return JSON.parse(value)
  } catch (error) {
    return fallback
  }
}

function loadExampleOutline() {
  outlineText.value = EXAMPLE_OUTLINE
  sourceMode.value = 'outline'
}

function useBlueprintOutline() {
  const text = blueprintOutlineText.value
  outlineText.value = text || EXAMPLE_OUTLINE
  sourceMode.value = 'outline'
}

function normalizeLayoutOptions(value = {}) {
  return {
    density: value.density || 'standard',
    direction: value.direction || 'horizontal',
    fontSize: value.fontSize || 'standard'
  }
}

function editorDiagramPayload() {
  return {
    sourceMode: sourceMode.value,
    outlineText: outlineText.value,
    layoutOptions: layoutOptions.value,
    graph: currentGraph.value,
    projectName: project.projectName
  }
}

function applySavedModuleDiagram(saved) {
  const payload = parseJson(saved?.diagramJson, null)
  if (!payload || typeof payload !== 'object') {
    useBlueprintOutline()
    return
  }
  sourceMode.value = payload.sourceMode === 'blueprint' ? 'blueprint' : 'outline'
  outlineText.value = typeof payload.outlineText === 'string' ? payload.outlineText : (blueprintOutlineText.value || EXAMPLE_OUTLINE)
  layoutOptions.value = normalizeLayoutOptions(payload.layoutOptions)
}

async function loadEditorData() {
  if (!projectId.value) return
  loading.value = true
  try {
    const [projectResult, diagramsResult] = await Promise.all([
      getProject(projectId.value),
      listProjectDiagrams(projectId.value)
    ])
    Object.assign(project, projectResult || {})
    savedDiagrams.value = Array.isArray(diagramsResult) ? diagramsResult : []
    const saved = savedDiagrams.value.find((item) => item.diagramType === 'module')
    if (saved) {
      applySavedModuleDiagram(saved)
    } else {
      useBlueprintOutline()
    }
  } catch (error) {
    ElMessage.error(error.message || '加载模块图失败')
  } finally {
    loading.value = false
  }
}

async function saveEditorDiagram() {
  if (!projectId.value) return
  const existing = savedDiagrams.value.find((item) => item.diagramType === 'module')
  saving.value = true
  try {
    const saved = await saveProjectDiagram(projectId.value, {
      diagramId: existing?.diagramId,
      diagramType: 'module',
      title: '功能模块图',
      description: '系统功能模块图草稿',
      diagramJson: JSON.stringify(editorDiagramPayload())
    })
    if (saved?.diagramId) {
      const index = savedDiagrams.value.findIndex((item) => item.diagramId === saved.diagramId)
      if (index >= 0) {
        savedDiagrams.value.splice(index, 1, saved)
      } else {
        savedDiagrams.value.unshift(saved)
      }
    }
    ElMessage.success('功能模块图已保存')
  } catch (error) {
    ElMessage.error(error.message || '保存模块图失败')
  } finally {
    saving.value = false
  }
}

onMounted(loadEditorData)
</script>

<style scoped lang="scss">
.module-diagram-editor-page {
  display: grid;
  gap: 18px;
}

.module-editor-shell {
  overflow: hidden;
}

.module-editor-layout {
  display: grid;
  grid-template-columns: minmax(300px, 360px) minmax(0, 1fr);
  min-height: 640px;
}

.module-editor-side {
  display: grid;
  align-content: start;
  gap: 12px;
  padding: 18px;
  border-right: 1px solid #e7ecf3;
  background: #fbfdff;
}

.module-editor-side-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.module-editor-side-header strong {
  color: #172033;
  font-size: 15px;
}

.module-editor-side-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
}

.module-editor-side :deep(.el-textarea__inner) {
  min-height: 560px !important;
  border-color: #d9e0ea;
  color: #172033;
  font-family: Consolas, "Courier New", "Microsoft YaHei", monospace;
  font-size: 14px;
  line-height: 1.65;
}

.module-editor-canvas {
  min-width: 0;
  background: #ffffff;
}

@media (max-width: 980px) {
  .module-editor-layout {
    grid-template-columns: 1fr;
  }

  .module-editor-side {
    border-right: 0;
    border-bottom: 1px solid #e7ecf3;
  }
}
</style>
