<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import { List } from './types'

const { t } = useI18n()

const visible = ref(false)

type AccumulatedAttr = {
  pointName: string
  totalRunTime?: number | null
}

interface Props {
  row: List
  readonly: boolean
  timeAccumulatedAttrs: AccumulatedAttr[]
  mileageAccumulatedAttrs: AccumulatedAttr[]
}

const form = ref<List>({
  deviceId: 0,
  bomNodeId: '',
  deviceCode: '',
  deviceName: '',
  name: '',
  runningTimeRule: 0,
  mileageRule: 0,
  naturalDateRule: 0,
  totalRunTime: null,
  tempTotalRunTime: null,
  totalMileage: null,
  tempTotalMileage: null,
  lastMaintenanceDate: null,
  lastRunningTime: null,
  nextRunningTime: null,
  lastRunningKilometers: null,
  nextRunningKilometers: null,
  lastNaturalDate: null,
  nextNaturalDate: null,
  kiloCycleLead: null,
  timePeriodLead: null,
  naturalDatePeriodLead: null,
  code: null,
  type: null
})
const isReadonly = ref<boolean>(false)
const sourceRow = ref<List>()
const formRef = ref<FormInstance>()
const timeAccumulatedAttrs = ref<AccumulatedAttr[]>([])
const mileageAccumulatedAttrs = ref<AccumulatedAttr[]>([])

const timeEnable = computed(() => form.value.runningTimeRule === 0)
const mileageEnable = computed(() => form.value.mileageRule === 0)
const naturalDateEnable = computed(() => form.value.naturalDateRule === 0)
const timeAccumulatedVisible = computed(
  () =>
    timeEnable.value &&
    timeAccumulatedAttrs.value.length > 0 &&
    (form.value.totalRunTime == null || isNaN(form.value.totalRunTime))
)
const mileageAccumulatedVisible = computed(
  () =>
    mileageEnable.value &&
    mileageAccumulatedAttrs.value.length > 0 &&
    (form.value.totalMileage == null || isNaN(form.value.totalMileage))
)
const accumulatedVisible = computed(
  () => timeAccumulatedVisible.value || mileageAccumulatedVisible.value
)

type NumberFieldProp =
  | 'lastRunningTime'
  | 'nextRunningTime'
  | 'timePeriodLead'
  | 'lastRunningKilometers'
  | 'nextRunningKilometers'
  | 'kiloCycleLead'
  | 'nextNaturalDate'
  | 'naturalDatePeriodLead'
type DateFieldProp = 'lastNaturalDate'
type NumberFieldConfig = {
  label: string
  prop: NumberFieldProp
  type: 'number'
  precision?: number
}
type DateFieldConfig = {
  label: string
  prop: DateFieldProp
  type: 'date'
  placeholder?: string
}
type FieldConfig = NumberFieldConfig | DateFieldConfig
type ConditionalFieldConfig = FieldConfig & { visible?: boolean }

type SectionConfig = {
  key: string
  title: string
  visible: boolean
  fields: FieldConfig[]
}

const enabledRuleCount = computed(
  () => [timeEnable.value, mileageEnable.value, naturalDateEnable.value].filter(Boolean).length
)

const enabledFields = (fields: ConditionalFieldConfig[]): FieldConfig[] =>
  fields.filter(({ visible = true }) => visible)

const ruleSections = computed<SectionConfig[]>(() => [
  {
    key: 'basic',
    title: t('mainPlan.basicMaintenanceRecords'),
    visible: enabledRuleCount.value > 0,
    fields: enabledFields([
      {
        label: t('mainPlan.lastMaintenanceOperationTime'),
        prop: 'lastRunningTime',
        type: 'number',
        precision: 1,
        visible: timeEnable.value
      },
      {
        label: t('mainPlan.lastMaintenanceMileage'),
        prop: 'lastRunningKilometers',
        type: 'number',
        precision: 2,
        visible: mileageEnable.value
      },
      {
        label: t('mainPlan.lastMaintenanceNaturalDate'),
        prop: 'lastNaturalDate',
        type: 'date',
        placeholder: '选择日期',
        visible: naturalDateEnable.value
      }
    ])
  },
  {
    key: 'time',
    title: t('mainPlan.RunTimeRuleConfiguration'),
    visible: timeEnable.value,
    fields: [
      {
        label: t('mainPlan.RunTimeCycle'),
        prop: 'nextRunningTime',
        type: 'number',
        precision: 1
      },
      {
        label: t('mainPlan.RunTimeCycle_Lead'),
        prop: 'timePeriodLead',
        type: 'number',
        precision: 1
      }
    ]
  },
  {
    key: 'mileage',
    title: t('mainPlan.operatingMileageRuleConfiguration'),
    visible: mileageEnable.value,
    fields: [
      {
        label: t('mainPlan.operatingMileageCycle'),
        prop: 'nextRunningKilometers',
        type: 'number',
        precision: 2
      },
      {
        label: t('mainPlan.OperatingMileageCycle_lead'),
        prop: 'kiloCycleLead',
        type: 'number',
        precision: 2
      }
    ]
  },
  {
    key: 'natural-date',
    title: t('mainPlan.NaturalDayRuleConfig'),
    visible: naturalDateEnable.value,
    fields: [
      {
        label: t('mainPlan.NaturalDailyCycle'),
        prop: 'nextNaturalDate',
        type: 'number'
      },
      {
        label: t('mainPlan.NaturalDailyCycle_Lead'),
        prop: 'naturalDatePeriodLead',
        type: 'number'
      }
    ]
  }
])

const cloneRow = (row: List): List => ({
  ...row
})

const isPositiveRequiredValue = (value: unknown) => typeof value === 'number' && value > 0

const positiveNumberRule = (label: string) => ({
  required: true,
  validator: (_rule: unknown, value: unknown, callback: (error?: Error) => void) => {
    if (isPositiveRequiredValue(value)) {
      callback()
      return
    }

    callback(new Error(`请填写${label}`))
  },
  trigger: ['blur', 'change']
})

const requiredRule = (message: string) => ({
  required: true,
  message,
  trigger: ['blur', 'change']
})

const formRules = computed<FormRules>(() => {
  const rules: FormRules = {}

  for (const section of ruleSections.value) {
    if (!section.visible) continue

    for (const field of section.fields) {
      rules[field.prop] =
        field.type === 'number'
          ? [positiveNumberRule(field.label)]
          : [requiredRule(`请选择${field.label}`)]
    }
  }

  if (timeAccumulatedVisible.value) {
    rules.code = [requiredRule('请选择累计运行时长')]
  }

  if (mileageAccumulatedVisible.value) {
    rules.type = [requiredRule('请选择累计运行公里数')]
  }

  return rules
})

const emit = defineEmits<{
  saved: []
}>()

const close = () => {
  visible.value = false
}

const save = async () => {
  if (isReadonly.value) {
    close()
    return
  }

  if (!sourceRow.value) return
  if (!formRef.value) return

  try {
    await formRef.value.validate()
  } catch {
    return
  }

  const data = cloneRow(form.value)

  if (timeAccumulatedVisible.value) {
    const selectedTimeAttr = timeAccumulatedAttrs.value.find((item) => item.pointName === data.code)
    data.tempTotalRunTime = selectedTimeAttr?.totalRunTime ?? null
  }

  if (mileageAccumulatedVisible.value) {
    const selectedMileageAttr = mileageAccumulatedAttrs.value.find(
      (item) => item.pointName === data.type
    )
    data.tempTotalMileage = selectedMileageAttr?.totalRunTime ?? null
  }

  Object.assign(sourceRow.value, data)
  emit('saved')
  close()
}

const open = ({
  row,
  readonly,
  timeAccumulatedAttrs: timeAttrs,
  mileageAccumulatedAttrs: mileageAttrs
}: Props) => {
  sourceRow.value = row
  form.value = cloneRow(row)
  isReadonly.value = readonly
  timeAccumulatedAttrs.value = timeAttrs || []
  mileageAccumulatedAttrs.value = mileageAttrs || []
  visible.value = true
  nextTick(() => {
    formRef.value?.clearValidate()
  })
}

defineExpose({
  open
})
</script>

<template>
  <Dialog v-model="visible" title="保养项配置" width="720px" :close-on-click-modal="false">
    <el-form
      ref="formRef"
      size="default"
      :model="form"
      :rules="formRules"
      label-position="top"
      class="maintenance-config-form">
      <div class="config-summary">
        <div class="summary-item">
          <span class="summary-label">{{ t('iotMaintain.deviceCode') }}</span>
          <span class="summary-value">{{ form.deviceCode || '-' }}</span>
        </div>
        <div class="summary-item">
          <span class="summary-label">{{ t('iotMaintain.deviceName') }}</span>
          <span class="summary-value">{{ form.deviceName || '-' }}</span>
        </div>
        <div class="summary-item summary-item-full">
          <span class="summary-label">{{ t('bomList.bomNode') }}</span>
          <span class="summary-value">{{ form.name || '-' }}</span>
        </div>
      </div>

      <el-empty v-if="enabledRuleCount === 0" :image-size="88" description="当前保养项未启用规则" />

      <section
        v-for="section in ruleSections"
        v-show="section.visible"
        :key="section.key"
        class="config-section">
        <div class="section-header">
          <div class="section-title">{{ section.title }}</div>
        </div>
        <el-row :gutter="16">
          <el-col v-for="field in section.fields" :key="field.prop" :xs="24" :sm="12">
            <el-form-item :label="field.label" :prop="field.prop">
              <el-input-number
                v-if="field.type === 'number'"
                v-model="form[field.prop]"
                :precision="field.precision"
                :min="0"
                :controls="false"
                :disabled="isReadonly"
                class="w-full!" />
              <el-date-picker
                v-else
                v-model="form[field.prop]"
                type="date"
                :placeholder="field.placeholder"
                value-format="x"
                :disabled="isReadonly"
                class="w-full!" />
            </el-form-item>
          </el-col>
        </el-row>
      </section>
      <section v-if="accumulatedVisible" class="config-section">
        <div class="section-header">
          <div class="section-title">{{ t('mainPlan.accumulatedParams') }}</div>
        </div>
        <el-row :gutter="16">
          <el-col v-if="timeAccumulatedVisible" :xs="24" :sm="12">
            <el-form-item :label="t('mainPlan.accumulatedRunTime')" prop="code">
              <el-select
                v-model="form.code"
                placeholder="请选择累计运行时长"
                clearable
                :disabled="isReadonly"
                class="w-full!">
                <el-option
                  v-for="(item, index) in timeAccumulatedAttrs"
                  :key="`time-${item.pointName}-${index}`"
                  :label="item.pointName"
                  :value="item.pointName" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col v-if="mileageAccumulatedVisible" :xs="24" :sm="12">
            <el-form-item :label="t('mainPlan.accumulatedMileage')" prop="type">
              <el-select
                v-model="form.type"
                placeholder="请选择累计运行公里数"
                clearable
                :disabled="isReadonly"
                class="w-full!">
                <el-option
                  v-for="(item, index) in mileageAccumulatedAttrs"
                  :key="`mileage-${item.pointName}-${index}`"
                  :label="item.pointName"
                  :value="item.pointName" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
      </section>
    </el-form>
    <template #footer>
      <el-button @click="close">{{ t('common.cancel') }}</el-button>
      <el-button v-if="!isReadonly" type="primary" @click="save">{{ t('common.save') }}</el-button>
    </template>
  </Dialog>
</template>

<style scoped lang="scss">
.maintenance-config-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.config-summary {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 14px;
  padding: 12px 14px;
  background: var(--el-fill-color-light);
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 8px;
}

.summary-item {
  min-width: 0;
}

.summary-item-full {
  grid-column: 1 / -1;
}

.summary-label {
  display: block;
  margin-bottom: 4px;
  font-size: 12px;
  line-height: 1.2;
  color: var(--el-text-color-secondary);
}

.summary-value {
  display: block;
  overflow: hidden;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--el-text-color-primary);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.config-section {
  padding: 14px 14px 2px;
  background: var(--el-bg-color);
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 8px;
}

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.section-title {
  position: relative;
  padding-left: 10px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--el-text-color-primary);
}

.section-title::before {
  position: absolute;
  top: 3px;
  bottom: 3px;
  left: 0;
  width: 3px;
  background: var(--el-color-primary);
  border-radius: 3px;
  content: '';
}

.form-control {
  width: 100% !important;
}

.maintenance-config-form :deep(.el-form-item) {
  margin-bottom: 14px;
}

.maintenance-config-form :deep(.el-form-item__label) {
  margin-bottom: 6px;
  font-size: 13px;
  line-height: 1.4;
  color: var(--el-text-color-regular);
}

.maintenance-config-form :deep(.el-input__wrapper) {
  border-radius: 6px;
  box-shadow: 0 0 0 1px var(--el-border-color-light) inset;
}

.maintenance-config-form :deep(.el-input__wrapper:hover) {
  box-shadow: 0 0 0 1px var(--el-border-color) inset;
}

.maintenance-config-form :deep(.el-input.is-disabled .el-input__wrapper) {
  background-color: var(--el-fill-color-lighter);
}

@media (width <= 640px) {
  .config-summary {
    grid-template-columns: 1fr;
  }
}
</style>
