<template>
  <div class="cameraTreeWrapper">
    <div class="cameraTreeInputWrapper">
      <el-input
        v-model="filterText"
        placeholder="请输入传感器名称进行搜索"
        :suffix-icon="Search"
        class="filterTextInput"
      />
    </div>
    <el-scrollbar class="tree-scroll">
      <el-tree
        :data="cameraTree"
        :props="defaultProps"
        show-checkbox
        node-key="code"
        :default-expand-all="true"
        :filter-node-method="filterNode"
        ref="treeRef"
        v-loading="treeLoading"
        :empty-text="treeEmptyText"
        element-loading-background="rgba(0, 0, 0, 0)"
      >
        <template #default="{ node, data }">
          <div class="treeNode">
            <div class="icons">
              <VideoCamera class="cameraIcon" />
              <WarningFilled v-if="isInvalid(data)" class="invalidCamera" style="color: red" />
            </div>
            <div class="cameraName">{{ node.label }}</div>
          </div>
        </template>
      </el-tree>
    </el-scrollbar>
    <div class="dialogFooter">
      <el-button @click="emit('close')">取消</el-button>
      <el-button type="primary" :loading="saving" @click="handleConfirm">确认</el-button>
    </div>
  </div>
</template>
<script setup lang="ts">
  import { ElInput, ElTree, ElScrollbar, ElButton, ElMessage } from 'element-plus';
  import { computed, nextTick, ref, watch } from 'vue';
  import { storeToRefs } from 'pinia';
  import { VideoCamera, WarningFilled, Search } from '@element-plus/icons-vue';
  import { useCameraGroupList } from '@/store/modules/useCameraGroupList';
  import {
    batchSaveSensor2GroupApi,
    deleteSensorFromGroupApi,
    queryDeviceListApi,
    querySensorGroupListApi,
    saveSensor2GroupApi,
    updateSensorGroupApi,
  } from '@/api/sensor-group';
  import type {
    DeviceListItem,
    ProductionSensorGroup,
    SensorGroupView,
    SensorDeviceViewItem,
  } from '@/api/sensor-group/type';
  import { userGridType } from '@/store/modules/userGridType';
  import { GridType } from '../../type';

  enum CameraTreeNodeType {
    group = 'group',
    camera = 'camera',
  }

  interface TreeNode {
    [key: string]: any;
  }

  const defaultProps = {
    children: 'children',
    label: 'name',
  };

  const cameraTree = ref<any[]>([]);
  const filterText = ref('');
  const treeRef = ref<InstanceType<typeof ElTree>>();
  const childrenNodeList = ref<string[]>([]);
  const deviceList = ref<DeviceListItem[]>([]);
  const treeLoading = ref(false);
  const treeEmptyText = ref('');
  const saving = ref(false);
  const props = defineProps<{ cameraGroup: SensorGroupView }>();
  const emit = defineEmits<{ (e: 'close'): void }>();

  const groupSensors = computed(() => props.cameraGroup.details);
  // 已在分组中的设备 code（deviceNo），用于初始勾选
  const initialCheckedKeys = computed(() => groupSensors.value.map((s) => s.code));

  const { cameraInPlay, cameraGroupList, isPlaying, isPaused, playIntervalTime } = storeToRefs(useCameraGroupList());
  const { restartPlay, setPlayGroup, groupStartPlay } = useCameraGroupList();
  const { changeGridType } = userGridType();

  function syncGroupSensors(newSensors: SensorDeviceViewItem[]) {
    const targetGroup = cameraGroupList.value.find((x: any) => x.id === props.cameraGroup.id) as
      | SensorGroupView
      | undefined;
    if (!targetGroup) return;
    targetGroup.details = newSensors;
  }

  function normalizeSensorGroups(list: ProductionSensorGroup[]): SensorGroupView[] {
    return (list || []).map((group) => {
      const details: SensorDeviceViewItem[] = (group.details || []).map((detail) => ({
        id: detail.sensorId,
        code: detail.deviceNo,
        name: detail.deviceName,
        status: detail.status,
      }));

      return {
        ...group,
        isPaused: group.isPaused ?? 1,
        details,
        children: details,
      } as any;
    });
  }

  async function loadDeviceList(deviceName = '') {
    treeLoading.value = true;
    try {
      const res = await queryDeviceListApi({
        pageNumber: 1,
        pageSize: 99999,
        queryParam: { deviceName },
      });
      deviceList.value = Array.isArray(res) ? res : res.records || [];
      treeEmptyText.value = deviceList.value.length === 0 ? '暂无数据' : '';
    } finally {
      treeLoading.value = false;
    }
  }

  async function handleConfirm() {
    saving.value = true;
    try {
      const checkedNodes = (treeRef.value?.getCheckedNodes() as any[]) || [];
      const checkedDeviceNoList = checkedNodes.map((n) => n.code as string);
      const initialDeviceNoList = initialCheckedKeys.value;
      const addedDeviceNoList = checkedDeviceNoList.filter((deviceNo) => !initialDeviceNoList.includes(deviceNo));
      const removedDeviceNoList = initialDeviceNoList.filter((deviceNo) => !checkedDeviceNoList.includes(deviceNo));

      if (removedDeviceNoList.length > 0) {
        await Promise.all(
          removedDeviceNoList.map((deviceNo) => deleteSensorFromGroupApi({ groupId: props.cameraGroup.id, deviceNo })),
        );
      }

      if (addedDeviceNoList.length === 1) {
        const addedDevice = deviceList.value.find((item) => item.deviceNo === addedDeviceNoList[0]);
        await saveSensor2GroupApi({
          groupId: props.cameraGroup.id,
          deviceNo: addedDeviceNoList[0],
          orderNum: props.cameraGroup.details.length + 1,
          deviceName: addedDevice?.deviceName || '',
          status: addedDevice?.deviceStatus || '',
        });
      } else if (addedDeviceNoList.length > 1) {
        await batchSaveSensor2GroupApi({
          groupId: props.cameraGroup.id,
          deviceList: addedDeviceNoList.map((deviceNo) => {
            const device = deviceList.value.find((item) => item.deviceNo === deviceNo);
            return {
              deviceNo,
              deviceName: device?.deviceName || '',
              status: device?.deviceStatus || '',
            };
          }),
        });
      }

      // 更新本地状态
      const newSensors: SensorDeviceViewItem[] = checkedNodes.map((n) => {
        const device = deviceList.value.find((item) => item.deviceNo === n.code);
        return {
          id: n.id,
          code: n.code,
          name: device?.deviceName || n.name,
          status: device?.deviceStatus || '',
        };
      });

      syncGroupSensors(newSensors);

      // 与初始化逻辑一致：保存后刷新分组列表并重置右侧播放数据
      const latestGroupList = await querySensorGroupListApi();
      cameraGroupList.value = normalizeSensorGroups(latestGroupList) as any;

      const defaultGroup = cameraGroupList.value.find((x) => x.isDefault === 1) as unknown as SensorGroupView;
      if (defaultGroup) {
        await updateSensorGroupApi({
          groupId: defaultGroup.id,
          isDefault: 1,
        });

        isPlaying.value = true;
        setPlayGroup({ ...(defaultGroup as any), children: defaultGroup.details } as any);
        playIntervalTime.value = defaultGroup.refreshIntervalSec || 60;
        isPaused.value = !defaultGroup.isPaused;
        changeGridType(GridType.nineGrids);
        groupStartPlay(playIntervalTime.value);
      }

      // 移除已不在分组中的正在播放的传感器
      cameraInPlay.value = cameraInPlay.value.map((x) => {
        const stillExists = newSensors.find((s) => s.id === x.id);
        return stillExists ? x : { ...x, id: -Date.now(), name: '', code: '' };
      });

      restartPlay();
      ElMessage({ message: '保存成功', type: 'success' });
      emit('close');
    } catch {
      ElMessage({ message: '保存失败', type: 'error' });
    } finally {
      saving.value = false;
    }
  }

  const treeSource = computed(() => {
    return deviceList.value.map((device) => ({
      id: device.id,
      code: device.deviceNo || String(device.id),
      name: device.deviceName || device.deviceNo || `设备${String(device.id).slice(-3)}`,
      nodeType: CameraTreeNodeType.camera,
      networkingState: device.deviceStatus === 'offline' ? 1 : 0,
      disable: device.deviceStatus === 'offline',
      pushStreamDTO: { videoUrls: { pushstreamIp: '' } },
    }));
  });

  watch(filterText, async (val) => {
    await loadDeviceList(val);
    childrenNodeList.value = [];
    treeRef.value?.filter(val);
  });

  function extractCodes(data: any[], codes: string[] = []) {
    data.forEach((item) => {
      codes.push(item.data.code);
      if (item.childNodes) {
        extractCodes(item.childNodes, codes);
      }
    });
    return codes;
  }

  const filterNode = (value: string, data: TreeNode, node) => {
    if (!value) return true;
    const labelMatch = data.name.includes(value);
    if (labelMatch) {
      if (node.childNodes && node.childNodes.length > 0) {
        childrenNodeList.value = extractCodes(node.childNodes, []);
      }
    }
    if (childrenNodeList.value.includes(data.code)) {
      return true;
    }
    return labelMatch;
  };

  const isInvalid = (data) => {
    if (data.networkingState !== 0) data.disable = true;
    return data.networkingState !== 0;
  };

  // 树数据加载完成后，回填已勾选项
  watch(
    cameraTree,
    () => {
      nextTick(() => {
        treeRef.value?.setCheckedKeys(initialCheckedKeys.value);
      });
    },
    { deep: true },
  );

  watch(
    treeSource,
    (value) => {
      cameraTree.value = value;
      treeEmptyText.value = deviceList.value.length === 0 ? '暂无数据' : '';
    },
    { immediate: true, deep: true },
  );

  loadDeviceList();
</script>
<style lang="scss" scoped>
  .cameraTreeWrapper {
    .cameraTreeInputWrapper {
      padding: 8px;
      .filterTextInput {
        margin: 8px 0;
      }
    }

    .tree-scroll {
      height: 400px;
      .selectedCamera {
        color: #1777ff !important;
      }
      .treeNode {
        display: flex;
        align-items: center;
        color: black;
        // position: relative;
        .icons {
          display: flex;
          align-items: center;
          position: relative;
          .cameraIcon {
            height: 18px;
            margin-right: 8px;
            color: black;
          }
          .invalidCamera {
            height: 14px;
            color: #dd5869;
            position: absolute;
            right: 0px;
            top: -5px;
          }
        }
      }
    }
  }

  :deep(.thumb-nail) {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 99;
  }

  :deep(.el-tree-node__content) {
    position: relative;
  }

  .dialogFooter {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 12px 8px 4px;
    border-top: 1px solid #f0f0f0;
    margin-top: 8px;
  }
</style>
