<template>
  <Dialog :title="dialogTitle" v-model="dialogVisible" width="1200px" @closed="handleDialogClosed">
    <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
      <el-row>
        <el-col :span="8">
          <el-form-item :label="t('EquipmentManagement.DvRepair.repairCode')" prop="repairCode">
            <el-input
              v-model="formData.repairCode"
              :placeholder="t('EquipmentManagement.DvRepair.placeholderRepairCode')"
              :disabled="isRepairMode" />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="t('EquipmentManagement.DvRepair.repairName')" prop="repairName">
            <el-input
              v-model="formData.repairName"
              :placeholder="t('EquipmentManagement.DvRepair.placeholderRepairName')"
              :disabled="isRepairMode" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item :label="t('EquipmentManagement.DvRepair.machineryTypeId')" prop="machineryTypeId">
        <el-radio-group v-model="formData.machineryTypeId" :disabled="isRepairMode">
          <el-radio :label="1">{{ t('EquipmentManagement.DvRepair.machineryTypeDevice') }}</el-radio>
          <el-radio :label="2">{{ t('EquipmentManagement.DvRepair.machineryTypeKeyItem') }}</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-row>
        <el-col :span="8">
          <el-form-item :label="t('EquipmentManagement.DvRepair.device')" prop="deviceId">
            <el-select
              v-model="formData.deviceId" filterable clearable :loading="deviceLoading"
              :disabled="isRepairMode"
              :placeholder="t('EquipmentManagement.DvRepair.placeholderDevice')" class="!w-full">
              <el-option v-for="opt in deviceOptions" :key="String(opt.value)" :label="opt.label" :value="opt.value" />
            </el-select>
          </el-form-item>
          <el-form-item v-if="showComponentSelect" :label="t('EquipmentManagement.DvRepair.component')" prop="componentId">
            <el-select
              v-model="formData.componentId" clearable :loading="componentLoading" :disabled="isRepairMode"
              :placeholder="t('EquipmentManagement.DvRepair.placeholderComponent')" class="!w-full">
              <el-option
                v-for="opt in componentOptions" :key="String(opt.value)" :label="opt.label"
                :value="opt.value" />
            </el-select>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="8">
          <el-form-item :label="t('EquipmentManagement.DvRepair.machineryName')" prop="machineryName" :required="false">
            <el-input
              v-model="formData.machineryName"
              :placeholder="t('EquipmentManagement.DvRepair.placeholderAutoFill')"
              disabled />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="t('EquipmentManagement.DvRepair.machineryCode')" prop="machineryCode" :required="false">
            <el-input
              v-model="formData.machineryCode"
              :placeholder="t('EquipmentManagement.DvRepair.placeholderAutoFill')"
              disabled />
          </el-form-item></el-col>
        <el-col :span="8">
          <el-form-item :label="t('EquipmentManagement.DvRepair.machinerySpec')" prop="machinerySpec" :required="false">
            <el-input
              v-model="formData.machinerySpec"
              :placeholder="t('EquipmentManagement.DvRepair.placeholderAutoFill')"
              disabled />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="8">
          <el-form-item :label="t('EquipmentManagement.DvRepair.acceptedBy')" prop="acceptedBy">
            <el-select
              v-model="formData.acceptedBy" filterable clearable
              :placeholder="t('EquipmentManagement.DvRepair.placeholderAcceptedBy')" class="!w-full"
              :disabled="isRepairMode">
              <el-option v-for="item in users" :key="String(item.id)" :label="item.nickname" :value="String(item.id)" />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="t('EquipmentManagement.DvRepair.confirmBy')" prop="confirmBy">
            <el-select
              v-model="formData.confirmBy" filterable clearable
              :placeholder="t('EquipmentManagement.DvRepair.placeholderConfirmBy')" class="!w-full"
              :disabled="isRepairMode">
              <el-option v-for="item in users" :key="String(item.id)" :label="item.nickname" :value="String(item.id)" />
            </el-select>
          </el-form-item>
        </el-col>
      </el-row>

      <template v-if="showRepairFields">
        <el-row>
          <el-col :span="8">
            <el-form-item :label="t('EquipmentManagement.DvRepair.requireDate')" prop="requireDate">
              <el-date-picker
                v-model="formData.requireDate" type="date" value-format="x"
                :placeholder="t('EquipmentManagement.DvRepair.placeholderRequireDate')"
                class="!w-full" :disabled="repairFieldsDisabled" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item :label="t('EquipmentManagement.DvRepair.finishDate')" prop="finishDate">
              <el-date-picker
                v-model="formData.finishDate" type="date" value-format="x"
                :placeholder="t('EquipmentManagement.DvRepair.placeholderFinishDate')"
                class="!w-full" :disabled="repairFieldsDisabled" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item :label="t('EquipmentManagement.DvRepair.confirmDate')" prop="confirmDate">
              <el-date-picker
                v-model="formData.confirmDate" type="date" value-format="x"
                :placeholder="t('EquipmentManagement.DvRepair.placeholderConfirmDate')"
                class="!w-full" :disabled="repairFieldsDisabled" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item :label="t('EquipmentManagement.DvRepair.repairResult')" prop="repairResult">
          <Editor v-model="formData.repairResult" height="150px" :readonly="repairFieldsDisabled" />
        </el-form-item>
      </template>
    </el-form>
    <!-- 子表的表单 -->
    <el-tabs v-model="subTabsName">
      <el-tab-pane :label="t('EquipmentManagement.DvRepair.repairLineTitle')" name="dvRepairLine">
        <DvRepairLineForm ref="dvRepairLineFormRef" :repair-id="formData.id" :line-mode="lineMode" />
      </el-tab-pane>
    </el-tabs>
    <template #footer>
      <el-button @click="submitForm" type="primary" :disabled="formLoading">{{ t('common.ok') }}</el-button>
      <el-button @click="dialogVisible = false">{{ t('common.cancel') }}</el-button>
    </template>
  </Dialog>
</template>
<script setup lang="ts">
import { DvRepairApi, DvRepairVO } from '@/api/mes/dvrepair'
import DvRepairLineForm from './components/DvRepairLineForm.vue'
import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger'
import { RepairItemsApi } from '@/api/mes/repairItems'
import { getSimpleUserList, UserVO } from '@/api/system/user'

/** 设备维修记录 表单 */
defineOptions({ name: 'DvRepairForm' })

const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中：1）修改时的数据加载；2）提交的按钮禁用
const formType = ref('') // 表单的类型：create - 新增；update - 修改
const isRepairMode = computed(() => formType.value === 'update' || formType.value === 'repair')
const showRepairFields = computed(() => formType.value === 'update' || formType.value === 'repair')
const repairFieldsDisabled = computed(() => formType.value !== 'repair')
const isHydrating = ref(false)
const emit = defineEmits(['success', 'closed']) // 定义 success 事件，用于操作成功后的回调
const formData = ref({
  id: undefined,
  repairCode: undefined,
  repairName: undefined,
  deviceId: undefined as number | undefined,
  componentId: undefined as number | undefined,
  machineryId: undefined,
  machineryCode: undefined,
  machineryName: undefined,
  machineryBrand: undefined,
  machinerySpec: undefined,
  machineryTypeId: undefined,
  requireDate: undefined,
  finishDate: undefined,
  confirmDate: undefined,
  repairResult: undefined,
  acceptedBy: undefined,
  confirmBy: undefined,
  status: undefined,
  remark: undefined,
})

const lineMode = computed(() => {
  if (formType.value === 'repair') return 'repair' as const
  if (formType.value === 'update') {
    const v = formData.value.status === '' || formData.value.status === null || formData.value.status === undefined
      ? undefined
      : String(formData.value.status)
    if (v === '1') return 'readonlyWithResult' as const
  }
  return 'edit' as const
})

const showComponentSelect = computed(() => formData.value.machineryTypeId === 2)

const deviceLoading = ref(false)
const deviceOptions = ref<{ label: string; value: number; raw?: DeviceLedgerVO }[]>([])
const deviceOptionsLoaded = ref(false)

const componentLoading = ref(false)
const componentOptions = ref<{ label: string; value: number }[]>([])

const users = ref<UserVO[]>([])

const ensureUsersLoaded = async () => {
  if (users.value.length) return
  users.value = (await getSimpleUserList()) ?? []
}

const normalizeUserId = (value: any) => {
  if (value === undefined || value === null || value === '') return undefined
  const str = String(value)
  if (/^\d+$/.test(str)) return str
  const matched = users.value.find((u) => u.nickname === str)
  return matched ? String(matched.id) : str
}

const upsertDeviceOption = (
  options: { label: string; value: number; raw?: DeviceLedgerVO }[],
  option: { label: string; value: number; raw?: DeviceLedgerVO }
) => {
  const existed = options.some((o) => o.value === option.value)
  return existed ? options : [option, ...options]
}

const toComponentOption = (item: any) => {
  const id = typeof item?.id === 'number' ? item.id : Number(item?.id)
  if (Number.isNaN(id)) return undefined
  const code = item?.code ?? item?.componentCode ?? item?.subjectCode
  const name = item?.name ?? item?.componentName ?? item?.subjectName
  const label = `${code ?? ''} ${name ?? ''}`.trim() || String(id)
  return { label, value: id }
}

const loadComponentOptionsByDeviceId = async (deviceId: number) => {
  componentLoading.value = true
  try {
    const data = await RepairItemsApi.getComponentList(deviceId)
    const rows = (Array.isArray(data) ? data : data?.list ?? data?.data ?? []) as any[]
    componentOptions.value = rows.map(toComponentOption).filter(Boolean) as { label: string; value: number }[]
  } finally {
    componentLoading.value = false
  }
}

const ensureDeviceOptionsLoaded = async () => {
  if (deviceOptionsLoaded.value) return
  deviceLoading.value = true
  try {
    const data = await DeviceLedgerApi.getDeviceLedgerList({})
    const rows = (Array.isArray(data) ? data : data?.list ?? data?.data ?? []) as DeviceLedgerVO[]
    deviceOptions.value = rows
      .filter((r) => typeof r?.id === 'number')
      .map((r) => ({ label: `${r.deviceCode ?? ''} ${r.deviceName ?? ''}`.trim(), value: r.id, raw: r }))
    deviceOptionsLoaded.value = true
  } finally {
    deviceLoading.value = false
  }
}

watch(
  () => formData.value.machineryTypeId,
  (val) => {
    if (isHydrating.value) return
    formData.value.deviceId = undefined
    formData.value.componentId = undefined
    formData.value.machineryId = undefined
    formData.value.machineryCode = undefined
    formData.value.machineryName = undefined
    formData.value.machineryBrand = undefined
    formData.value.machinerySpec = undefined
    componentOptions.value = []
    setLineRows([])
  }
)

watch(
  () => formData.value.deviceId,
  async (deviceId) => {
    if (isHydrating.value) return
    formData.value.componentId = undefined
    componentOptions.value = []
    if (typeof deviceId !== 'number') {
      setLineRows([])
    }

    const option = deviceOptions.value.find((o) => o.value === deviceId)
    if (option?.raw) {
      formData.value.machineryCode = option.raw.deviceCode
      formData.value.machineryName = option.raw.deviceName
      formData.value.machinerySpec = option.raw.deviceSpec
      formData.value.machineryBrand = option.raw.deviceBrand
    }

    if (formData.value.machineryTypeId === 2 && typeof deviceId === 'number') {
      await loadComponentOptionsByDeviceId(deviceId)
    }

    if (formData.value.machineryTypeId === 1 && typeof deviceId === 'number') {
      await prefillLinesByDeviceOrComponent({ deviceId, deviceType: 1 })
    }
  }
)

watch(
  () => formData.value.componentId,
  async (componentId) => {
    if (isHydrating.value) return
    if (formData.value.machineryTypeId !== 2) return
    const deviceId = formData.value.deviceId
    if (typeof deviceId !== 'number' || typeof componentId !== 'number') {
      setLineRows([])
      return
    }
    await prefillLinesByDeviceOrComponent({ deviceId, componentId, deviceType: 2 })
  }
)
const formRules = reactive({
  repairCode: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorRepairCodeRequired'), trigger: 'blur' }],
  machineryId: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorMachineryIdRequired'), trigger: 'blur' }],
  machineryCode: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorMachineryCodeRequired'), trigger: 'blur' }],
  machineryName: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorMachineryNameRequired'), trigger: 'blur' }],
  machineryTypeId: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorMachineryTypeIdRequired'), trigger: 'blur' }],
  requireDate: [
    {
      validator: (_: any, value: any, callback: any) => {
        if (formType.value === 'repair' && !value) {
          callback(new Error(t('EquipmentManagement.DvRepair.validatorRequireDateRequired')))
          return
        }
        callback()
      },
      trigger: 'change',
    },
  ],
  finishDate: [
    {
      validator: (_: any, value: any, callback: any) => {
        if (formType.value === 'repair' && !value) {
          callback(new Error(t('EquipmentManagement.DvRepair.validatorFinishDateRequired')))
          return
        }
        callback()
      },
      trigger: 'change',
    },
  ],
  confirmDate: [
    {
      validator: (_: any, value: any, callback: any) => {
        if (formType.value === 'repair' && !value) {
          callback(new Error(t('EquipmentManagement.DvRepair.validatorConfirmDateRequired')))
          return
        }
        callback()
      },
      trigger: 'change',
    },
  ],
  repairResult: [
    {
      validator: (_: any, value: any, callback: any) => {
        if (formType.value === 'repair' && !value) {
          callback(new Error(t('EquipmentManagement.DvRepair.validatorRepairResultRequired')))
          return
        }
        callback()
      },
      trigger: 'blur',
    },
  ],
})
const formRef = ref() // 表单 Ref

/** 子表的表单 */
const subTabsName = ref('dvRepairLine')
const dvRepairLineFormRef = ref()

const normalizeDeviceOrComponentList = (data: any) => {
  const rows = (Array.isArray(data) ? data : data?.list ?? data?.data ?? []) as any[]
  return rows
}

const toDvRepairLineRow = (item: any) => {
  const subjectId = item?.subjectId ?? item?.id
  return {
    id: undefined,
    repairId: formData.value.id,
    subjectId,
    subjectCode: item?.subjectCode ?? item?.subject_code ?? item?.code,
    subjectName: item?.subjectName ?? item?.subject_name ?? item?.name,
    subjectType: item?.subjectType ?? item?.subject_type ?? item?.type,
    subjectContent: item?.subjectContent ?? item?.projectContent ?? item?.subject_content,
    subjectStandard: item?.subjectStandard ?? item?.judgmentCriteria ?? item?.subject_standard,
    malfunction: undefined,
    malfunctionUrl: undefined,
    repairDes: undefined,
    remark: undefined
  }
}

const setLineRows = (rows: any[]) => {
  dvRepairLineFormRef.value?.setData(rows)
}

const prefillLinesByDeviceOrComponent = async (params: { deviceId: number; componentId?: number; deviceType: number }) => {
  if (formType.value !== 'create') return
  const data = await RepairItemsApi.getDeviceOrComponentList(params)
  const list = normalizeDeviceOrComponentList(data)
  setLineRows(list.map(toDvRepairLineRow))
}

let openRequestId = 0

/** 打开弹窗 */
const open = async (type: string, id?: number) => {
  const currentOpenId = ++openRequestId
  dialogVisible.value = true
  dialogTitle.value = type === 'repair' ? '维修' : t('action.' + type)
  formType.value = type
  resetForm()
  await ensureUsersLoaded()
  await ensureDeviceOptionsLoaded()
  if (currentOpenId !== openRequestId) return
  // 修改时，设置数据
  if (id) {
    formLoading.value = true
    try {
      isHydrating.value = true
      formData.value = await DvRepairApi.getDvRepair(id)

      if (currentOpenId !== openRequestId) return

        ; (formData.value as any).requireDate = (formData.value as any).requireDate ?? undefined
        ; (formData.value as any).finishDate = (formData.value as any).finishDate ?? undefined
        ; (formData.value as any).confirmDate = (formData.value as any).confirmDate ?? undefined
        ; (formData.value as any).repairResult = (formData.value as any).repairResult ?? ''

        ; (formData.value as any).acceptedBy = normalizeUserId((formData.value as any).acceptedBy)
        ; (formData.value as any).confirmBy = normalizeUserId((formData.value as any).confirmBy)

      const typeId = typeof formData.value.machineryTypeId === 'number' ? formData.value.machineryTypeId : Number(formData.value.machineryTypeId)
      formData.value.machineryTypeId = Number.isNaN(typeId) ? formData.value.machineryTypeId : typeId

      const deviceId = (formData.value as any).deviceId
      const resolvedDeviceId = typeof deviceId === 'number' ? deviceId : formData.value.machineryId
      if (typeof resolvedDeviceId === 'number') {
        formData.value.deviceId = resolvedDeviceId
        const label = `${formData.value.machineryCode ?? ''} ${formData.value.machineryName ?? ''}`.trim() || `ID:${resolvedDeviceId}`
        deviceOptions.value = upsertDeviceOption(deviceOptions.value, { label, value: resolvedDeviceId })
      }

      if (formData.value.machineryTypeId === 2 && typeof formData.value.deviceId === 'number') {
        await loadComponentOptionsByDeviceId(formData.value.deviceId)
        const componentId = (formData.value as any).componentId
        const resolvedComponentId = typeof componentId === 'number' ? componentId : Number(componentId)
        if (!Number.isNaN(resolvedComponentId)) {
          formData.value.componentId = resolvedComponentId
        }
      }
    } finally {
      isHydrating.value = false
      formLoading.value = false
    }
  }
}
defineExpose({ open }) // 提供 open 方法，用于打开弹窗

const handleDialogClosed = () => {
  openRequestId++
  emit('closed')
}

onBeforeUnmount(() => {
  openRequestId++
})

/** 提交表单 */
const submitForm = async () => {
  // 校验表单
  await formRef.value.validate()
  // 校验子表单
  try {
    await dvRepairLineFormRef.value.validate()
  } catch (e) {
    subTabsName.value = 'dvRepairLine'
    return
  }
  // 提交请求
  formLoading.value = true
  try {
    const data = { ...(formData.value as any) } as DvRepairVO & { deviceId?: number; componentId?: number }
      ; (data as any).acceptedBy = normalizeUserId((data as any).acceptedBy)
      ; (data as any).confirmBy = normalizeUserId((data as any).confirmBy)
    if (formType.value === 'repair') {
      ; (data as any).status = 1
    }
    if (typeof formData.value.deviceId === 'number') {
      data.machineryId = formData.value.deviceId as any
    }
    ; (data as any).deviceId = formData.value.deviceId
      ; (data as any).componentId = formData.value.machineryTypeId === 2 ? formData.value.componentId : undefined
    const lineList = dvRepairLineFormRef.value.getData() || []
    if (formType.value === 'repair') {
      const requireDate = data.requireDate
      const finishDate = data.finishDate
      const confirmDate = data.confirmDate
      const repairResult = data.repairResult
      const updateReqVOList = lineList
      await DvRepairApi.updateDvRepairStatus({
        id: data.id,
        requireDate,
        finishDate,
        confirmDate,
        repairResult,
        updateReqVOList,
      })
      message.success(t('common.updateSuccess'))
    } else {
      ; (data as any).dvRepairLines = lineList
      if (formType.value === 'create') {
        await DvRepairApi.createDvRepair(data)
        message.success(t('common.createSuccess'))
      } else {
        await DvRepairApi.updateDvRepair(data)
        message.success(t('common.updateSuccess'))
      }
    }
    dialogVisible.value = false
    // 发送操作成功的事件
    emit('success')
  } finally {
    formLoading.value = false
  }
}

/** 重置表单 */
const resetForm = () => {
  formData.value = {
    id: undefined,
    repairCode: undefined,
    repairName: undefined,
    deviceId: undefined,
    componentId: undefined,
    machineryId: undefined,
    machineryCode: undefined,
    machineryName: undefined,
    machineryBrand: undefined,
    machinerySpec: undefined,
    machineryTypeId: 1,
    requireDate: undefined,
    finishDate: undefined,
    confirmDate: undefined,
    repairResult: '',
    acceptedBy: undefined,
    confirmBy: undefined,
    status: undefined,
    remark: undefined,
  }
  deviceOptionsLoaded.value = false
  componentOptions.value = []
  formRef.value?.resetFields()
}
</script>
