<script setup lang="ts">
import { onMounted, ref, useTemplateRef } from 'vue';
import { useRouter } from 'vue-router';
import { useInfiniteScroll } from '@vueuse/core';

import SvgIcon from '@/components/SvgIcon.vue';
import { useRequest } from '@/hooks/request';
import { getDevWorkRealTimeData, getDevWorkTypeCount, queryDevicesList } from '@/api';
import { DeviceRunningStatus, DeviceStatusQuery } from '@/constants';
import { DevParamChillerUnit, DevParamCtrlCabinet } from '@/constants/device-params';

import { deviceCardData, DeviceType } from './device-card';
import DeviceWorkParams from './DeviceWorkParams.vue';
import DevWorkParamData from './DevWorkParamData.vue';

import type { DevGroupTabCompProps, DevicesListItem, DeviceTypeCount, PageParams } from '@/types';

const props = defineProps<DevGroupTabCompProps>();

const router = useRouter();
const { isLoading, handleRequest } = useRequest();
const deviceTypes = ref<DeviceTypeCount[]>([]);
const activeDeviceType = ref<DeviceType>(DeviceType.空);
const activeDeviceStatus = ref<DeviceStatusQuery>(DeviceStatusQuery.All);

onMounted(() => {
  handleRequest(async () => {
    deviceTypes.value = await getDevWorkTypeCount(props.deviceGroupId, [
      DeviceType.冷水主机,
      DeviceType.控制柜,
      DeviceType.冷却塔,
      DeviceType.冷却泵,
      DeviceType.冷冻泵,
    ]);

    if (deviceTypes.value.length) {
      activeDeviceType.value = deviceTypes.value[0].deviceType;
      getDeviceList();
    }
  });
});

/**
 * 设备实时数据映射对象
 * - 以设备 id 作为 key
 * - 时间与设备参数的值构成的对象作为 value
 */
type DeviceRTDMap = Record<
  number,
  {
    [key: string]: number | string | undefined;
    time?: string;
  }
>;

const deviceList = ref<DevicesListItem[]>([]);
const deviceTotal = ref(0);
const deviceRealTimeData = ref<DeviceRTDMap>({});
const pageParams = ref<PageParams>({
  pageIndex: 1,
  pageSize: 12,
  pageSorts: [
    {
      column: 'id',
      asc: true,
    },
  ],
});

const deviceListEl = useTemplateRef('deviceListEl');

useInfiniteScroll(
  deviceListEl,
  () => {
    getDeviceList();
  },
  {
    distance: 10,
    canLoadMore: () => {
      if (pageParams.value.pageIndex === 1 || isLoading.value) {
        return false;
      }

      return deviceList.value.length < deviceTotal.value;
    },
  },
);

const getDeviceList = () => {
  handleRequest(async () => {
    let runningStatusList = null;

    if (activeDeviceStatus.value === DeviceStatusQuery.Offline) {
      runningStatusList = [DeviceRunningStatus.Offline];
    } else if (activeDeviceStatus.value === DeviceStatusQuery.Online) {
      runningStatusList = [DeviceRunningStatus.Stop, DeviceRunningStatus.Run];
    }

    const { records, total } = await queryDevicesList({
      ...pageParams.value,
      deviceType: activeDeviceType.value,
      runningStatusList,
    });

    const deviceIds = records.map((item) => item.id);
    const deviceParamCode = deviceCardData[activeDeviceType.value]?.paramCodes || [];

    const data = await getDevWorkRealTimeData(activeDeviceType.value, deviceIds, deviceParamCode);
    const isDeviceChillerUnit = activeDeviceType.value === DeviceType.冷水主机;

    data.forEach((item) => {
      const { deviceId, deviceParamMapList, ...chillerUnitExtraParams } = item;

      if (!deviceRealTimeData.value[deviceId]) {
        deviceRealTimeData.value[deviceId] = {};
      }

      deviceParamMapList.forEach((paramItem) => {
        Object.assign(deviceRealTimeData.value[item.deviceId], paramItem);
      });

      if (isDeviceChillerUnit) {
        Object.assign(deviceRealTimeData.value[item.deviceId], chillerUnitExtraParams);
      }
    });

    deviceList.value.push(...records);
    deviceTotal.value = total;
    pageParams.value.pageIndex++;
  });
};

const handleTabClick = () => {
  deviceList.value = [];
  deviceTotal.value = 0;
  deviceRealTimeData.value = {};

  setTimeout(() => {
    pageParams.value.pageIndex = 1;
    getDeviceList();
  }, 0);
};

const deviceWorkParamsRef = useTemplateRef('deviceWorkParams');

const currentDevId = ref<number>(0);

const viewDevParam = (id: number, e: MouseEvent) => {
  e.stopPropagation();
  currentDevId.value = id;
  deviceWorkParamsRef.value?.showView();
};

const devWorkParamDataRef = useTemplateRef('devWorkParamData');

const currentDevParamCodes = ref<string[]>([]);

const viewHistoryData = (paramCode: string) => {
  currentDevParamCodes.value = [paramCode];
  devWorkParamDataRef.value?.showView();
};

/**
 * 使用事件委托处理设置了参数编码属性 data-param-code 的元素的点击事件，用来查看该参数的历史数据
 */
const handleDevCardClick = (devId: number, e: Event) => {
  const target = e.target as HTMLElement;
  const { paramCode } = target.dataset;

  if (paramCode) {
    currentDevId.value = devId;
    viewHistoryData(paramCode);
  } else {
    router.push(`/device-manage/device-list/equipment-details/${devId}`);
  }
};
</script>

<template>
  <div class="device-work-container">
    <div class="device-work-header">
      <ATabs
        class="button-tabs-card device-type-tab"
        v-model:active-key="activeDeviceType"
        type="card"
        @tab-click="handleTabClick"
      >
        <ATabPane v-for="item in deviceTypes" :key="item.deviceType" :tab="`${item.deviceTypeName}(${item.count})`" />
      </ATabs>
      <ATabs class="device-status-tab" v-model:active-key="activeDeviceStatus" @tab-click="handleTabClick">
        <ATabPane :key="DeviceStatusQuery.All" :tab="$t('common.entire')" />
        <ATabPane :key="DeviceStatusQuery.Online" :tab="$t('common.online')" />
        <ATabPane :key="DeviceStatusQuery.Offline" :tab="$t('common.offline')" />
      </ATabs>
    </div>
    <div ref="deviceListEl" class="device-card-list">
      <ARow :gutter="[22, 24]">
        <ACol v-for="item in deviceList" :key="item.id" :xs="24" :sm="24" :md="24" :lg="24" :xl="12" :xxl="8">
          <div class="device-card-container" @click="handleDevCardClick(item.id, $event)">
            <div class="device-card-header">
              <span
                :class="[
                  'status-dot',
                  {
                    'device-status-offline': item.runningStatus === DeviceRunningStatus.Offline,
                  },
                ]"
              ></span>
              <div class="ellipsis-text device-card-header-title">{{ item.deviceName }}</div>
              <div
                v-if="
                  activeDeviceType === DeviceType.控制柜 &&
                  deviceRealTimeData[item.id]?.[DevParamCtrlCabinet.系统控制模式设定]
                "
                class="ctrl-cabinet-mode"
              >
                {{ deviceRealTimeData[item.id][DevParamCtrlCabinet.系统控制模式设定] }}
              </div>
              <template
                v-if="
                  activeDeviceType === DeviceType.冷水主机 &&
                  deviceRealTimeData[item.id]?.[DevParamChillerUnit.COP] !== undefined
                "
              >
                <div class="device-cop-value">
                  {{ deviceRealTimeData[item.id][DevParamChillerUnit.COP] }}
                </div>
                <!-- <div class="device-cop-level">中</div> -->
              </template>
              <span class="device-card-header-time">{{ deviceRealTimeData[item.id]?.time }}</span>
              <SvgIcon class="device-card-header-button" name="adjustment" @click="viewDevParam(item.id, $event)" />
            </div>
            <component
              :is="deviceCardData[activeDeviceType]?.component"
              :real-time-data="deviceRealTimeData[item.id]"
              :device-detail="JSON.parse(item.deviceDetail || '{}')"
            />
          </div>
        </ACol>
      </ARow>
    </div>
    <DeviceWorkParams ref="deviceWorkParams" :dev-id="currentDevId" @view-history-data="viewHistoryData" />
    <DevWorkParamData ref="devWorkParamData" :dev-id="currentDevId" :param-codes="currentDevParamCodes" />
  </div>
</template>

<style lang="scss" scoped>
.device-work-container {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}

.device-work-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.device-type-tab {
  width: calc(100% - 200px);
}

:deep(.device-status-tab) {
  font-weight: 500;
  line-height: 22px;

  &.ant-tabs-top > .ant-tabs-nav {
    .ant-tabs-tab {
      padding: 5px 0;

      + .ant-tabs-tab {
        margin-left: 24px;
      }
    }

    &::before {
      border: none;
    }
  }
}

.device-card-list {
  flex: 1;
  overflow: hidden auto;
}

.device-card-container {
  position: relative;
  height: 328px;
  padding: 16px 24px;
  background-color: #fff;
  border-radius: 12px;
}

.device-card-header {
  display: flex;
  align-items: center;
  margin-bottom: 24px;
}

.device-status-offline {
  --status-dot-rgb: 191, 191, 191; // RGB 颜色分量 (灰色)
}

.device-card-header-title {
  max-width: 150px;
  margin-right: 16px;
  margin-left: 8px;
  font-size: 16px;
  font-weight: 600;
  line-height: 28px;
  color: var(--antd-color-text);
}

.ctrl-cabinet-mode {
  width: 86px;
  height: 24px;
  font-size: 14px;
  font-weight: 500;
  line-height: 22px;
  color: var(--antd-color-primary);
  text-align: center;
  background: var(--antd-color-primary-opacity-10);
  border: 1px solid var(--antd-color-primary);
  border-radius: 4px;
}

.device-cop-value {
  font-family: DINAlternate;
  font-size: 24px;
  font-weight: bold;
  line-height: 32px;
  color: #e6a23c;
}

.device-cop-level {
  width: 16px;
  height: 16px;
  margin-left: 8px;
  font-size: 12px;
  font-weight: 600;
  line-height: 16px;
  color: #e6a23c;
  text-align: center;
  background: rgb(234 178 94 / 40%);
  border-radius: 2px;
}

.device-card-header-time {
  flex: 1;
  font-size: 12px;
  font-weight: 500;
  line-height: 20px;
  color: #999;
  text-align: right;
}

.device-card-header-button {
  padding: 4px;
  margin-left: 16px;
  font-size: 16px;
  color: var(--antd-color-primary);
  cursor: pointer;
  background: var(--antd-color-primary-opacity-15);
  border-radius: 4px;
}

:deep(.device-card-label) {
  height: 20px;
  font-size: 12px;
  font-weight: 500;
  line-height: 20px;
  color: #999;

  + .progress-text-bar {
    margin-top: 4px;
    cursor: pointer;
  }
}

:deep(.device-card-value) {
  height: 24px;
  font-family: DINAlternate;
  font-size: 16px;
  font-weight: bold;
  line-height: 24px;
  color: #333;
  cursor: pointer;

  &.device-card-no-history {
    cursor: default;
  }
}
</style>
