<template>
  <div class="page-builder-editor">
    <div class="pbe-split">
      <div class="pbe-editor-col">
        <PageBuilderBlocks v-model:blocks="blocks" :site-id="siteId" />
        <el-collapse class="adv-collapse" accordion>
          <el-collapse-item title="高级：直接编辑 JSON（慎用）" name="json">
            <el-input
              v-model="jsonDraft"
              type="textarea"
              :rows="10"
              placeholder="修改后会覆盖上方可视化内容"
            />
            <el-button type="warning" style="margin-top: 8px" @click="applyJsonDraft">应用 JSON</el-button>
          </el-collapse-item>
        </el-collapse>
      </div>
      <aside class="pbe-preview-col">
        <div class="pbe-preview-head">
          <span>实时预览</span>
          <el-text size="small" type="info">与前台样式接近，保存后线上一致</el-text>
        </div>
        <div class="pbe-preview-body">
          <BlockRenderer v-if="blocks.length" :blocks="blocks" />
          <el-empty v-else description="添加模块后此处显示效果" :image-size="80" />
        </div>
      </aside>
    </div>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import PageBuilderBlocks from './PageBuilderBlocks.vue'
import BlockRenderer from '@yh-web/components/blocks/BlockRenderer.vue'
import '@yh-web/styles/page-animations.css'

const props = defineProps({
  modelValue: { type: String, default: '' },
  siteId: { type: String, default: '' }
})
const emit = defineEmits(['update:modelValue'])

const blocks = ref([])
const jsonDraft = ref('')
let syncingFromParent = false

function newBlockId() {
  return 'b-' + Date.now() + '-' + Math.random().toString(36).slice(2, 10)
}

function normalizeBlock(b) {
  if (!b.id) b.id = newBlockId()
  if (!b.props) b.props = {}
  if (!b.animation) b.animation = { enter: 'fadeIn', delay_ms: 0, duration_ms: 600 }
  if (b.type === 'link_list' && !Array.isArray(b.props.items)) b.props.items = []
  if (b.type === 'section' && !Array.isArray(b.children)) b.children = []
  if (Array.isArray(b.children)) b.children.forEach(normalizeBlock)
}

function parseFromString(s) {
  syncingFromParent = true
  try {
    const j = JSON.parse(s || '{}')
    const raw = Array.isArray(j.blocks) ? JSON.parse(JSON.stringify(j.blocks)) : []
    raw.forEach(normalizeBlock)
    blocks.value = raw
    jsonDraft.value = JSON.stringify({ version: j.version || 1, blocks: blocks.value }, null, 2)
  } catch {
    blocks.value = []
    jsonDraft.value = '{"version":1,"blocks":[]}'
  }
  syncingFromParent = false
}

function stringify() {
  return JSON.stringify({ version: 1, blocks: blocks.value }, null, 2)
}

watch(
  () => props.modelValue,
  (v) => {
    if (syncingFromParent) return
    parseFromString(v)
  },
  { immediate: true }
)

watch(
  blocks,
  () => {
    if (syncingFromParent) return
    const s = stringify()
    jsonDraft.value = s
    emit('update:modelValue', s)
  },
  { deep: true }
)

function applyJsonDraft() {
  try {
    const j = JSON.parse(jsonDraft.value || '{}')
    if (!Array.isArray(j.blocks)) {
      ElMessage.error('JSON 须包含 blocks 数组')
      return
    }
    syncingFromParent = true
    blocks.value = JSON.parse(JSON.stringify(j.blocks))
    blocks.value.forEach(normalizeBlock)
    syncingFromParent = false
    emit('update:modelValue', stringify())
    ElMessage.success('已应用')
  } catch (e) {
    ElMessage.error('JSON 格式错误')
  }
}
</script>

<style scoped>
.page-builder-editor {
  width: 100%;
}
.pbe-split {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  flex-wrap: wrap;
}
.pbe-editor-col {
  flex: 1 1 420px;
  min-width: 320px;
}
.pbe-preview-col {
  flex: 0 1 380px;
  width: 100%;
  max-width: 420px;
  border: 1px solid #dcdfe6;
  border-radius: 8px;
  background: #0a0a12;
  color: #e8e8ef;
  overflow: hidden;
  position: sticky;
  top: 8px;
}
.pbe-preview-head {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  font-weight: 600;
  font-size: 14px;
}
.pbe-preview-body {
  padding: 16px;
  max-height: min(62vh, 640px);
  overflow: auto;
}
.pbe-preview-body :deep(.builder-heading),
.pbe-preview-body :deep(.builder-text),
.pbe-preview-body :deep(.builder-links a),
.pbe-preview-body :deep(.builder-btn) {
  color: inherit;
}
.pbe-preview-body :deep(.builder-text) {
  color: rgba(255, 255, 255, 0.75);
}
.pbe-preview-body :deep(.builder-links a) {
  color: #7eb8ff;
}
.pbe-preview-body :deep(hr) {
  border-color: rgba(255, 255, 255, 0.15) !important;
}
.adv-collapse {
  margin-top: 12px;
}
</style>
