<script setup lang="ts">
import { initStationAlarms, initStationDevices, syncCameraApi, syncNvrChannelsApi, type Station } from '@/apis';
import { AlarmDetailModal, DeviceDetailModal, DeviceParamConfigModal, IcmpExportModal, RecordCheckExportModal, StationCard, type StationCardProps } from '@/components';
import { useLineDevicesQuery } from '@/composables';
import { useAlarmStore, useDeviceStore, useSettingStore, useStationStore } from '@/stores';
import { parseErrorFeedback } from '@/utils';
import { useMutation } from '@tanstack/vue-query';
import { NButton, NButtonGroup, NCheckbox, NFlex, NGrid, NGridItem, NScrollbar } from 'naive-ui';
import { storeToRefs } from 'pinia';
import { computed, ref } from 'vue';

const settingStore = useSettingStore();
const { stationGridCols: stationGridColumns } = storeToRefs(settingStore);
const stationStore = useStationStore();
const { stations } = storeToRefs(stationStore);
const deviceStore = useDeviceStore();
const { lineDevices } = storeToRefs(deviceStore);
const alarmStore = useAlarmStore();
const { lineAlarms } = storeToRefs(alarmStore);

const { refetch: refetchLineDevicesQuery } = useLineDevicesQuery();

// 操作栏
// 当点击操作栏中的一个按钮时，其他按钮会被禁用
type Action = 'export-icmp' | 'export-record' | 'sync-camera' | 'sync-nvr' | null;
const selectedAction = ref<Action>(null);
const showOperation = ref(false);
const stationSelectable = ref(false);
const stationSelection = ref<Record<Station['code'], boolean>>({});
const showIcmpExportModal = ref(false);
const showRecordCheckExportModal = ref(false);

const onToggleSelectAll = (checked: boolean) => {
  if (!checked) {
    stationSelection.value = {};
  } else {
    stationSelection.value = Object.fromEntries(stations.value.map((station) => [station.code, true]));
  }
};

const onAction = (action: Action) => {
  selectedAction.value = action;
  if (action === null) return;
  showOperation.value = true;
  stationSelectable.value = true;
};

const onCancel = () => {
  selectedAction.value = null;
  showOperation.value = false;
  stationSelectable.value = false;
  stationSelection.value = {};
};

const onFinish = onCancel;

const { mutate: syncCamera, isPending: cameraSyncing } = useMutation({
  mutationFn: async () => {
    const stationCodes = Object.entries(stationSelection.value)
      .filter(([, selected]) => selected)
      .map(([code]) => code);
    const results = await Promise.allSettled(stationCodes.map((stationCode) => syncCameraApi({ stationCode })));
    return results.map((result, index) => ({ ...result, stationCode: stationCodes[index] }));
  },
  onSuccess: (results) => {
    const successCount = results.filter((result) => result.status === 'fulfilled').length;
    const failures = results.filter((result) => result.status === 'rejected');
    const failureCount = failures.length;
    if (failureCount > 0) {
      const failedStations = failures.map((f) => stations.value.find((s) => s.code === f.stationCode)?.name).join('、');
      if (successCount === 0) {
        window.$message.error('摄像机同步全部失败');
        window.$message.error(`${failedStations}`);
      } else {
        window.$message.warning(`摄像机同步完成：成功${successCount}个车站，失败${failureCount}个车站`);
        window.$message.warning(`${failedStations}`);
      }
    } else {
      window.$message.success('摄像机同步成功');
    }
    if (successCount > 0) {
      // 摄像机同步后，需要重新查询一次设备，待测试
      refetchLineDevicesQuery();
    }
    onFinish();
  },
  onError: (error) => {
    console.error(error);
    const errorFeedback = parseErrorFeedback(error);
    window.$message.error(errorFeedback);
    onCancel();
  },
});

const { mutate: syncNvrChannels, isPending: nvrChannelsSyncing } = useMutation({
  mutationFn: async () => {
    const stationCodes = Object.entries(stationSelection.value)
      .filter(([, selected]) => selected)
      .map(([code]) => code);
    const results = await Promise.allSettled(stationCodes.map((stationCode) => syncNvrChannelsApi({ stationCode })));
    return results.map((result, index) => ({ ...result, stationCode: stationCodes[index] }));
  },
  onSuccess: (results) => {
    const successCount = results.filter((result) => result.status === 'fulfilled').length;
    const failures = results.filter((result) => result.status === 'rejected');
    const failureCount = failures.length;
    if (failureCount > 0) {
      const failedStations = failures.map((failure) => stations.value.find((station) => station.code === failure.stationCode)?.name).join('、');
      if (successCount === 0) {
        window.$message.error('录像机通道同步全部失败');
        window.$message.error(`${failedStations}`);
      } else {
        window.$message.warning(`录像机通道同步完成：成功${successCount}个车站，失败${failureCount}个车站`);
        window.$message.warning(`${failedStations}`);
      }
    } else {
      window.$message.success('录像机通道同步成功');
    }
    onFinish();
  },
  onError: (error) => {
    console.error(error);
    const errorFeedback = parseErrorFeedback(error);
    window.$message.error(errorFeedback);
    onCancel();
  },
});

const confirming = computed(() => cameraSyncing.value || nvrChannelsSyncing.value);

const onConfirm = async () => {
  const noStationSelected = !Object.values(stationSelection.value).some((selected) => selected);
  if (selectedAction.value === 'export-icmp') {
    if (noStationSelected) {
      window.$message.warning('请选择要导出设备状态的车站');
      return;
    }
    showIcmpExportModal.value = true;
  } else if (selectedAction.value === 'export-record') {
    if (noStationSelected) {
      window.$message.warning('请选择要导出录像诊断的车站');
      return;
    }
    showRecordCheckExportModal.value = true;
  } else if (selectedAction.value === 'sync-camera') {
    if (noStationSelected) {
      window.$message.warning('请选择要同步摄像机的车站');
      return;
    }
    syncCamera();
  } else if (selectedAction.value === 'sync-nvr') {
    if (noStationSelected) {
      window.$message.warning('请选择要同步录像机通道的车站');
      return;
    }
    syncNvrChannels();
  } else {
    return;
  }
};

// 车站卡片的事件
const selectedStation = ref<Station>();
const showDeviceParamConfigModal = ref(false);
const showDeviceDetailModal = ref(false);
const showAlarmDetailModal = ref(false);

const onClickConfig: StationCardProps['onClickConfig'] = (station) => {
  selectedStation.value = station;
  showDeviceParamConfigModal.value = true;
};

const onClickDetail: StationCardProps['onClickDetail'] = (type, station) => {
  selectedStation.value = station;
  if (type === 'device') {
    showDeviceDetailModal.value = true;
  }
  if (type === 'alarm') {
    showAlarmDetailModal.value = true;
  }
};
</script>

<template>
  <NScrollbar content-style="padding-right: 8px" style="width: 100%; height: 100%">
    <!-- 工具栏 -->
    <NFlex align="center" style="padding: 8px 8px 0 8px">
      <NButtonGroup>
        <NButton secondary :focusable="false" :disabled="!!selectedAction && selectedAction !== 'export-icmp'" @click="() => onAction('export-icmp')">导出设备状态</NButton>
        <NButton secondary :focusable="false" :disabled="!!selectedAction && selectedAction !== 'export-record'" @click="() => onAction('export-record')">导出录像诊断</NButton>
        <NButton secondary :focusable="false" :disabled="!!selectedAction && selectedAction !== 'sync-camera'" @click="() => onAction('sync-camera')">同步摄像机</NButton>
        <NButton secondary :focusable="false" :disabled="!!selectedAction && selectedAction !== 'sync-nvr'" @click="() => onAction('sync-nvr')">同步录像机通道</NButton>
      </NButtonGroup>
      <template v-if="showOperation">
        <NCheckbox label="全选" @update:checked="onToggleSelectAll" />
        <NButton tertiary size="small" type="primary" :focusable="false" :loading="confirming" @click="onConfirm">确定</NButton>
        <NButton tertiary size="small" type="tertiary" :focusable="false" :disabled="confirming" @click="onCancel">取消</NButton>
      </template>
    </NFlex>

    <!-- 车站 -->
    <NGrid :cols="stationGridColumns" :x-gap="6" :y-gap="6" style="padding: 8px">
      <NGridItem v-for="station in stations" :key="station.code">
        <StationCard
          :station="station"
          :devices="lineDevices[station.code] ?? initStationDevices()"
          :alarms="lineAlarms[station.code] ?? initStationAlarms()"
          :selectable="stationSelectable"
          v-model:selected="stationSelection[station.code]"
          @click-detail="onClickDetail"
          @click-config="onClickConfig"
        />
      </NGridItem>
    </NGrid>
  </NScrollbar>

  <IcmpExportModal v-model:show="showIcmpExportModal" :stations="stations.filter((station) => stationSelection[station.code])" @after-leave="onFinish" />
  <RecordCheckExportModal v-model:show="showRecordCheckExportModal" :stations="stations.filter((station) => stationSelection[station.code])" @after-leave="onFinish" />

  <DeviceParamConfigModal v-model:show="showDeviceParamConfigModal" :station="selectedStation" />
  <DeviceDetailModal v-model:show="showDeviceDetailModal" :station="selectedStation" />
  <AlarmDetailModal v-model:show="showAlarmDetailModal" :station="selectedStation" />
</template>

<style scoped lang="scss"></style>
