<script setup lang="ts">
import { PageContainer } from 'antdv-pro-layout';
import { ColumnsType } from 'ant-design-vue/es/table';
import { message } from 'ant-design-vue/es';
import {
  reactive,
  ref,
  onMounted,
  onBeforeUnmount,
  markRaw,
  useTemplateRef,
} from 'vue';
import useI18n from '@/hooks/useI18n';
import { TooltipComponent } from 'echarts/components';
import { GaugeChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import * as echarts from 'echarts/core';
import { TitleComponent, LegendComponent } from 'echarts/components';
import { PieChart } from 'echarts/charts';
import { LabelLayout } from 'echarts/features';
import { useRoute } from 'vue-router';
import useAppStore from '@/store/modules/app';
import useDictStore from '@/store/modules/dict';
import { listAllNeInfo } from '@/api/ne/neInfo';
import { parseDateToStr } from '@/utils/date-utils';
const { getDict } = useDictStore();
const appStore = useAppStore();
const route = useRoute();
const { t } = useI18n();

echarts.use([
  TooltipComponent,
  GaugeChart,
  TitleComponent,
  LegendComponent,
  PieChart,
  CanvasRenderer,
  LabelLayout,
]);

/**图DOM节点实例对象 */
const statusBar = useTemplateRef<HTMLDivElement>('statusBar');

/**图实例对象 */
const statusBarChart = ref<any>(null);

/**表格字段列 */
let tableColumns: ColumnsType = [
  {
    title: t('views.index.object'),
    dataIndex: 'neName',
    align: 'left',
  },
  {
    title: t('views.index.realNeStatus'),
    dataIndex: 'serverState',
    align: 'left',
    key: 'status',
  },
  {
    title: t('views.index.reloadTime'),
    dataIndex: 'serverState',
    align: 'left',
    customRender(opt) {
      if (opt.value?.refreshTime) {
        return parseDateToStr(opt.value?.refreshTime, 'HH:mm:ss');
      }
      return '-';
    },
  },
  {
    title: t('views.index.version'),
    dataIndex: 'serverState',
    align: 'left',
    customRender(opt) {
      return opt.value?.version || '-';
    },
  },
  {
    title: t('views.index.serialNum'),
    dataIndex: 'serverState',
    align: 'left',
    customRender(opt) {
      return opt.value?.sn || '-';
    },
  },
  {
    title: t('views.index.expiryDate'),
    dataIndex: 'serverState',
    align: 'left',
    customRender(opt) {
      return opt.value?.expire || '-';
    },
  },
  {
    title: t('views.index.ipAddress'),
    dataIndex: 'serverState',
    align: 'left',
    customRender(opt) {
      return opt.value?.neIP || '-';
    },
  },
];

/**表格状态类型 */
type TabeStateType = {
  /**加载等待 */
  loading: boolean;
  /**记录数据 */
  data: Record<string, any>[];
  /**勾选记录 */
  selectedRowKeys: (string | number)[];
};

/**表格状态 */
let tableState: TabeStateType = reactive({
  loading: false,
  data: [],
  selectedRowKeys: [],
});

/**状态 */
let serverState: any = ref({});

/**查询网元状态列表 */
async function fnGetList(reload: boolean = false) {
  tableState.loading = !reload;
  try {
    const res = await listAllNeInfo({ bandStatus: true });
    tableState.data = res.data;
  } catch (error) {
    console.error(error);
    tableState.data = [];
  }
  tableState.loading = false;
  if (tableState.data.length == 0) {
    return;
  }

  var rightNum = 0;
  var errorNum = 0;
  for (const v of tableState.data) {
    if (v?.serverState?.online) {
      rightNum++;
    } else {
      errorNum++;
    }
  }

  // 初始
  if (!reload) {
    // 选择第一个
    if (tableState.data.length > 0) {
      const id = tableState.data[0].id;
      fnTableSelectedRowKeys([id]);
    } else {
      fnTableSelectedRowKeys(tableState.selectedRowKeys);
    }

    if (statusBar.value) {
      fnDesign(statusBar.value, rightNum, errorNum);
    }
  } else {
    statusBarChart.value.setOption({
      series: [
        {
          data: [
            { value: rightNum, name: t('views.index.normal') },
            { value: errorNum, name: t('views.index.abnormal') },
          ],
        },
      ],
    });
  }
}

function fnDesign(container: HTMLElement, rightNum: number, errorNum: number) {
  /// 图表数据
  const optionData: any = {
    title: {
      text: '',
      subtext: '',
      left: 'center',
    },
    tooltip: {
      trigger: 'item',
    },
    legend: {
      orient: 'vertical',
      left: 'left',
    },
    color: dict.indexStatus.map(item => item.tagClass),
    series: [
      {
        name: t('views.index.runStatus'),
        type: 'pie',
        radius: '70%',
        center: ['50%', '50%'],
        data: [
          { value: rightNum, name: t('views.index.normal') },
          { value: errorNum, name: t('views.index.abnormal') },
        ],
      },
    ],
  };
  statusBarChart.value = markRaw(echarts.init(container, 'light'));
  statusBarChart.value.setOption(optionData);

  // 创建 ResizeObserver 实例
  var observer = new ResizeObserver(entries => {
    if (statusBarChart.value) {
      statusBarChart.value.resize();
    }
  });
  // 监听元素大小变化
  observer.observe(container);
}

/**表格多选 */
function fnTableSelectedRowKeys(keys: (string | number)[]) {
  if (keys.length <= 0) return;
  const id = keys[0];
  const row: any = tableState.data.find((item: any) => item.id === id);
  if (!row) {
    message.error(t('views.index.neStatus'), 2);
    return;
  }
  const neState = row.serverState;
  if (!neState?.online) {
    message.error(t('views.index.neStatus'), 2);
    return;
  }
  tableState.selectedRowKeys = keys;
  // Mem 将KB转换为MB
  const totalMemInKB = neState.mem?.totalMem;
  const nfUsedMemInKB = neState.mem?.nfUsedMem;
  const sysMemUsageInKB = neState.mem?.sysMemUsage;
  const totalMemInMB = Math.round((totalMemInKB / 1024) * 100) / 100;
  const nfUsedMemInMB = Math.round((nfUsedMemInKB / 1024) * 100) / 100;
  const sysMemUsageInMB = Math.round((sysMemUsageInKB / 1024) * 100) / 100;

  // CPU
  const nfCpu = neState.cpu?.nfCpuUsage;
  const sysCpu = neState.cpu?.sysCpuUsage;
  const nfCpuP = Math.round(nfCpu) / 100;
  const sysCpuP = Math.round(sysCpu) / 100;

  serverState.value = Object.assign(
    {
      cpuUse: `NE:${nfCpuP}%; SYS:${sysCpuP}%`,
      memoryUse: `Total: ${totalMemInMB}MB; NE: ${nfUsedMemInMB}MB; SYS: ${sysMemUsageInMB}MB`,
    },
    neState
  );
}

/**
 * 国际化翻译转换
 */
function fnLocale() {
  let title = route.meta.title as string;
  if (title.indexOf('router.') !== -1) {
    title = t(title);
  }
  appStore.setTitle(title);
}

/**字典数据 */
let dict: {
  /**网元信息状态 */
  neInfoStatus: DictType[];
  /**主页状态 */
  indexStatus: DictType[];
} = reactive({
  neInfoStatus: [],
  indexStatus: [],
});

let timer: any;
onMounted(() => {
  // 初始字典数据
  Promise.allSettled([getDict('ne_info_status'), getDict('index_status')])
    .then(resArr => {
      if (resArr[0].status === 'fulfilled') {
        dict.neInfoStatus = resArr[0].value;
      }
      if (resArr[1].status === 'fulfilled') {
        dict.indexStatus = resArr[1].value;
      }
    })
    .finally(async () => {
      fnLocale();
      await fnGetList(false);
      timer = setInterval(() => {
        if (!timer) return;
        fnGetList(true);
      }, 10_000); // 每隔10秒执行一次
    });
});

// 在组件卸载之前清除定时器
onBeforeUnmount(() => {
  clearInterval(timer);
  timer = null;
});
</script>

<template>
  <PageContainer :breadcrumb="{}">
    <a-row :gutter="16">
      <a-col :lg="14" :md="16" :xs="24">
        <!-- 表格列表 -->
        <a-table
          class="table"
          row-key="id"
          size="small"
          :columns="tableColumns"
          :data-source="tableState.data"
          :loading="tableState.loading"
          :pagination="false"
          :scroll="{ x: true }"
          :row-selection="{
            type: 'radio',
            columnWidth: '48px',
            selectedRowKeys: tableState.selectedRowKeys,
            onChange: fnTableSelectedRowKeys,
          }"
        >
          <template #bodyCell="{ column, record }">
            <template v-if="column.key === 'status'">
              <DictTag :options="dict.neInfoStatus" :value="record.status" />
            </template>
          </template>
        </a-table>
      </a-col>
      <a-col :lg="10" :md="8" :xs="24">
        <a-card
          :title="t('views.index.runStatus')"
          style="margin-bottom: 16px"
          size="small"
        >
          <div style="width: 100%; min-height: 200px" ref="statusBar"></div>
        </a-card>
        <a-card
          :loading="tableState.loading"
          :title="`${t('views.index.mark')} - ${serverState.neName || 'OMC'}`"
          style="margin-top: 16px"
          size="small"
        >
          <a-descriptions
            bordered
            :column="1"
            :label-style="{ width: '160px' }"
          >
            <a-descriptions-item :label="t('views.index.hostName')">
              {{ serverState.hostname }}
            </a-descriptions-item>
            <a-descriptions-item :label="t('views.index.osInfo')">
              {{ serverState.os }}
            </a-descriptions-item>
            <a-descriptions-item :label="t('views.index.ipAddress')">
              {{ serverState.neIP }}
            </a-descriptions-item>
            <a-descriptions-item :label="t('views.index.version')">
              {{ serverState.version }}
            </a-descriptions-item>
            <a-descriptions-item :label="t('views.index.capability')">
              {{ serverState.capability }}
            </a-descriptions-item>
            <a-descriptions-item :label="t('views.index.cpuUse')">
              {{ serverState.cpuUse }}
            </a-descriptions-item>
            <a-descriptions-item :label="t('views.index.memoryUse')">
              {{ serverState.memoryUse }}
            </a-descriptions-item>
            <a-descriptions-item :label="t('views.index.serialNum')">
              {{ serverState.sn }}
            </a-descriptions-item>
            <a-descriptions-item :label="t('views.index.expiryDate')">
              {{ serverState.expire }}
            </a-descriptions-item>
          </a-descriptions>
        </a-card>
      </a-col>
    </a-row>
  </PageContainer>
</template>

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