<script lang="ts" setup>
import { onMounted, reactive } from 'vue';
import { message, Modal } from 'ant-design-vue/lib';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { PageContainer } from 'antdv-pro-layout';
import { dumpStart, dumpStop, traceUPF } from '@/api/traceManage/pcap';
import { listNe } from '@/api/ne/ne';
import { getNeFile } from '@/api/tool/neFile';
import saveAs from 'file-saver';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();

/**对话框对象信息状态类型 */
type ModalStateType = {
  /**表单数据 */
  from: Record<string, any>;
  /**tcpdump命令组 */
  cmdOptions: Record<string, any>[];
  /**UPF命令组 */
  cmdOptionsUPF: Record<string, any>[];
  /**详情框是否显示 */
  visibleByView: boolean;
  /**详情框内容 */
  logMsg: string;
};

/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
  from: {},
  cmdOptions: [
    {
      label: t('views.traceManage.pcap.execCmd'),
      start: '-n -s 0 -v -w',
      stop: '',
      value: 'any',
    },
    {
      label: t('views.traceManage.pcap.execCmdsSctp'),
      start: 'sctp or tcp port 3030 or 8088',
      stop: '',
      value: 'any2',
    },
  ],
  cmdOptionsUPF: [
    {
      label: t('views.traceManage.pcap.execUPFCmdA'),
      start: 'pcap trace rx tx max 100000 intfc any',
      stop: 'pcap trace rx tx off',
      value: 'pcap trace',
    },
    {
      label: t('views.traceManage.pcap.execUPFCmdB'),
      start: 'pcap dispatch trace on max 100000',
      stop: 'pcap dispatch trace off',
      value: 'pcap dispatch',
    },
  ],
  visibleByView: false,
  logMsg: '',
});

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

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

/**表格字段列 */
let tableColumns: ColumnsType = [
  {
    title: t('views.configManage.neManage.neType'),
    dataIndex: 'neType',
    align: 'left',
    width: 100,
  },
  {
    title: t('views.configManage.neManage.neId'),
    dataIndex: 'neId',
    align: 'left',
    width: 100,
  },
  {
    title: t('views.configManage.neManage.neName'),
    dataIndex: 'neName',
    align: 'left',
    width: 100,
  },
  {
    title: t('views.configManage.neManage.ip'),
    dataIndex: 'ip',
    align: 'left',
    width: 150,
  },
  {
    title: t('views.traceManage.pcap.cmd'),
    key: 'cmd',
    dataIndex: 'serverState',
    align: 'left',
    width: 300,
  },
  {
    title: t('common.operate'),
    key: 'id',
    align: 'left',
    fixed: 'right',
  },
];

/**表格多选 */
function fnTableSelectedRowKeys(keys: (string | number)[]) {
  tableState.selectedRowKeys = keys;
}

/**查询全部网元数据列表 */
function fnGetList() {
  if (tableState.loading) return;
  tableState.loading = true;
  listNe({
    bandStatus: false,
  }).then(res => {
    if (
      res.code === RESULT_CODE_SUCCESS &&
      Array.isArray(res.data) &&
      res.data.length > 0
    ) {
      tableState.data = res.data;
      // 初始网元参数表单
      const { start, stop } = modalState.cmdOptions[0];
      for (const item of res.data) {
        modalState.from[item.id] = {
          loading: false,
          title: item.neName, // 网元名
          cmdStart: start,
          cmdStop: stop, // upf需要停止命令
          out: '',
          log: '',
          data: {
            neType: item.neType,
            neId: item.neId,
          },
        };
      }
    } else {
      message.warning({
        content: t('common.noData'),
        duration: 2,
      });
    }
    tableState.loading = false;
  });
}

/**抓包命令选择 */
function fnSelectCmd(id: any, option: any) {
  modalState.from[id].cmdStart = option.start;
  modalState.from[id].cmdStop = option.stop;
}

/**
 * 开始
 * @param row 行记录
 */
function fnRecordStart(row?: Record<string, any>) {
  let neIDs: string[] = [];
  if (row) {
    neIDs = [`${row.id}`];
  } else {
    row = {
      neName: t('views.traceManage.pcap.textSelect'),
    };
    neIDs = tableState.selectedRowKeys.map(s => `${s}`);
  }

  Modal.confirm({
    title: t('common.tipTitle'),
    content: t('views.traceManage.pcap.startTip', { title: row.neName }),
    onOk() {
      const hide = message.loading(t('common.loading'), 0);
      const fromArr = neIDs.map(id => modalState.from[id]);
      const reqArr = fromArr.map(from => {
        const data = Object.assign({ cmd: from.cmdStart }, from.data);
        if (from.data.neType === 'UPF' && from.cmdStart.startsWith('pcap')) {
          return traceUPF(data);
        }
        return dumpStart(data);
      });
      Promise.allSettled(reqArr)
        .then(resArr => {
          resArr.forEach((res, idx) => {
            const title = fromArr[idx].title;
            if (res.status === 'fulfilled') {
              const resV = res.value;
              if (resV.code === RESULT_CODE_SUCCESS) {
                fromArr[idx].out = resV.data.out;
                fromArr[idx].log = resV.data.log;
                fromArr[idx].loading = true;
                message.success({
                  content: t('views.traceManage.pcap.startOk', { title }),
                  duration: 3,
                });
              } else {
                message.warning({
                  content: `${resV.msg}`,
                  duration: 3,
                });
              }
            } else {
              message.error({
                content: t('views.traceManage.pcap.startErr', { title }),
                duration: 3,
              });
            }
          });
        })
        .finally(() => {
          hide();
        });
    },
  });
}

/**
 * 停止
 * @param row 行记录
 */
function fnRecordStop(row?: Record<string, any>) {
  let neIDs: string[] = [];
  if (row) {
    neIDs = [`${row.id}`];
  } else {
    row = {
      neName: t('views.traceManage.pcap.textSelect'),
    };
    neIDs = tableState.selectedRowKeys.map(s => `${s}`);
  }

  Modal.confirm({
    title: t('common.tipTitle'),
    content: t('views.traceManage.pcap.stopTip', { title: row.neName }),
    onOk() {
      const hide = message.loading(t('common.loading'), 0);
      const fromArr = neIDs.map(id => modalState.from[id]);
      const reqArr = fromArr.map(from => {
        if (from.data.neType === 'UPF' && from.cmdStart.startsWith('pcap')) {
          return traceUPF(Object.assign({ cmd: from.cmdStop }, from.data));
        }
        return dumpStop(Object.assign({ fileName: from.out }, from.data));
      });
      Promise.allSettled(reqArr)
        .then(resArr => {
          resArr.forEach((res, idx) => {
            const title = fromArr[idx].title;
            if (res.status === 'fulfilled') {
              const resV = res.value;
              if (resV.code === RESULT_CODE_SUCCESS) {
                fromArr[idx].out = resV.data.out;
                fromArr[idx].log = resV.data.log;
                fromArr[idx].loading = false;
                message.success({
                  content: t('views.traceManage.pcap.stopOk', { title }),
                  duration: 3,
                });
              } else if (resV.msg.indexOf('not run') > 0) {
                message.warning({
                  content: t('views.traceManage.pcap.stopNotRun', { title }),
                  duration: 3,
                });
              } else {
                message.warning({
                  content: `${resV.msg}`,
                  duration: 3,
                });
              }
            } else {
              message.error({
                content: t('views.traceManage.pcap.stopErr', { title }),
                duration: 3,
              });
            }
          });
        })
        .finally(() => {
          hide();
        });
    },
  });
}

/**下载PCAP文件 */
function fnDownPCAP(row?: Record<string, any>) {
  let neIDs: string[] = [];
  if (row) {
    neIDs = [`${row.id}`];
  } else {
    row = {
      neName: t('views.traceManage.pcap.textSelect'),
    };
    neIDs = tableState.selectedRowKeys.map(s => `${s}`);
  }

  Modal.confirm({
    title: t('common.tipTitle'),
    content: t('views.traceManage.pcap.downTip', { title: row.neName }),
    onOk() {
      const hide = message.loading(t('common.loading'), 0);
      const fromArr = neIDs.map(id => modalState.from[id]);
      const reqArr = [];
      for (const from of fromArr) {
        if (!from.out) {
          message.warning({
            content: t('views.traceManage.pcap.stopNotRun', {
              title: from.title,
            }),
            duration: 3,
          });
          continue;
        }

        reqArr.push(
          getNeFile(
            Object.assign(
              {
                path: '/tmp',
                fileName: `${from.out}.pcap`,
              },
              from.data
            )
          )
        );
      }

      Promise.allSettled(reqArr)
        .then(resArr => {
          resArr.forEach((res, idx) => {
            const title = fromArr[idx].title;

            if (res.status === 'fulfilled') {
              const resV = res.value;
              if (resV.code === RESULT_CODE_SUCCESS) {
                message.success({
                  content: t('views.traceManage.pcap.downOk', { title }),
                  duration: 3,
                });
                // 文件名
                const fileName = `${fromArr[idx].out}.pcap`;
                if (fileName.length > 6) {
                  saveAs(resV.data, fileName);
                }
              } else {
                message.warning({
                  content: `${resV.msg}`,
                  duration: 3,
                });
              }
            } else {
              message.error({
                content: t('views.traceManage.pcap.downErr', { title }),
                duration: 3,
              });
            }
          });
        })
        .finally(() => {
          hide();
        });
    },
  });
}

/**
 * 对话框弹出显示为 查看
 * @param dictId 字典编号id
 */
function fnModalVisibleByVive(id: string | number) {
  const from = modalState.from[id];
  if (!from) return;
  modalState.visibleByView = true;
  modalState.logMsg = from.log;
}

/**
 * 对话框弹出关闭执行函数
 * 进行表达规则校验
 */
function fnModalCancel() {
  modalState.visibleByView = false;
  modalState.logMsg = '';
}

onMounted(() => {
  // 获取网元列表
  fnGetList();
});
</script>

<template>
  <PageContainer>
    <a-card :bordered="false" :body-style="{ padding: '0px' }">
      <!-- 插槽-卡片左侧侧 -->
      <template #title>
        <a-space :size="8" align="center">
          <a-button
            type="primary"
            :disabled="tableState.selectedRowKeys.length <= 0"
            @click.prevent="fnRecordStart()"
          >
            <template #icon><PlayCircleOutlined /> </template>
            {{ t('views.traceManage.pcap.textStartBatch') }}
          </a-button>
          <a-button
            danger
            :disabled="tableState.selectedRowKeys.length <= 0"
            @click.prevent="fnRecordStop()"
          >
            <template #icon><CloseSquareOutlined /> </template>
            {{ t('views.traceManage.pcap.textStopBatch') }}
          </a-button>
          <a-button
            type="dashed"
            :disabled="tableState.selectedRowKeys.length <= 0"
            @click.prevent="fnDownPCAP()"
          >
            <template #icon><DownloadOutlined /></template>
            {{ t('views.traceManage.pcap.textDownBatch') }}
          </a-button>
        </a-space>
      </template>

      <!-- 插槽-卡片右侧 -->
      <template #extra>
        <a-space :size="8" align="center">
          <a-tooltip>
            <template #title>{{ t('common.reloadText') }}</template>
            <a-button type="text" @click.prevent="fnGetList()">
              <template #icon><ReloadOutlined /></template>
            </a-button>
          </a-tooltip>
        </a-space>
      </template>

      <!-- 表格列表 -->
      <a-table
        class="table"
        row-key="id"
        size="small"
        :columns="tableColumns"
        :loading="tableState.loading"
        :data-source="tableState.data"
        :pagination="false"
        :scroll="{ x: tableColumns.length * 120 }"
        :row-selection="{
          type: 'checkbox',
          selectedRowKeys: tableState.selectedRowKeys,
          onChange: fnTableSelectedRowKeys,
        }"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'cmd'">
            <a-auto-complete
              v-model:value="modalState.from[record.id].cmdStart"
              :options="
                record.neType === 'UPF'
                  ? modalState.cmdOptions.concat(modalState.cmdOptionsUPF)
                  : modalState.cmdOptions
              "
              :placeholder="t('views.traceManage.pcap.capArgPlease')"
              :disabled="modalState.from[record.id].loading"
              allow-clear
              @select="(_: any, option: any) => fnSelectCmd(record.id, option)"
              style="width: 100%"
            />
          </template>
          <template v-if="column.key === 'id'">
            <a-space :size="8" align="start" direction="horizontal">
              <a-button
                type="primary"
                size="small"
                :loading="modalState.from[record.id].loading"
                @click.prevent="fnRecordStart(record)"
              >
                <template #icon><PlayCircleOutlined /> </template>
                {{ t('views.traceManage.pcap.textStart') }}
              </a-button>

              <a-button
                type="default"
                danger
                size="small"
                @click.prevent="fnRecordStop(record)"
              >
                <template #icon><CloseSquareOutlined /> </template>
                {{ t('views.traceManage.pcap.textStop') }}
              </a-button>

              <a-button
                type="primary"
                ghost
                size="small"
                @click.prevent="fnModalVisibleByVive(record.id)"
                v-if="modalState.from[record.id].log"
              >
                <template #icon><FileTextOutlined /> </template>
                {{ t('views.traceManage.pcap.textLog') }}
              </a-button>

              <a-button
                type="primary"
                ghost
                size="small"
                @click.prevent="fnDownPCAP(record)"
                v-if="
                  !modalState.from[record.id].loading &&
                  modalState.from[record.id].out
                "
              >
                <template #icon><DownloadOutlined /></template>
                {{ t('views.traceManage.pcap.textDown') }}
              </a-button>
            </a-space>
          </template>
        </template>
      </a-table>
    </a-card>

    <!-- 详情框 -->
    <a-modal
      width="800px"
      :visible="modalState.visibleByView"
      :footer="null"
      :maskClosable="false"
      :keyboard="false"
      :title="t('views.traceManage.pcap.textLogMsg')"
      @cancel="fnModalCancel"
    >
      <a-textarea
        v-model:value="modalState.logMsg"
        :auto-size="{ minRows: 2, maxRows: 24 }"
        :disabled="true"
        style="color: rgba(0, 0, 0, 0.85)"
      />
    </a-modal>
  </PageContainer>
</template>

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