<template>
  <el-dialog v-model="visibleInternal" :title="dialogTitle" width="600px" :close-on-click-modal="false"
    @close="closeDialog">
    <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px">
      <el-form-item label="分类名称" prop="label">
        <el-input v-model="formData.label" placeholder="请输入分类名称" clearable />
      </el-form-item>

      <el-row :gutter="24">
        <el-col :span="12">
          <el-form-item label="父级分类" prop="parentId">
            <el-tree-select v-model="formData.parentId" :data="treeData"
              :props="{ label: 'label', value: 'id', children: 'children' }" placeholder="选择父级分类（可选）" clearable
              filterable check-strictly style="width: 100%" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="排序" prop="sort">
            <el-input-number v-model="formData.sort" :min="0" :max="999" controls-position="right"
              style="width: 100%" />
          </el-form-item>
        </el-col>
      </el-row>

      <el-form-item label="默认图片" prop="image">
        <div class="uploads">
          <el-upload v-model:file-list="fileList" :auto-upload="false" :before-upload="beforeImgUpload" list-type="picture-card" :limit="1" :on-change="handleUploadChange">
            <el-icon>
              <Plus />
            </el-icon>

            <template #file="{ file }">
              <div>
                <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
                <span class="el-upload-list__item-actions">
                  <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
                    <el-icon>
                      <ZoomIn />
                    </el-icon>
                  </span>
                  <span class="el-upload-list__item-delete" @click="handleRemove(file)">
                    <el-icon>
                      <Delete />
                    </el-icon>
                  </span>
                </span>
              </div>
            </template>
          </el-upload>
          <el-dialog v-model="dialogVisible">
            <img w-full :src="dialogImageUrl" alt="Preview Image" />
          </el-dialog>

          <div class="upload-tip">
            <span>建议尺寸：250px × 140px</span>
          </div>
        </div>
      </el-form-item>

      <el-form-item label="分类描述" prop="remark">
        <el-input v-model="formData.remark" type="textarea" :rows="4" placeholder="请输入分类描述..." maxlength="200"
          show-word-limit />
      </el-form-item>

      <el-form-item label="状态" prop="status">
        <el-radio-group v-model="formData.status">
          <el-radio :label="1">启用</el-radio>
          <el-radio :label="0">禁用</el-radio>
        </el-radio-group>
      </el-form-item>
    </el-form>

    <template #footer>
      <el-button @click="closeDialog">取消</el-button>
      <el-button type="primary" @click="handleSubmit" :loading="submitLoading">
        {{ isEdit ? '更新' : '创建' }}
      </el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { Plus, ZoomIn, Delete } from '@element-plus/icons-vue'
import { ElMessage, ElUpload } from 'element-plus'
import { createCategory, editCategory, listCategories } from '@/api/article'
import { uploadFile } from '@/api/file.js'

// Props
const props = defineProps({
  modelValue: { type: Boolean, default: false },
  category: { type: Object as () => any | null, default: null }, // 传入的分类对象，null 表示新增
})

// Emits
const emit = defineEmits<{
  (e: 'update:modelValue', value: boolean): void
  (e: 'saved'): void
}>()

// 可见性同步
const visibleInternal = ref(props.modelValue)
watch(() => props.modelValue, v => (visibleInternal.value = v))
watch(visibleInternal, v => {
  emit('update:modelValue', v)
  if (v) loadTreeData()
})

// 数据加载：父级分类树
const treeData = ref<any[]>([])
watch(treeData, () => {
  // 触发tree-select重新渲染已选 label
  formData.parentId = formData.parentId ?? 0
})

async function loadTreeData() {
  const res = await listCategories({ page: 1, pageSize: 1000 })
  if (res.code === 200) {
    const list = res.data?.records || res.data || []
    treeData.value = buildTree(list)
  }
}

// 构建树形
function buildTree(data: any[]) {
  const map = new Map()
  const roots: any[] = []
  data.forEach((item) => {
    map.set(item.id, { ...item, label: item.name ?? item.label, children: [] })
  })
  map.forEach((item: any) => {
    if (item.cid && map.has(item.cid)) {
      map.get(item.cid).children.push(item)
    } else {
      roots.push(item)
    }
  })
  return [{ id: 0, label: '顶级', children: roots }]
}

// 表单
const formRef = ref()
const formData = reactive({
  id: null as number | null,
  label: '',
  image: '',
  remark: '',
  sort: 0,
  status: 1,
  parentId: 0 as number,
})

function resetForm() {
  if (formRef.value) formRef.value.clearValidate()
  Object.assign(formData, {
    id: null,
    label: '',
    image: '',
    remark: '',
    sort: 0,
    status: 1,
    parentId: 0,
  })
}

// 当传入 category 变化时同步
watch(
  () => props.category,
  (val) => {
    if (val) {
      Object.assign(formData, {
        id: val.id,
        label: val.label,
        image: val.image,
        remark: val.remark,
        sort: val.sort,
        status: val.status,
        parentId: val.parentId ?? val.cid ?? 0,
      })
    } else {
      resetForm()
    }
  },
  { immediate: true }
)

// 上传相关
const fileList = ref<any[]>([])
const dialogVisible = ref(false)
const dialogImageUrl = ref('')

function beforeImgUpload(file: File) {
  const isImage = file.type.startsWith('image/')
  const isLt10M = file.size / 1024 / 1024 < 10
  if (!isImage) ElMessage.error('仅支持图片格式')
  if (!isLt10M) ElMessage.error('图片大小不能超过10MB')
  return isImage && isLt10M
}

function handleRemove(file: any) {
  fileList.value = []
  formData.image = ''
}

async function handleUploadChange(file: any) {
  if (file.raw) {
    const isImage = file.raw.type.startsWith('image/')
    const isLt10M = file.raw.size / 1024 / 1024 < 10
    if (!isImage || !isLt10M) {
      fileList.value = []
      ElMessage.error(isImage ? '图片大小不能超过10MB' : '仅支持图片格式')
      return
    }
  }
}

function handlePictureCardPreview(file: any) {
  dialogImageUrl.value = file.url
  dialogVisible.value = true
}

// 校验
const formRules = {
  label: [
    { required: true, message: '请输入分类名称', trigger: 'blur' },
    { min: 2, max: 50, message: '分类名称长度在 2 到 50 个字符', trigger: 'blur' },
  ],
  remark: [{ max: 200, message: '描述不能超过200个字符', trigger: 'blur' }],
}

const isEdit = computed(() => !!formData.id)
// 预览对话框

const dialogTitle = computed(() => (isEdit.value ? '编辑分类' : '新增分类'))
const submitLoading = ref(false)

async function handleSubmit() {
  formRef.value.validate(async (valid: boolean) => {
    if (!valid) return
    try {
      submitLoading.value = true
      
      let imageUrl = formData.image
      
      if (fileList.value.length > 0 && fileList.value[0].raw) {
        const uploadFormData = new FormData()
        uploadFormData.append('file', fileList.value[0].raw)
        uploadFormData.append('cate', 'category')
        
        const uploadRes = await uploadFile(uploadFormData)
        if (uploadRes?.data?.url) {
          imageUrl = uploadRes.data.url
        }
      }
      
      const payload = {
        name: formData.label,
        image: imageUrl,
        desc: formData.remark,
        sort: formData.sort,
        status: formData.status,
        cid: formData.parentId,
      }
      if (isEdit.value) {
        await editCategory(formData.id, payload)
        ElMessage.success('更新成功')
      } else {
        await createCategory(payload)
        ElMessage.success('创建成功')
      }
      emit('saved')
      closeDialog()
    } catch (err) {
      console.error(err)
      ElMessage.error(isEdit.value ? '更新失败' : '创建失败')
    } finally {
      submitLoading.value = false
    }
  })
}

function closeDialog() {
  visibleInternal.value = false
  resetForm()
}
</script>

<style scoped>
/* 如果需要额外样式，可在此处编写 */
.avatar-uploader {
  .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }

  .avatar {
    width: 80px;
    height: 80px;
    display: block;
    border-radius: 6px;
  }

  .avatar-uploader-icon {
    font-size: 32px;
    color: #8c939d;
    width: 80px;
    height: 80px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
.uploads{
  display: flex;
  flex-direction: column;
}
.upload-tip {
  font-size: 12px;
  color: #999;
}
</style>
