<script setup lang="ts">
import { reactive, onMounted } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import ChartLine from '@/components/ChartLine/index.vue';
import { getLoad } from '@/api/monitor/monitor';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useI18n from '@/hooks/useI18n';
import {
  YYYY_MM_DD_HH_MM_SS,
  parseDateToStr,
  parseDateWithoutYear,
  parseStrToDate,
} from '@/utils/date-utils';
import { parseSizeFromKBs } from '@/utils/parse-utils';
import dayjs, { Dayjs } from 'dayjs';
const { t } = useI18n();

/**开始结束时间类型 */
type RangePickerType = {
  placeholder: [string, string];
  ranges: Record<string, [Dayjs, Dayjs]>;
  /**全局时间 */
  all: [string, string];
  /**平均负载 */
  load: [string, string];
  /**CPU */
  cpu: [string, string];
  /**内存 */
  memory: [string, string];
  /**磁盘 */
  io: [string, string];
  /**网络 */
  network: [string, string];
};

/**开始结束时间 */
let rangePicker = reactive<RangePickerType>({
  placeholder: [
    t('views.monitor.monitor.startTime'),
    t('views.monitor.monitor.endTime'),
  ],
  ranges: {
    [t('views.monitor.monitor.today')]: [
      dayjs().subtract(1, 'day').startOf('day'),
      dayjs().subtract(1, 'day').endOf('day'),
    ],
    [t('views.monitor.monitor.yesterday')]: [dayjs().startOf('day'), dayjs()],
    [t('views.monitor.monitor.week')]: [
      dayjs().startOf('week'),
      dayjs().endOf('week'),
    ],
    [t('views.monitor.monitor.month')]: [
      dayjs().startOf('month'),
      dayjs().endOf('month'),
    ],
  },
  all: ['', ''],
  load: ['', ''],
  cpu: ['', ''],
  memory: ['', ''],
  io: ['', ''],
  network: ['', ''],
});

/**查询全部资源数据列表 */
function fnGetList() {
  let startTime = null;
  let endTime = null;
  const dateString = rangePicker.all;
  if (dateString[0]) {
    startTime = parseStrToDate(dateString[0], YYYY_MM_DD_HH_MM_SS);
    endTime = parseStrToDate(dateString[1], YYYY_MM_DD_HH_MM_SS);
  } else {
    const now = new Date();
    now.setHours(0, 0, 0, 0);
    startTime = now;
    endTime = new Date();
  }

  getLoad({
    type: 'all',
    startTime: startTime.getTime(),
    endTime: endTime.getTime(),
    neType: '#',
    neId: '#',
  }).then(res => {
    if (res.code === RESULT_CODE_SUCCESS && res.data) {
      fnLoadChart(res.data.base);
      fnCPUChart(res.data.base);
      fnMemoryChart(res.data.base);
      fnIOChart(res.data.io);
      fnNetworkChart(res.data.network);
    }
  });

  // 设置初始时间段
  const initRangePicker: [string, string] = [
    parseDateToStr(startTime, YYYY_MM_DD_HH_MM_SS),
    parseDateToStr(endTime, YYYY_MM_DD_HH_MM_SS),
  ];
  rangePicker.all = initRangePicker;
  rangePicker.load = initRangePicker;
  rangePicker.cpu = initRangePicker;
  rangePicker.memory = initRangePicker;
  rangePicker.io = initRangePicker;
  rangePicker.network = initRangePicker;
}

/**图表显示数据 */
const chartsOption = reactive({
  /**平均负载 */
  loadChart: {},
  /**CPU */
  CPUChart: {},
  /**内存 */
  memoryChart: {},
  /**IO */
  ioChart: {},
  /**网络 */
  networkChart: {},
});

/**初始图表数据-平均负载 */
function fnLoadChart(data: Record<string, any>[]) {
  let loadDate: string[] = [];
  let load1Data: string[] = [];
  let load5Data: string[] = [];
  let load15Data: string[] = [];
  let loadUsage: string[] = [];

  for (const item of data) {
    loadDate.push(parseDateWithoutYear(item.createTime));
    load1Data.push(Number(item.cpuLoad1).toFixed(2));
    load5Data.push(Number(item.cpuLoad5).toFixed(2));
    load15Data.push(Number(item.cpuLoad15).toFixed(2));
    loadUsage.push(Number(item.loadUsage).toFixed(2));
  }

  // 图标参数
  const option = {
    xDatas: loadDate,
    yDatas: [
      {
        name: `1${t('common.units.minute')}`,
        data: load1Data,
      },
      {
        name: `5${t('common.units.minute')}`,
        data: load5Data,
      },
      {
        name: `15${t('common.units.minute')}`,
        data: load15Data,
      },
      {
        name: t('views.monitor.monitor.resourceUsage'),
        data: loadUsage,
        yAxisIndex: 1,
      },
    ],
    yAxis: [
      { type: 'value', name: `${t('views.monitor.monitor.loadDetail')} ( % )` },
      {
        type: 'value',
        name: `${t('views.monitor.monitor.resourceUsage')} ( % )`,
        position: 'right',
        alignTicks: true,
      },
    ],
    grid: { left: '5%', right: '5%', bottom: '20%' },
    formatStr: '%',
  };

  chartsOption.loadChart = option;
}

/**初始图表数据-CPU */
function fnCPUChart(data: Record<string, any>[]) {
  let cpuDate: string[] = [];
  let cpuData: string[] = [];
  for (const item of data) {
    cpuDate.push(parseDateWithoutYear(item.createTime));
    cpuData.push(Number(item.cpu).toFixed(2));
  }

  // 图标参数
  const option = {
    xDatas: cpuDate,
    yDatas: [
      {
        name: 'CPU',
        data: cpuData,
      },
    ],
    grid: {
      left: '5%',
      right: '5%',
      bottom: '20%',
    },
    formatStr: '%',
  };

  chartsOption.CPUChart = option;
}

/**初始图表数据-内存 */
function fnMemoryChart(data: Record<string, any>[]) {
  let memoryDate: string[] = [];
  let memoryData: number[] = [];
  for (const item of data) {
    memoryDate.push(parseDateWithoutYear(item.createTime));
    memoryData.push(Number(item.memory));
  }

  // 图标参数
  const option = {
    xDatas: memoryDate,
    yDatas: [
      {
        name: t('views.monitor.monitor.memory'),
        data: memoryData,
      },
    ],
    grid: {
      left: '5%',
      right: '5%',
      bottom: '20%',
    },
    formatStr: '%',
  };

  chartsOption.memoryChart = option;
}

/**初始图表数据-IO */
function fnIOChart(data: Record<string, any>[]) {
  let ioDate: string[] = [];
  let ioRead: string[] = [];
  let ioWrite: string[] = [];
  let ioCount: number[] = [];
  let ioTime: number[] = [];
  for (const item of data) {
    ioDate.push(parseDateWithoutYear(item.createTime));
    ioRead.push(Number(item.read / 1024).toFixed(2));
    ioWrite.push(Number(item.write / 1024).toFixed(2));
    ioCount.push(Number(item.count));
    ioTime.push(Number(item.time));
  }

  // 图标参数
  const option = {
    xDatas: ioDate,
    yDatas: [
      {
        name: t('views.monitor.monitor.read'),
        data: ioRead,
      },
      {
        name: t('views.monitor.monitor.write'),
        data: ioWrite,
      },
      {
        name: t('views.monitor.monitor.readWriteCount'),
        data: ioCount,
        yAxisIndex: 1,
      },
      {
        name: t('views.monitor.monitor.readWriteTime'),
        data: ioTime,
        yAxisIndex: 1,
      },
    ],
    tooltip: {
      trigger: 'axis',
      formatter: function (datas: any) {
        let res = datas[0].name + '<br/>';
        for (const item of datas) {
          if (
            item.seriesName === t('views.monitor.monitor.read') ||
            item.seriesName === t('views.monitor.monitor.write')
          ) {
            res += `${item.marker} ${item.seriesName}：${parseSizeFromKBs(
              item.data
            )}<br/>`;
          }
          if (item.seriesName === t('views.monitor.monitor.readWriteCount')) {
            res += `${item.marker} ${item.seriesName}：${item.data} ${t(
              'views.monitor.monitor.count'
            )}/s<br/>`;
          }
          if (item.seriesName === t('views.monitor.monitor.readWriteTime')) {
            res += `${item.marker} ${item.seriesName}：${item.data} ms<br/>`;
          }
        }
        return res;
      },
    },
    grid: {
      left: '5%',
      right: '5%',
      bottom: '20%',
    },
    yAxis: [
      { type: 'value', name: '( KB/s )', axisLabel: { fontSize: 10 } },
      {
        type: 'value',
        position: 'right',
        alignTicks: true,
        axisLabel: {
          fontSize: 10,
        },
      },
    ],
  };

  chartsOption.ioChart = option;
}

/**初始图表数据-Network */
function fnNetworkChart(data: Record<string, any>[]) {
  let networkDate: string[] = [];
  let networkUp: string[] = [];
  let networkDown: string[] = [];

  for (const item of data) {
    networkDate.push(parseDateWithoutYear(item.createTime));
    networkUp.push(Number(item.up).toFixed(2));
    networkDown.push(Number(item.down).toFixed(2));
  }

  // 图标参数
  const option = {
    xDatas: networkDate,
    yDatas: [
      {
        name: t('views.monitor.monitor.up'),
        data: networkUp,
      },
      {
        name: t('views.monitor.monitor.down'),
        data: networkDown,
      },
    ],
    grid: {
      left: '5%',
      right: '5%',
      bottom: '20%',
    },
    formatStr: 'KB/s',
  };

  chartsOption.networkChart = option;
}

/**查询数据-平均负载/CPU/内存 */
function fnGetQuery(
  type: 'load' | 'cpu' | 'memory',
  dateString: [string, string]
) {
  if (!dateString[0]) {
    return;
  }
  const startTime = parseStrToDate(dateString[0], YYYY_MM_DD_HH_MM_SS);
  const endTime = parseStrToDate(dateString[1], YYYY_MM_DD_HH_MM_SS);
  getLoad({
    type: type,
    startTime: startTime.getTime(),
    endTime: endTime.getTime(),
    neType: '#',
    neId: '#',
  }).then(res => {
    if (res.code === RESULT_CODE_SUCCESS && res.data) {
      if (type === 'load') {
        fnLoadChart(res.data.base);
      }
      if (type === 'cpu') {
        fnCPUChart(res.data.base);
      }
      if (type === 'memory') {
        fnMemoryChart(res.data.base);
      }
    }
  });
}

/**查询数据-IO */
function fnGetQueryIO(v: any, dateString: [string, string]) {
  if (!v) {
    return;
  }
  const startTime = parseStrToDate(dateString[0], YYYY_MM_DD_HH_MM_SS);
  const endTime = parseStrToDate(dateString[1], YYYY_MM_DD_HH_MM_SS);
  getLoad({
    type: 'io',
    startTime: startTime.getTime(),
    endTime: endTime.getTime(),
    neType: '#',
    neId: '#',
  }).then(res => {
    if (res.code === RESULT_CODE_SUCCESS && res.data) {
      fnIOChart(res.data.io);
    }
  });
}

/**查询数据-Network */
function fnGetQueryNetwork(v: any, dateString: [string, string]) {
  if (!v) {
    return;
  }
  const startTime = parseStrToDate(dateString[0], YYYY_MM_DD_HH_MM_SS);
  const endTime = parseStrToDate(dateString[1], YYYY_MM_DD_HH_MM_SS);
  getLoad({
    type: 'network',
    startTime: startTime.getTime(),
    endTime: endTime.getTime(),
    neType: '#',
    neId: '#',
  }).then(res => {
    if (res.code === RESULT_CODE_SUCCESS && res.data) {
      fnNetworkChart(res.data.network);
    }
  });
}

onMounted(() => {
  fnGetList();
});
</script>

<template>
  <PageContainer>
    <a-card
      :bordered="false"
      :body-style="{ marginBottom: '24px', paddingBottom: 0 }"
    >
      <!-- 表格搜索栏 -->
      <a-form name="queryParams" layout="horizontal">
        <a-row :gutter="16">
          <a-col :lg="10" :md="10" :xs="24">
            <a-form-item
              :label="t('views.monitor.monitor.filter')"
              name="neTypeSelect"
            >
              <a-range-picker
                v-model:value="rangePicker.all"
                :allow-clear="false"
                bordered
                value-format="YYYY-MM-DD HH:mm:ss"
                format="YYYY-MM-DD HH:mm:ss"
                show-time
                :placeholder="rangePicker.placeholder"
                :ranges="rangePicker.ranges"
                style="width: 100%"
              ></a-range-picker>
            </a-form-item>
          </a-col>
          <a-col :lg="6" :md="12" :xs="24">
            <a-form-item>
              <a-space :size="8">
                <a-button type="primary" @click.prevent="fnGetList()">
                  <template #icon><SearchOutlined /></template>
                  {{ t('common.search') }}
                </a-button>
              </a-space>
            </a-form-item>
          </a-col>
        </a-row>
      </a-form>
    </a-card>

    <a-row :gutter="16">
      <a-col :lg="24" :md="24" :xs="24">
        <a-card :bordered="false" :body-style="{ marginBottom: '24px' }">
          <!-- 插槽-卡片左侧侧 -->
          <template #title>{{ t('views.monitor.monitor.avgLoad') }}</template>
          <!-- 插槽-卡片右侧 -->
          <template #extra>
            <a-range-picker
              v-model:value="rangePicker.load"
              :allow-clear="false"
              bordered
              value-format="YYYY-MM-DD HH:mm:ss"
              format="YYYY-MM-DD HH:mm:ss"
              show-time
              :placeholder="rangePicker.placeholder"
              style="width: 100%"
              @change="(_:any, d:[string,string]) => fnGetQuery('load', d)"
            ></a-range-picker>
          </template>

          <div class="chart">
            <ChartLine
              :option="chartsOption.loadChart"
              :dataZoom="true"
              height="400px"
            ></ChartLine>
          </div>
        </a-card>
      </a-col>
    </a-row>
    <a-row :gutter="16">
      <a-col :lg="12" :md="12" :xs="24">
        <a-card :bordered="false" :body-style="{ marginBottom: '24px' }">
          <!-- 插槽-卡片左侧侧 -->
          <template #title>CPU</template>
          <!-- 插槽-卡片右侧 -->
          <template #extra>
            <a-range-picker
              v-model:value="rangePicker.cpu"
              :allow-clear="false"
              bordered
              value-format="YYYY-MM-DD HH:mm:ss"
              format="YYYY-MM-DD HH:mm:ss"
              show-time
              :placeholder="rangePicker.placeholder"
              style="width: 100%"
              @change="(_:any, d:[string,string]) => fnGetQuery('cpu', d)"
            ></a-range-picker>
          </template>

          <div class="chart">
            <ChartLine
              :option="chartsOption.CPUChart"
              :dataZoom="true"
              height="400px"
            ></ChartLine>
          </div>
        </a-card>
      </a-col>
      <a-col :lg="12" :md="12" :xs="24">
        <a-card :bordered="false" :body-style="{ marginBottom: '24px' }">
          <!-- 插槽-卡片左侧侧 -->
          <template #title>{{ t('views.monitor.monitor.memory') }}</template>
          <!-- 插槽-卡片右侧 -->
          <template #extra>
            <a-range-picker
              v-model:value="rangePicker.memory"
              :allow-clear="false"
              bordered
              value-format="YYYY-MM-DD HH:mm:ss"
              format="YYYY-MM-DD HH:mm:ss"
              show-time
              :placeholder="rangePicker.placeholder"
              style="width: 100%"
              @change="(_:any, d:[string,string]) => fnGetQuery('memory', d)"
            ></a-range-picker>
          </template>

          <div class="chart">
            <ChartLine
              :option="chartsOption.memoryChart"
              :dataZoom="true"
              height="400px"
            ></ChartLine>
          </div>
        </a-card>
      </a-col>
    </a-row>
    <a-row :gutter="16">
      <a-col :lg="12" :md="12" :xs="24">
        <a-card :bordered="false" :body-style="{ marginBottom: '24px' }">
          <!-- 插槽-卡片左侧侧 -->
          <template #title>{{ t('views.monitor.monitor.io') }}</template>
          <!-- 插槽-卡片右侧 -->
          <template #extra>
            <a-range-picker
              v-model:value="rangePicker.io"
              :allow-clear="false"
              bordered
              value-format="YYYY-MM-DD HH:mm:ss"
              format="YYYY-MM-DD HH:mm:ss"
              show-time
              :placeholder="rangePicker.placeholder"
              style="width: 100%"
              @change="fnGetQueryIO"
            ></a-range-picker>
          </template>

          <div class="chart">
            <ChartLine
              :option="chartsOption.ioChart"
              :dataZoom="true"
              height="400px"
            ></ChartLine>
          </div>
        </a-card>
      </a-col>
      <a-col :lg="12" :md="12" :xs="24">
        <a-card :bordered="false" :body-style="{ marginBottom: '24px' }">
          <!-- 插槽-卡片左侧侧 -->
          <template #title>{{ t('views.monitor.monitor.network') }}</template>
          <!-- 插槽-卡片右侧 -->
          <template #extra>
            <a-range-picker
              v-model:value="rangePicker.network"
              :allow-clear="false"
              bordered
              value-format="YYYY-MM-DD HH:mm:ss"
              format="YYYY-MM-DD HH:mm:ss"
              show-time
              :placeholder="rangePicker.placeholder"
              style="width: 100%"
              @change="fnGetQueryNetwork"
            ></a-range-picker>
          </template>

          <div class="chart">
            <ChartLine
              :option="chartsOption.networkChart"
              :dataZoom="true"
              height="400px"
            ></ChartLine>
          </div>
        </a-card>
      </a-col>
    </a-row>
  </PageContainer>
</template>

<style lang="less" scoped>
.chart {
  width: 100%;
  height: 400px;
}
</style>
