<template>
  <div class="allot-config-page">
    <div class="selection-grid">
      <section class="panel">
        <div class="panel-header">
          <div class="panel-title">
            <span class="panel-marker"></span>
            <span>{{ t('configPerson.deviceList') }}</span>
          </div>
          <el-tag size="small" type="info">{{ filteredDevices.length }} 台</el-tag>
        </div>

        <div class="panel-toolbar">
          <el-tree-select
            v-model="formData.sourceDeptId"
            :data="deptList"
            :props="defaultProps"
            check-strictly
            node-key="id"
            filterable
            clearable
            size="default"
            class="toolbar-control"
            :placeholder="t('configPerson.deviceListHolder')"
            @node-click="handleSourceDeptClick"
            @clear="handleClearSourceDept" />
          <el-input
            v-model="deviceFilterText"
            :placeholder="t('devicePerson.filterDevicePlaceholder')"
            :disabled="!devicesLoaded"
            clearable
            size="default"
            class="toolbar-control">
            <template #prefix>
              <Icon icon="ep:search" />
            </template>
          </el-input>
        </div>

        <el-scrollbar class="option-scroll">
          <el-checkbox-group v-model="selectedDevices" class="option-list">
            <el-checkbox
              v-for="device in filteredDevices"
              :key="device.id"
              :value="device.id"
              class="option-item"
              :class="{ 'is-selected': selectedDevices.includes(device.id) }">
              <span class="option-content">
                <span class="option-main">{{ device.deviceCode || '暂无编码' }}</span>
                <span class="option-sub">{{ device.deviceName || '暂无名称' }}</span>
                <span class="option-extra">当前部门：{{ device.deptName || '暂无' }}</span>
              </span>
            </el-checkbox>
          </el-checkbox-group>
          <el-empty
            v-if="devicesLoaded && filteredDevices.length === 0"
            :image-size="92"
            description="暂无设备" />
        </el-scrollbar>
      </section>

      <section class="panel">
        <div class="panel-header">
          <div class="panel-title">
            <span class="panel-marker"></span>
            <span>{{ t('configDevice.deptList') }}</span>
          </div>
          <el-tag size="small" type="info">{{ selectedDevices.length }} 台已选</el-tag>
        </div>

        <el-form class="target-form" label-position="top" size="default">
          <el-form-item>
            <template #label>
              <span>调拨部门</span>
              <span class="required-star">*</span>
            </template>
            <el-tree-select
              v-model="formData.targetDeptId"
              :data="deptList"
              :props="defaultProps"
              check-strictly
              node-key="id"
              filterable
              clearable
              class="toolbar-control"
              :disabled="selectedDevices.length === 0"
              :placeholder="t('configPerson.deviceListHolder')"
              @change="handleTargetDeptChange"
              @clear="handleClearTargetDept" />
          </el-form-item>

          <el-form-item>
            <template #label>
              <span>{{ t('devicePerson.rp') }}</span>
              <span class="required-star">*</span>
            </template>
            <el-select
              v-model="selectedPersons"
              multiple
              filterable
              clearable
              collapse-tags
              collapse-tags-tooltip
              :max-collapse-tags="6"
              popper-class="allot-person-tags-popper"
              class="toolbar-control person-select"
              :loading="personLoading"
              :disabled="!formData.targetDeptId"
              :placeholder="t('configPerson.selectPersons')"
              @change="syncRelations">
              <el-option
                v-for="person in simpleUsers"
                :key="person.id"
                :label="person.nickname || person.username"
                :value="person.id" />
            </el-select>
          </el-form-item>

          <div class="target-tip">
            选择目标部门后会加载该部门人员，调拨记录会按设备逐条生成预览。
          </div>
        </el-form>
      </section>
    </div>

    <section class="panel reason-panel">
      <div class="panel-header">
        <div class="panel-title">
          <span class="panel-marker"></span>
          <span>{{ t('configDevice.reasonForAdjustment') }}</span>
          <span class="required-star">*</span>
        </div>
      </div>
      <el-input
        v-model="formData.reason"
        :placeholder="t('configDevice.rfaHolder')"
        type="textarea"
        :rows="4"
        resize="none"
        size="default"
        :disabled="selectedDevices.length === 0 || !formData.targetDeptId"
        @input="syncRelations" />
    </section>

    <section class="panel record-panel">
      <div class="panel-header">
        <div class="panel-title">
          <span class="panel-marker"></span>
          <span>{{ t('configPerson.adjustmentRecords') }}</span>
        </div>
        <el-button
          type="primary"
          size="default"
          :disabled="isSaveDisabled"
          @click="submitRelations">
          <Icon icon="ep:check" class="mr-5px" />
          {{ t('iotMaintain.save') }}
        </el-button>
      </div>

      <ZmTable
        :data="tempRelations"
        :loading="false"
        :show-border="true"
        settings-cache-key="pms-device-allot-config-record"
        class="record-table">
        <ZmTableColumn prop="deviceNames" :label="t('deviceStatus.deviceName')" min-width="240" />
        <ZmTableColumn prop="oldDeptName" label="原部门" min-width="160" />
        <ZmTableColumn prop="deptName" label="调拨部门" min-width="160" />
        <ZmTableColumn prop="personNames" :label="t('devicePerson.rp')" min-width="220">
          <template #default="{ row }">
            <span>{{ row.personNames || '未选择责任人' }}</span>
          </template>
        </ZmTableColumn>
        <ZmTableColumn
          prop="reason"
          :label="t('configDevice.reasonForAdjustment')"
          min-width="280"
          align="left">
          <template #default="{ row }">
            <span>{{ row.reason || '未填写调拨原因' }}</span>
          </template>
        </ZmTableColumn>
        <ZmTableColumn :label="t('deviceStatus.operation')" width="120" fixed="right" action>
          <template #default="{ row }">
            <el-button type="danger" link size="default" @click="removeTempRelation(row.deviceId)">
              <Icon icon="ep:delete" class="mr-4px" />
              {{ t('fault.del') }}
            </el-button>
          </template>
        </ZmTableColumn>
      </ZmTable>
    </section>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref, unref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { useTableComponents } from '@/components/ZmTable/useTableComponents'
import * as DeptApi from '@/api/system/dept'
import * as UserApi from '@/api/system/user'
import type { UserVO } from '@/api/system/user'
import { IotDeviceApi, type IotDeviceVO } from '@/api/pms/device'
import { useTagsViewStore } from '@/store/modules/tagsView'
import { defaultProps, handleTree } from '@/utils/tree'

defineOptions({ name: 'ConfigDeviceAllot' })

type TempRelation = {
  deviceId: number
  deviceNames: string
  oldDeptId?: number
  oldDeptName: string
  deptId: number
  deptName: string
  personIds: number[]
  personNames: string
  reason: string
}

type ConfigFormData = {
  sourceDeptId?: number
  targetDeptId?: number
  reason: string
}

const router = useRouter()
const route = useRoute()
const { t } = useI18n()
const { delView } = useTagsViewStore()
const { ZmTable, ZmTableColumn } = useTableComponents<TempRelation>()

const deptList = ref<Tree[]>([])
const simpleDevices = ref<IotDeviceVO[]>([])
const simpleUsers = ref<UserVO[]>([])
const selectedDevices = ref<number[]>([])
const selectedPersons = ref<number[]>([])
const tempRelations = ref<TempRelation[]>([])
const deviceFilterText = ref('')
const devicesLoaded = ref(false)
const personLoading = ref(false)

const formData = reactive<ConfigFormData>({
  sourceDeptId: undefined,
  targetDeptId: undefined,
  reason: ''
})

const filteredDevices = computed(() => {
  const searchText = deviceFilterText.value.toLowerCase().trim()
  if (!searchText) return simpleDevices.value

  return simpleDevices.value.filter((device) => {
    return (
      (device.deviceCode || '').toLowerCase().includes(searchText) ||
      (device.deviceName || '').toLowerCase().includes(searchText) ||
      (device.deptName || '').toLowerCase().includes(searchText)
    )
  })
})

const selectedPersonObjects = computed(() => {
  return simpleUsers.value.filter((person) => selectedPersons.value.includes(person.id))
})

const selectedPersonNames = computed(() => {
  return selectedPersonObjects.value
    .map((person) => person.nickname || person.username)
    .filter(Boolean)
    .join('、')
})

const targetDeptName = computed(() => {
  if (!formData.targetDeptId) return ''
  return findDeptNode(deptList.value, formData.targetDeptId)?.name || '未知部门'
})

const isSaveDisabled = computed(() => {
  return (
    tempRelations.value.length === 0 ||
    !formData.targetDeptId ||
    !selectedPersons.value.length ||
    tempRelations.value.some((item) => !item.reason?.trim() || !item.personIds.length)
  )
})

watch(
  selectedDevices,
  (newVal, oldVal) => {
    const removedDeviceIds = oldVal.filter((id) => !newVal.includes(id))
    tempRelations.value = tempRelations.value.filter(
      (relation) => !removedDeviceIds.includes(relation.deviceId)
    )

    if (!newVal.length) {
      selectedPersons.value = []
      simpleUsers.value = []
      formData.targetDeptId = undefined
      formData.reason = ''
      tempRelations.value = []
      return
    }

    if (formData.targetDeptId && hasSameTargetDept()) {
      ElMessage.warning('不能选择设备原属部门作为调拨部门')
      formData.targetDeptId = undefined
      selectedPersons.value = []
      simpleUsers.value = []
    }

    syncRelations()
  },
  { deep: true }
)

const getDeviceLabel = (device: IotDeviceVO) => {
  return `${device.deviceCode || '暂无编码'}（${device.deviceName || '暂无名称'}）`
}

const hasSameTargetDept = () => {
  return selectedDevices.value.some((deviceId) => {
    const device = simpleDevices.value.find((item) => item.id === deviceId)
    return device?.deptId === formData.targetDeptId
  })
}

const syncRelations = () => {
  if (!formData.targetDeptId) {
    tempRelations.value = []
    return
  }

  const selectedDeviceSet = new Set(selectedDevices.value)
  const personIds = [...selectedPersons.value]
  const personNames = selectedPersonNames.value
  tempRelations.value = simpleDevices.value
    .filter((device) => selectedDeviceSet.has(device.id))
    .map((device) => ({
      deviceId: device.id,
      deviceNames: getDeviceLabel(device),
      oldDeptId: device.deptId,
      oldDeptName: device.deptName || '暂无',
      deptId: formData.targetDeptId!,
      deptName: targetDeptName.value,
      personIds,
      personNames,
      reason: formData.reason
    }))
}

const getDeviceList = async () => {
  devicesLoaded.value = false
  try {
    const data = await IotDeviceApi.simpleDevices({ deptId: formData.sourceDeptId })
    simpleDevices.value = data || []
    selectedDevices.value = selectedDevices.value.filter((id) =>
      simpleDevices.value.some((device) => device.id === id)
    )
    syncRelations()
  } catch (error) {
    simpleDevices.value = []
    ElMessage.error('获取设备列表失败')
  } finally {
    devicesLoaded.value = true
  }
}

const getUserList = async () => {
  if (!formData.targetDeptId) {
    simpleUsers.value = []
    selectedPersons.value = []
    syncRelations()
    return
  }

  personLoading.value = true
  try {
    const data = await UserApi.simpleUserList({
      deptId: formData.targetDeptId,
      pageNo: 1,
      pageSize: 100
    })
    simpleUsers.value = data || []
    selectedPersons.value = selectedPersons.value.filter((id) =>
      simpleUsers.value.some((person) => person.id === id)
    )
    syncRelations()
  } catch (error) {
    simpleUsers.value = []
    selectedPersons.value = []
    ElMessage.error('获取责任人列表失败')
  } finally {
    personLoading.value = false
  }
}

const handleSourceDeptClick = async (row: Tree) => {
  formData.sourceDeptId = row.id
  selectedDevices.value = []
  selectedPersons.value = []
  simpleUsers.value = []
  formData.targetDeptId = undefined
  deviceFilterText.value = ''
  await getDeviceList()
}

const handleClearSourceDept = () => {
  simpleDevices.value = []
  selectedDevices.value = []
  selectedPersons.value = []
  tempRelations.value = []
  deviceFilterText.value = ''
  devicesLoaded.value = false
}

const handleTargetDeptChange = async () => {
  if (formData.targetDeptId && hasSameTargetDept()) {
    ElMessage.error('不能选择设备原属部门作为调拨部门')
    formData.targetDeptId = undefined
    selectedPersons.value = []
    simpleUsers.value = []
    syncRelations()
    return
  }

  selectedPersons.value = []
  await getUserList()
}

const handleClearTargetDept = () => {
  formData.targetDeptId = undefined
  selectedPersons.value = []
  simpleUsers.value = []
  syncRelations()
}

const removeTempRelation = (deviceId: number) => {
  selectedDevices.value = selectedDevices.value.filter((id) => id !== deviceId)
  tempRelations.value = tempRelations.value.filter((relation) => relation.deviceId !== deviceId)
}

const submitRelations = async () => {
  if (!selectedDevices.value.length) {
    ElMessage.error(t('iotMaintain.deviceHolder'))
    return
  }

  if (!formData.targetDeptId) {
    ElMessage.error('请选择调拨部门')
    return
  }

  if (!selectedPersons.value.length) {
    ElMessage.error(t('configPerson.selectPersons'))
    return
  }

  if (hasSameTargetDept()) {
    ElMessage.error('存在调拨部门与设备原属部门相同的情况，请检查')
    return
  }

  if (tempRelations.value.some((item) => !item.reason?.trim())) {
    ElMessage.error(t('configDevice.rfaHolder'))
    return
  }

  try {
    const submitData = tempRelations.value.map((relation) => ({
      deviceId: relation.deviceId,
      deptId: relation.deptId,
      reason: relation.reason,
      personIds: relation.personIds,
      personNames: relation.personNames ? relation.personNames.split('、') : []
    }))

    await IotDeviceApi.saveDeviceAllot(submitData)
    ElMessage.success('提交成功')
    tempRelations.value = []
    delView(unref(router.currentRoute.value))
    router.back()
  } catch (error) {
    ElMessage.error('提交失败，请重试')
  }
}

const findDeptNode = (nodes: Tree[], deptId: number): Tree | null => {
  for (const node of nodes) {
    if (node.id === deptId) return node

    if (node.children?.length) {
      const found = findDeptNode(node.children, deptId)
      if (found) return found
    }
  }

  return null
}

onMounted(async () => {
  try {
    const deptData = await DeptApi.getSimpleDeptList()
    deptList.value = handleTree(deptData)

    const routeDeptId = route.query.deptId ? Number(route.query.deptId) : undefined
    const targetDeptId = routeDeptId || deptList.value[0]?.id

    if (!targetDeptId) {
      ElMessage.warning('暂无可用部门数据')
      return
    }

    formData.sourceDeptId = targetDeptId
    const targetDeptNode = findDeptNode(deptList.value, targetDeptId)
    if (targetDeptNode) {
      await handleSourceDeptClick(targetDeptNode)
    } else {
      await getDeviceList()
    }
  } catch (error) {
    ElMessage.error('加载部门数据失败')
  }
})
</script>

<style lang="scss" scoped>
.allot-config-page {
  min-height: calc(
    100vh - 20px - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height)
  );
  background: #f5f7fb;
}

.selection-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}

.panel {
  overflow: hidden;
  background: var(--el-bg-color);
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgb(15 35 70 / 5%);
}

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 56px;
  padding: 0 18px;
  background: #f4f9ff;
  border-bottom: 1px solid var(--el-border-color-lighter);
}

.panel-title {
  display: flex;
  align-items: center;
  font-size: 16px;
  font-weight: 600;
  color: var(--el-text-color-primary);
}

.panel-marker {
  width: 4px;
  height: 18px;
  margin-right: 10px;
  background: var(--el-color-primary);
  border-radius: 4px;
}

.panel-toolbar {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  padding: 16px 18px 0;
}

.toolbar-control {
  width: 100%;
}

.target-form {
  padding: 18px;
}

.target-tip {
  padding: 10px 12px;
  font-size: 12px;
  line-height: 18px;
  color: var(--el-text-color-secondary);
  background: #f8fbff;
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 6px;
}

.person-select :deep(.el-select__tags) {
  flex-wrap: nowrap;
  max-width: calc(100% - 48px);
  overflow: hidden;
}

.person-select :deep(.el-tag) {
  flex-shrink: 0;
  max-width: 92px;
}

.person-select :deep(.el-tag__content) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

:global(.allot-person-tags-popper .el-select__selection) {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  max-width: 520px;
  max-height: 220px;
  overflow-y: auto;
}

:global(.allot-person-tags-popper .el-select__selected-item) {
  max-width: 120px;
}

:global(.allot-person-tags-popper .el-tag__content),
:global(.allot-person-tags-popper .el-select__tags-text) {
  display: inline-block;
  max-width: 92px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}

.option-scroll {
  height: 430px;
  padding: 14px 18px 18px;
}

.option-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.option-item {
  display: flex;
  height: auto;
  min-width: 0;
  padding: 12px;
  cursor: pointer;
  background: var(--el-fill-color-blank);
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 6px;
  transition:
    border-color 0.2s,
    background-color 0.2s,
    box-shadow 0.2s;
  align-items: flex-start;

  &:hover,
  &.is-selected {
    background: #f7fbff;
    border-color: var(--el-color-primary-light-5);
    box-shadow: 0 6px 18px rgb(64 158 255 / 10%);
  }

  :deep(.el-checkbox__input) {
    margin-top: 2px;
  }

  :deep(.el-checkbox__label) {
    flex: 1;
    min-width: 0;
    padding-left: 10px;
  }
}

.option-content {
  display: grid;
  width: 100%;
  min-width: 0;
  align-items: center;
  grid-template-columns: minmax(90px, 0.7fr) minmax(120px, 1fr) minmax(150px, 1.2fr);
  gap: 12px;
}

.option-main,
.option-sub,
.option-extra {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.option-main {
  font-size: 14px;
  font-weight: 600;
  color: var(--el-text-color-primary);
}

.option-sub,
.option-extra {
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.reason-panel,
.record-panel {
  margin-top: 16px;
}

.reason-panel {
  padding-bottom: 18px;

  :deep(.el-textarea) {
    padding: 18px 18px 0;
  }
}

.record-panel {
  padding-bottom: 18px;
}

.record-table {
  width: calc(100% - 36px);
  margin: 18px;
}

.required-star {
  margin-left: 4px;
  color: var(--el-color-danger);
}

@media (width <= 1180px) {
  .selection-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
</style>
