<!--
  ThemeEditor.vue — LiteDesign 可视化编辑器（重构版）

  三栏布局：组件库 | 预览区 | 属性配置
  核心功能：SortableJS拖拽 + Schema驱动表单 + 撤销重做 + 层级管理 + 多端预览

  兼容旧版数据格式：自动将 store.components 映射为 API 请求体
-->
<template>
  <div class="theme-editor">
    <!-- ===== 顶部工具栏 ===== -->
    <header class="editor-toolbar">
      <div class="toolbar-left">
        <span class="toolbar-title">📐 页面装修</span>
        <el-select v-model="currentTemplateId" placeholder="选择模板" size="small" style="width:180px" @change="loadTemplate">
          <el-option v-for="t in templates" :key="t.id" :label="t.name+(t.is_default?' ⭐':'')" :value="t.id" />
        </el-select>
        <el-button size="small" @click="showNewDialog=true">+ 新建</el-button>
        <el-tooltip content="撤销 Ctrl+Z"><el-button size="small" :disabled="!store.canUndo" @click="store.undo()">↩</el-button></el-tooltip>
        <el-tooltip content="重做 Ctrl+Shift+Z"><el-button size="small" :disabled="!store.canRedo" @click="store.redo()">↪</el-button></el-tooltip>
        <el-divider direction="vertical" />
        <el-tooltip content="清空画布"><el-button size="small" @click="handleClearCanvas">🗑 清空</el-button></el-tooltip>
        <el-tooltip content="恢复默认模板"><el-button size="small" @click="handleResetDefault">↺ 恢复默认</el-button></el-tooltip>
        <el-divider direction="vertical" />
        <span style="font-size:12px;color:#999">主题：</span>
        <el-select v-model="currentThemeId" size="small" style="width:130px" @change="applyTheme">
          <el-option v-for="t in themes" :key="t.id" :value="t.id">
            <span><span class="theme-dot" :style="{background:t.colors.primary}"></span>{{t.name}}</span>
          </el-option>
        </el-select>
      </div>
      <div class="toolbar-right">
        <el-button size="small" @click="showPreview=true">👁 预览</el-button>
        <el-button size="small" @click="handleExport">⬇ 导出</el-button>
        <el-button size="small" @click="handleImport">📂 导入</el-button>
        <el-button size="small" type="primary" :loading="store.isSaving" @click="handleSave">💾 保存</el-button>
        <el-button size="small" type="success" :loading="store.isPublishing" @click="handlePublish">🚀 发布</el-button>
      </div>
    </header>

    <!-- ===== 主体三栏布局 ===== -->
    <div class="editor-body">
      <!-- 左侧：组件库 -->
      <WidgetPanel @add-component="addComponent" />

      <!-- 中间：预览区 -->
      <PhonePreview ref="previewRef" />

      <!-- 右侧：属性/层级 → 可折叠 tab 切换 -->
      <aside class="right-column">
        <div class="right-tabs">
          <div
            class="right-tab"
            :class="{ active: rightPanel === 'props' }"
            @click="rightPanel = 'props'"
          >⚙️ 属性配置</div>
          <div
            class="right-tab"
            :class="{ active: rightPanel === 'layer' }"
            @click="rightPanel = 'layer'"
          >🔲 层级管理</div>
        </div>
        <div v-show="rightPanel === 'props'" class="right-body"><ConfigPanel /></div>
        <div v-show="rightPanel === 'layer'" class="right-body"><LayerPanel /></div>
      </aside>
    </div>

    <!-- ===== 全屏预览弹窗 ===== -->
    <el-dialog v-model="showPreview" title="预览" width="420px" class="preview-dialog" top="5vh">
      <div class="fullscreen-preview">
        <div class="fp-screen">
          <div v-for="comp in store.components" :key="comp.id" class="fp-comp">
            <!-- 复用内部预览类似的渲染 -->
            <SwiperPreview    v-if="comp.type==='swiper'"        :props="comp.props" />
            <NavGroupPreview  v-else-if="comp.type==='navGroup'"       :props="comp.props" />
            <TitleBarPreview  v-else-if="comp.type==='titleBar'"       :props="comp.props" />
            <ImageAdPreview   v-else-if="comp.type==='imageAd'"        :props="comp.props" />
            <NoticeBarPreview v-else-if="comp.type==='noticeBar'"      :props="comp.props" />
            <SpacerPreview    v-else-if="comp.type==='spacer'"         :props="comp.props" />
            <DividerPreview   v-else-if="comp.type==='divider'"        :props="comp.props" />
            <ProductListPreview v-else-if="comp.type==='productList'"  :props="comp.props" />
            <SeckillPreview   v-else-if="comp.type==='seckillEntry'"   :props="comp.props" />
            <CouponPreview    v-else-if="comp.type==='couponEntry'"    :props="comp.props" />
            <SearchBoxPreview v-else-if="comp.type==='searchBox'"     :props="comp.props" />
            <PromotionListPreview v-else-if="comp.type==='promotionList'":props="comp.props" />
          </div>
        </div>
      </div>
    </el-dialog>

    <!-- ===== 新建模板弹窗 ===== -->
    <el-dialog v-model="showNewDialog" title="新建模板" width="400px">
      <el-form label-width="80px">
        <el-form-item label="名称"><el-input v-model="newTemplateName" /></el-form-item>
        <el-form-item label="终端">
          <el-select v-model="newTemplateTerminal" style="width:100%">
            <el-option label="H5移动端" value="h5" />
            <el-option label="PC电脑端" value="pc" />
            <el-option label="小程序" value="miniapp" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showNewDialog=false">取消</el-button>
        <el-button type="primary" @click="createTemplate">创建</el-button>
      </template>
    </el-dialog>

    <!-- ===== 隐藏的导入input ===== -->
    <input ref="importInput" type="file" accept=".json" style="display:none" @change="onImportFile" />
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import axios from 'axios'

import { useDesignStore } from '../stores/designStore.js'
import { COMPONENT_REGISTRY } from './design/utils/componentRegistry.js'

// 子组件
import WidgetPanel from './design/components/WidgetPanel.vue'
import PhonePreview from './design/components/PhonePreview.vue'
import ConfigPanel from './design/components/ConfigPanel.vue'
import LayerPanel from './design/components/LayerPanel.vue'

// 预览子组件（用于全屏预览）
import SwiperPreview from './design/components/preview/SwiperPreview.vue'
import NavGroupPreview from './design/components/preview/NavGroupPreview.vue'
import TitleBarPreview from './design/components/preview/TitleBarPreview.vue'
import ImageAdPreview from './design/components/preview/ImageAdPreview.vue'
import NoticeBarPreview from './design/components/preview/NoticeBarPreview.vue'
import SpacerPreview from './design/components/preview/SpacerPreview.vue'
import DividerPreview from './design/components/preview/DividerPreview.vue'
import ProductListPreview from './design/components/preview/ProductListPreview.vue'
import SeckillPreview from './design/components/preview/SeckillEntryPreview.vue'
import CouponPreview from './design/components/preview/CouponEntryPreview.vue'
import SearchBoxPreview from './design/components/preview/SearchBoxPreview.vue'
import PromotionListPreview from './design/components/preview/PromotionListPreview.vue'

const store = useDesignStore()

// 右侧面板 tab：属性配置 / 层级管理
const rightPanel = ref('props')
const previewRef = ref(null)
const importInput = ref(null)

// ===== 模板管理 =====
const templates = ref([])
const currentTemplateId = ref(null)
const showNewDialog = ref(false)
const newTemplateName = ref('')
const newTemplateTerminal = ref('h5')
const showPreview = ref(false)

// ===== 主题 =====
const currentThemeId = ref('icy_blue')
const themes = ref([
  { id: 'icy_blue', name: '冰蓝', colors: { primary: '#6366F1' } },
  { id: 'twilight', name: '暮山紫', colors: { primary: '#7C3AED' } },
  { id: 'forest', name: '森林绿', colors: { primary: '#10B981' } },
  { id: 'sunset', name: '日落橙', colors: { primary: '#F59E0B' } },
  { id: 'rose', name: '玫瑰红', colors: { primary: '#EF4444' } }
])

// ===== 键盘快捷键 =====
function handleKeydown(e) {
  if ((e.ctrlKey || e.metaKey) && e.key === 'z') {
    e.preventDefault()
    if (e.shiftKey) store.redo()
    else store.undo()
  }
}

onMounted(() => {
  window.addEventListener('keydown', handleKeydown)
  loadTemplates()
  // 加载默认模板
  loadDefaultTemplate()
})

onBeforeUnmount(() => {
  window.removeEventListener('keydown', handleKeydown)
})

// ===== 加载模板列表 =====
async function loadTemplates() {
  try {
    const res = await axios.get('/api/admin/design/templates')
    if (res.data && res.data.data) {
      templates.value = res.data.data
    }
  } catch (e) {
    // 静默失败
  }
}

// ===== 加载模板 =====
async function loadTemplate(id) {
  if (!id) return
  currentTemplateId.value = id
  try {
    const res = await axios.get(`/api/admin/design/templates/${id}`)
    if (res.data && res.data.data) {
      store.loadTemplate(res.data.data)
    }
  } catch (e) {
    ElMessage.warning('加载模板失败')
  }
}

// ===== 清空画布 =====
function handleClearCanvas() {
  if (!store.components.length) { ElMessage.info('画布已是空状态'); return }
  ElMessageBox.confirm('确定清空当前画布全部组件？\n可点↩撤销恢复。', '清空画布', {
    type: 'warning', confirmButtonText: '清空', cancelButtonText: '取消'
  }).then(() => {
    store.setComponents([])
    ElMessage.success('已清空')
  }).catch(() => {})
}

// ===== 恢复默认模板 =====
function handleResetDefault() {
  ElMessageBox.confirm('将用默认模板覆盖当前画布？\n可点↩撤销恢复。', '恢复默认', {
    type: 'info', confirmButtonText: '恢复', cancelButtonText: '取消'
  }).then(() => {
    loadDefaultTemplate()
    ElMessage.success('已恢复默认模板')
  }).catch(() => {})
}

// ===== 默认模板 =====
function loadDefaultTemplate() {
  // 加载默认首页组件，使用与老版相同的默认数据
  store.reset()
  store.addComponent('swiper')
  store.addComponent('searchBox')
  store.addComponent('navGroup')
  store.addComponent('seckillEntry')
  store.addComponent('titleBar')
  store.addComponent('productList')
  store.addComponent('spacer')
  store.addComponent('divider')
  store.addComponent('couponEntry')
  store.addComponent('noticeBar')
  store.addComponent('imageAd')
}

// ===== 新建模板 =====
async function createTemplate() {
  if (!newTemplateName.value) {
    ElMessage.warning('请输入模板名称')
    return
  }
  try {
    const res = await axios.post('/api/admin/design/templates', {
      name: newTemplateName.value,
      terminal: newTemplateTerminal.value
    })
    if (res.data && res.data.data) {
      ElMessage.success('模板已创建')
      showNewDialog.value = false
      await loadTemplates()
      currentTemplateId.value = res.data.data.id
      store.reset()
      store.templateName.value = newTemplateName.value
      store.terminal.value = newTemplateTerminal.value
      store.templateId.value = res.data.data.id
    }
  } catch (e) {
    ElMessage.error('创建失败')
  }
}

// ===== 添加组件（从左侧面板添加） =====
function addComponent(type) {
  store.addComponent(type)
}

// ===== 保存 =====
async function handleSave() {
  store.isSaving.value = true
  try {
    const data = store.getTemplateData()
    // API 格式兼容：转换为后端期望的格式（content JSON blob）
    const payload = {
      name: store.templateName,
      terminal: store.terminal,
      content: JSON.stringify({
        themeName: store.themeName,
        components: data.components.map(c => ({
          id: c.id,
          type: c.type,
          props: c.props
        }))
      })
    }

    if (store.templateId) {
      await axios.put(`/api/admin/design/templates/${store.templateId}`, payload)
    } else {
      const res = await axios.post('/api/admin/design/templates', payload)
      if (res.data && res.data.data) {
        store.templateId = res.data.data.id
        currentTemplateId.value = res.data.data.id
        await loadTemplates()
      }
    }
    ElMessage.success('已保存')
  } catch (e) {
    ElMessage.error('保存失败')
  } finally {
    store.isSaving.value = false
  }
}

// ===== 发布 =====
async function handlePublish() {
  try {
    await ElMessageBox.confirm(`发布「${store.templateName}」将覆盖线上页面，确认发布？`, '确认发布')
  } catch {
    return
  }

  store.isPublishing.value = true
  try {
    // 先保存
    await handleSave()
    // 再设置默认
    if (store.templateId) {
      await axios.post(`/api/admin/design/templates/${store.templateId}/set-default`)
      ElMessage.success('🚀 已发布上线！')
      await loadTemplates()
    }
  } catch (e) {
    ElMessage.error('发布失败')
  } finally {
    store.isPublishing.value = false
  }
}

// ===== 导出 =====
function handleExport() {
  const data = store.getTemplateData()
  const blob = new Blob([JSON.stringify({ themeName: store.themeName, components: data.components }, null, 2)], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `${store.templateName || '装修模板'}.json`
  a.click()
  URL.revokeObjectURL(url)
  ElMessage.success('导出成功')
}

// ===== 导入 =====
function handleImport() {
  importInput.value?.click()
}

function onImportFile(e) {
  const file = e.target.files?.[0]
  if (!file) return
  const reader = new FileReader()
  reader.onload = (ev) => {
    try {
      const data = JSON.parse(ev.target.result)
      if (data.components) {
        store.loadTemplate({ name: file.name.replace('.json', ''), ...data })
        ElMessage.success(`已导入 ${file.name}`)
      } else {
        ElMessage.warning('JSON 格式不正确，需要包含 components 字段')
      }
    } catch {
      ElMessage.error('JSON 解析失败')
    }
  }
  reader.readAsText(file)
  e.target.value = ''
}

// ===== 主题 =====
function applyTheme(id) {
  const theme = themes.value.find(t => t.id === id)
  if (theme) {
    document.documentElement.style.setProperty('--theme-primary', theme.colors.primary)
    store.themeName = theme.name
  }
}
</script>

<style scoped>
.theme-editor {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 90px);
  background: #f0f2f5;
  border-radius: 8px;
  overflow: hidden;
}

/* ===== 顶部工具栏 ===== */
.editor-toolbar {
  height: 52px;
  background: #fff;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  border-bottom: 1px solid #e8eaed;
  flex-shrink: 0;
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 8px;
}

.toolbar-title {
  font-size: 15px;
  font-weight: 700;
  color: #333;
  margin-right: 4px;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 6px;
}

.theme-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-right: 4px;
  vertical-align: middle;
}

/* ===== 主体 ===== */
.editor-body {
  flex: 1;
  display: flex;
  overflow: hidden;
}

.right-column {
  width: 290px;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
}

/* 属性/层级 折叠 tab */
.right-tabs {
  display: flex;
  border-bottom: 1px solid #eef0f5;
  background: #fff;
  flex-shrink: 0;
}

.right-tab {
  flex: 1;
  padding: 10px 0;
  text-align: center;
  font-size: 13px;
  color: #666;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: color .15s, border-color .15s;
  user-select: none;
}

.right-tab:hover {
  color: var(--theme-primary, #6366F1);
  background: #faf9ff;
}

.right-tab.active {
  color: var(--theme-primary, #6366F1);
  font-weight: 600;
  border-bottom-color: var(--theme-primary, #6366F1);
}

.right-body {
  flex: 1;
  overflow-y: auto;
}
</style>

<style>
/* 全局主题色 */
.theme-editor {
  --theme-primary: #6366F1;
  --theme-primary-light: #f0ecff;
}

/* 预览弹窗样式 */
.preview-dialog .el-dialog__body {
  padding: 0;
  background: #f8f8f8;
}

.fullscreen-preview {
  padding: 0;
}

.fp-screen {
  width: 375px;
  margin: 0 auto;
  min-height: 600px;
}

.fp-comp {
  margin: 0;
}
</style>
