<template>
  <Dialog v-model="dialogVisible" :title="dialogTitle" width="900px">
    <el-form
      ref="formRef"
      v-loading="formLoading"
      :model="formData"
      :rules="formRules"
      label-width="100px">
      <el-form-item label="功能标识" prop="identifier">
        <el-input v-model="formData.identifier" placeholder="请输入功能标识" />
      </el-form-item>
      <el-form-item label="功能名称" prop="name">
        <el-input v-model="formData.name" placeholder="请输入功能名称" />
      </el-form-item>
      <el-form-item label="功能描述" prop="description">
        <el-input
          v-model="formData.description"
          type="textarea"
          :rows="3"
          :maxlength="200"
          placeholder="请输入功能描述" />
      </el-form-item>
      <el-form-item label="功能类型" prop="type">
        <el-radio-group v-model="formData.type">
          <el-radio-button
            v-for="dict in getIntDictOptions(DICT_TYPE.IOT_THING_MODEL_TYPE)"
            :key="dict.value"
            :value="dict.value">
            {{ dict.label }}
          </el-radio-button>
        </el-radio-group>
      </el-form-item>

      <el-form-item v-if="formData.type === 1" label="属性" prop="property">
        <div class="json-editor-field">
          <div class="json-editor-toolbar">
            <span class="json-editor-toolbar__tip">请输入属性 JSON 数据</span>
            <div class="json-editor-toolbar__actions">
              <el-button text type="primary" @click="formatJsonField('property')">
                美化 JSON
              </el-button>
              <el-button text @click="compressJsonField('property')">压缩 JSON</el-button>
            </div>
          </div>
          <v-ace-editor
            v-model:value="formData.property"
            lang="json"
            theme="monokai"
            class="json-editor"
            :options="editorOptions" />
        </div>
      </el-form-item>

      <el-form-item v-if="formData.type === 3" label="事件" prop="event">
        <div class="json-editor-field">
          <div class="json-editor-toolbar">
            <span class="json-editor-toolbar__tip">请输入事件 JSON 数据</span>
            <div class="json-editor-toolbar__actions">
              <el-button text type="primary" @click="formatJsonField('event')">美化 JSON</el-button>
              <el-button text @click="compressJsonField('event')">压缩 JSON</el-button>
            </div>
          </div>
          <v-ace-editor
            v-model:value="formData.event"
            lang="json"
            theme="monokai"
            class="json-editor"
            :options="editorOptions" />
        </div>
      </el-form-item>

      <el-form-item v-if="formData.type === 2" label="服务" prop="service">
        <div class="json-editor-field">
          <div class="json-editor-toolbar">
            <span class="json-editor-toolbar__tip">请输入服务 JSON 数据</span>
            <div class="json-editor-toolbar__actions">
              <el-button text type="primary" @click="formatJsonField('service')">
                美化 JSON
              </el-button>
              <el-button text @click="compressJsonField('service')">压缩 JSON</el-button>
            </div>
          </div>
          <v-ace-editor
            v-model:value="formData.service"
            lang="json"
            theme="monokai"
            class="json-editor"
            :options="editorOptions" />
        </div>
      </el-form-item>
    </el-form>

    <template #footer>
      <el-button :disabled="formLoading" type="primary" @click="submitForm">确定</el-button>
      <el-button @click="dialogVisible = false">取消</el-button>
    </template>
  </Dialog>
</template>

<script lang="ts" setup>
import '@/components/mt-edit/ace-edit'
import { VAceEditor } from 'vue3-ace-editor'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { ThingModelCommon, type CommonThingModelData } from '@/api/iot/thingmodel'

defineOptions({ name: 'CommonThingModelForm' })

const { t } = useI18n()
const message = useMessage()

const dialogVisible = ref(false)
const dialogTitle = ref('')
const formLoading = ref(false)
const formType = ref('')
const formRef = ref()
const editorOptions = {
  useWorker: true,
  enableBasicAutocompletion: true,
  enableSnippets: true,
  enableLiveAutocompletion: true
}

const createDefaultFormData = (): CommonThingModelData => ({
  identifier: '',
  name: '',
  description: '',
  type: 1,
  property: '',
  event: '',
  service: ''
})

const formData = ref<CommonThingModelData>(createDefaultFormData())

const getJsonFieldByType = () => {
  if (formData.value.type === 1) return 'property'
  if (formData.value.type === 2) return 'service'
  return 'event'
}

const tryFormatJson = (value?: string, indent = 2) => {
  if (!value) return ''
  const trimmed = value.trim()
  if (!trimmed) return ''
  return JSON.stringify(JSON.parse(trimmed), null, indent)
}

const formatJsonField = (field: 'property' | 'event' | 'service') => {
  try {
    formData.value[field] = tryFormatJson(formData.value[field], 2)
    message.success('JSON 已美化')
  } catch {
    message.warning('当前内容不是合法 JSON，无法美化')
  }
}

const compressJsonField = (field: 'property' | 'event' | 'service') => {
  try {
    formData.value[field] = tryFormatJson(formData.value[field], 0)
    message.success('JSON 已压缩')
  } catch {
    message.warning('当前内容不是合法 JSON，无法压缩')
  }
}

const validateJsonField = (field: 'property' | 'event' | 'service', label: string) => {
  return (_rule: any, value: string, callback: (error?: Error) => void) => {
    const currentType = formData.value.type
    const fieldTypeMap = {
      property: 1,
      service: 2,
      event: 3
    }

    if (currentType !== fieldTypeMap[field]) {
      callback()
      return
    }

    if (!value) {
      callback(new Error(`${label}不能为空`))
      return
    }

    try {
      JSON.parse(value)
      callback()
    } catch {
      callback(new Error(`${label}必须是合法的 JSON`))
    }
  }
}

const formRules = reactive({
  identifier: [{ required: true, message: '功能标识不能为空', trigger: 'blur' }],
  name: [{ required: true, message: '功能名称不能为空', trigger: 'blur' }],
  type: [{ required: true, message: '功能类型不能为空', trigger: 'change' }]
  // property: [{ validator: validateJsonField('property', '属性'), trigger: 'blur' }],
  // event: [{ validator: validateJsonField('event', '事件'), trigger: 'blur' }],
  // service: [{ validator: validateJsonField('service', '服务'), trigger: 'blur' }]
})

const open = async (type: string, id?: number) => {
  dialogVisible.value = true
  dialogTitle.value = t('action.' + type)
  formType.value = type
  resetForm()
  if (!id) return

  formLoading.value = true
  try {
    const data = await ThingModelCommon.getCommonThingModel(id)
    formData.value = {
      ...createDefaultFormData(),
      ...data
    }
    const activeField = getJsonFieldByType()
    if (formData.value[activeField]) {
      formData.value[activeField] = tryFormatJson(formData.value[activeField], 2)
    }
  } finally {
    formLoading.value = false
  }
}

defineExpose({ open, close: () => (dialogVisible.value = false) })

const emit = defineEmits(['success'])

const submitForm = async () => {
  await formRef.value.validate()
  formLoading.value = true
  try {
    const payload: CommonThingModelData = {
      ...formData.value,
      property: formData.value.type === 1 ? formData.value.property : '',
      service: formData.value.type === 2 ? formData.value.service : '',
      event: formData.value.type === 3 ? formData.value.event : ''
    }

    if (formType.value === 'create') {
      await ThingModelCommon.createCommonThingModel(payload)
      message.success(t('common.createSuccess'))
    } else {
      await ThingModelCommon.updateCommonThingModel(payload)
      message.success(t('common.updateSuccess'))
    }

    dialogVisible.value = false
    emit('success')
  } finally {
    formLoading.value = false
  }
}

const resetForm = () => {
  formData.value = createDefaultFormData()
  formRef.value?.resetFields()
}

watch(
  () => formData.value.type,
  () => {
    const activeField = getJsonFieldByType()
    if (formData.value[activeField]) {
      try {
        formData.value[activeField] = tryFormatJson(formData.value[activeField], 2)
      } catch {
        // Keep original input when JSON is incomplete during editing.
      }
    }
  }
)
</script>

<style scoped>
.json-editor-field {
  width: 100%;
  border: 1px solid var(--el-border-color);
  border-radius: 8px;
  overflow: hidden;
  background: #111827;
}

.json-editor-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  background: #1f2937;
  border-bottom: 1px solid rgb(255 255 255 / 0.08);
}

.json-editor-toolbar__tip {
  font-size: 12px;
  color: rgb(255 255 255 / 0.72);
}

.json-editor-toolbar__actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.json-editor {
  width: 100%;
  height: 320px;
}
</style>
