<script setup lang="ts">
import {
  IBasicAttribute,
  ICartData,
  IColumns,
  IFields,
  ILabelValue,
} from '@/model/System/net-interface';
import {
  haveDataJudgments,
  initInterfaceType,
  initMediaType,
  initShowData,
  processArrayField,
} from '@/pages/System/Info/InfoPages/Net/netFunctions';
import { getErrorTranslate, traduction } from '@/utils/language';
import { PropType, reactive, Ref, ref, watch } from 'vue';

import DataList from '@/components/DataList/DataList.vue';
import CanOpenRowTable from '@/pages/System/Info/InfoPages/Net/NetPages/components/CanOpenRowTable.vue';
import { initExpendTableData, initOpticalData } from '../components/initExpendData';
import { getNetDataPort, getTx, getPortMapping, savePortCount } from '@/pages/System/Info/InfoPages/Net/net.server';
import OpticalTopo from '../components/OpticalTopo.vue';
import { getMessageId, showElMessage } from '@/utils/utils';
import { showFailedMessage } from '@/utils/composition';

const props = defineProps({
  showData: {
    type: Object as PropType<ICartData>,
    default: () => {
      return {};
    },
    requird: true,
  },
});

const emits = defineEmits(['changeDialogShow']);

watch(
  () => props.showData,
  () => {
    initData();
  },
  { deep: true },
);

const nicDeviceData: ILabelValue[] = reactive([]);
const tableData: Ref<any[]> = ref([]);
const splitPortInfo = ref(false);
const txTableData = ref<any[]>([]);
const topologyData = ref<any[]>([]);
const countConfigDialogShow = ref(false);
const countConfigFormRef = ref();
const countConfigCount = ref();
let openRow = reactive([] as any[]);

const columns: IColumns[] = [
  {
    title: traduction('SERVICE_PORT'),
    key: 'PhysicalPortNumber',
  },
  {
    title: traduction('SERVICE_STATUS'),
    key: 'LinkStatus',
  },
  {
    title: traduction('IBMC_NETWORK_PORT_TYPE'),
    key: 'InterfaceType',
  },
  {
    title: traduction('NET_MEDIUM_TYPE'),
    key: 'MediaType',
  },
];

const columnsWRelated: IColumns[] = [
  ...columns,
  {
    title: traduction('NET_RELATED_PROCESSOR'),
    key: 'RelatedProcessor',
  },
];

const opticalColumns: IColumns[] = [
  {
    title: traduction('NET_OPTICAL_ID'),
    key: 'OpticalID',
  },
];

const nicFields: IFields[] = [
  {
    key: 'CardName',
    lable: traduction('NET_NAME'),
  },
  {
    key: 'CardModel',
    lable: traduction('NET_TYPE'),
  },
  {
    key: 'BoardID',
    lable: traduction('OTHER_BOARD_ID'),
  },
  {
    key: 'ComponentUniqueID',
    lable: traduction('COMMON_COMPONENT_UID'),
  },
  {
    key: 'FirmwareVersion',
    lable: traduction('COMMON_FIXED_VERSION'),
  },
  {
    key: 'CardManufacturer',
    lable: traduction('COMMON_MANUFACTURER'),
  },
  {
    key: 'ChipManufacturer',
    lable: traduction('OTHER_CHIP_VENDOR'),
  },
  {
    key: 'ChipModel',
    lable: traduction('OTHER_CHIP_MODEL'),
  },
  {
    key: 'PCBVersion',
    lable: traduction('COMMON_ALARM_PCB_VERSION'),
  },
  {
    key: 'AssociatedResources',
    lable: traduction('COMMON_RESOURCE_OWNER'),
  },
  {
    key: 'RootBDFs',
    lable: traduction('BUS_INFO_BDF'),
  },
  {
    key: 'PcieSlotId',
    lable: traduction('PCIE_SLOTID'),
  },
  {
    key: 'SerialNumber',
    lable: traduction('COMMON_SERIALNUMBER'),
  },
  {
    key: 'Presence',
    lable: traduction('STORE_IN_POSITION'),
  },
  {
    key: 'Position',
    lable: traduction('MEMORY_POSITION'),
  },
];

// 修改弹窗显示状态
function changeDialogShow(val: boolean) {
  emits('changeDialogShow', val);
}

function getVlan(vlanInfo: any) {
  let portData = {
    vlanId: vlanInfo.ID !== null ? vlanInfo.ID : '--',
    vlanEnable: '',
    prEnable: vlanInfo.Priority !== null ? vlanInfo.Priority : '--',
  };
  if (vlanInfo.Enable !== null) {
    portData.vlanEnable = vlanInfo.Enable ? 'Enable' : 'Disable';
  } else {
    portData.vlanEnable = '--';
  }
  return `${portData.vlanId}|${portData.vlanEnable}|${portData.prEnable}`;
}

// 初始化表格展开的数据
function initExpandData(): void {
  tableData.value.forEach(item => {
    if (item && item.extendData) {
      initExpendTableData(item.extendData, item.LinkStatus || '');
    }
  });
}

function initNetworkAttribute(item: IBasicAttribute): void {
  if (item.NetworkAttribute.Name === 'System Ethernet Interface') {
    item.NetworkAttribute.Name = '';
  }

  // VLAN(ID|使能|优先级)
  let vlan: string = '';
  const vlans: any = item.NetworkAttribute.VLAN || [];
  if (vlans && vlans.length > 0) {
    vlans.forEach((v: any) => {
      vlan += `${getVlan(v)} `;
    });
  } else {
    vlan = '';
  }
  if (vlan) {
    item.NetworkAttribute.Vlans = vlan;
  }
}

function ubDataList(): void {
  const cardName = nicDeviceData.filter(item => item.label === traduction('NET_NAME'))[0]?.value as string;
  const filteredFields: ILabelValue[] = [];
  if (['Ethernet Adapter Board', 'UBoE Adapter Board'].some(item => cardName?.includes(item))) {
    const labels = ['PCIE_SLOTID', 'COMMON_RESOURCE_OWNER', 'BUS_INFO_BDF'].map(item => traduction(item));
    nicDeviceData.forEach((item) => {
      if (item.label === traduction('OTHER_CHIP_MODEL')) {
        filteredFields.push({ ...item, value: 'NPU' });
        return;
      }
      if (!labels.includes(item.label)) {
        filteredFields.push(item);
      }
    });
    nicDeviceData.splice(0);
    nicDeviceData.push(...filteredFields);
  }
}

function initTx(data: any): void {
  splitPortInfo.value = data.CardName?.includes('Ethernet Adapter Board');
  txTableData.value.splice(0);
  if (splitPortInfo.value && data.TransceiverUrls) {
    data.TransceiverUrls.forEach((url: string) => {
      if (!url) {
        return;
      }
      txTableData.value.push({
        ['OpticalID']: url.slice(url.lastIndexOf('/') + 1),
        url,
        extendData: { showExpendData: {} },
      });
    });
  }
}

async function initTopo(): Promise<void> {
  if (!splitPortInfo.value) {
    return;
  }
  const adapterId = props.showData.AdapterId;
  try {
    const data = await getPortMapping(adapterId);
    topologyData.value.splice(0);
    topologyData.value.push(...data.PortMappings);
  } catch {
    topologyData.value.splice(0);
  }
}

// 初始化数据
function initData() {
  nicDeviceData.splice(0);
  countConfigCount.value = `${props.showData.PreloadPortCount}`;
  tableData.value = [];
  const data = JSON.parse(JSON.stringify(props.showData));

  if (data.Presence === 0 || data.Presence) {
    data.Presence = data.Presence === 0 ? traduction('COMMON_NO') : traduction('COMMON_YES');
  }
  if (data?.RootBDFs) {
    processArrayField(data, 'RootBDFs');
  }
  if (data?.AssociatedResources) {
    processArrayField(data, 'AssociatedResources');
  }
  // 网卡设备
  initShowData(data, nicFields, nicDeviceData);
  ubDataList();
  initTx(data);
  initTopo();

  // 端口属性
  if (data.PortProperties && data.PortProperties.length > 0) {
    data.PortProperties.forEach((item: IBasicAttribute) => {
      item.PhysicalPortNumber = haveDataJudgments(item.PhysicalPortNumber, 'Port');
      // 网口类型：物理网口或者虚拟网口
      item.InterfaceType = initInterfaceType(item.InterfaceType);
      // 介质类型：电口或者光口
      item.MediaType = initMediaType(item.MediaType);
      const checkItem = openRow.find((i: any) => i.PhysicalPortNumber === item.PhysicalPortNumber);
      const relatedPorts = item.RelatedProcessorPorts?.[0];
      item.RelatedProcessor = relatedPorts ? `${relatedPorts.ProcessorSilkText} IODie ${relatedPorts.IODieId} ${relatedPorts.PortId}` :  '--';
      if (checkItem) {
        tableData.value.push({ ...checkItem, ...item, adapterId: data.adapterId});
      } else {
        tableData.value.push({ ...item, adapterId: data.adapterId , extendData: { showExpendData: {} } });
      }
    });
  }
  resetPort(data.adapterId);
}

function expandChange(obj: any) {
  openRow = JSON.parse(JSON.stringify(obj.expandedRows));
  const checkItem = openRow.find((item: any) => item.PhysicalPortNumber === obj.row.PhysicalPortNumber);
  if (checkItem) {
    getPortData(
      checkItem.adapterId,
      obj.row.PhysicalPortNumber?.split('')
        ?.splice(4)
        ?.join(''),
      obj.row,
      obj,
    );
  }
}

function txExpandChange(obj: any) {
  openRow = JSON.parse(JSON.stringify(obj.expandedRows));
  const checkItem = openRow.find((item: any) => item.OpticalID === obj.row.OpticalID);
  if (checkItem) {
    getTx(obj.row.url)
      .then((res) => {
        obj.row.extendData.OpticalModule = res;
        initOpticalData(obj.row.extendData);
      });
  }
}

function getPortData(id: string, port: number, row: any, obj?: any) {
  getNetDataPort(id, port)
    .then((res: any) => {
      const checkIndex = tableData.value.findIndex(
        (item: any) => item.PhysicalPortNumber === row.PhysicalPortNumber,
      );
      if (checkIndex > -1) {
        tableData.value[checkIndex].extendData = JSON.parse(JSON.stringify(res));
        if (tableData.value[checkIndex].extendData?.NetworkAttribute) {
          initNetworkAttribute(tableData.value[checkIndex].extendData);
        }
        if (tableData.value[checkIndex] && tableData.value[checkIndex]?.extendData) {
          initExpendTableData(
            tableData.value[checkIndex].extendData,
            tableData.value[checkIndex].LinkStatus || '',
          );
        }
      }
    })
    .finally(() => {
      if (obj) {
        openRow = JSON.parse(JSON.stringify(obj.expandedRows));
      }
    });
}

function resetPort(adapterId: string) {
  openRow.forEach((element: any) => {
    getPortData(
      adapterId,
      element.PhysicalPortNumber.split('')
        .splice(4)
        .join(''),
      element,
    );
  });
}

async function savePortCountConfig(): Promise<void> {
  try {
    await savePortCount(props.showData.AdapterId, parseInt(countConfigCount.value, 10));
    countConfigDialogShow.value = false;
    showElMessage('success', traduction('COMMON_SUCCESS'));
    resetPort(props.showData.AdapterId);
  } catch (error: any) {
    const errors = getMessageId(error.data);
    if (error && errors?.length > 0) {
      const errorId = errors[0].code;
      const errorMsg = getErrorTranslate(errorId as string);
      showFailedMessage(errorMsg);
    }
  }
}

defineExpose({
  resetPort,
});

initData();
</script>

<template>
  <div class="card-box">
    <div class="n-i-c-device">
      <div class="left">
        <img src="@/assets/common/image/network_card.svg" class="img" />
        <div class="part-title">{{ $t('NET_DEVICE') }}</div>

        <el-button
          v-if="showData.HotPlugSupported"
          id="hotPlugSupported"
          class="hot-plugin-btn"
          :disabled="
            showData.OrderlyHotplugCtrlStatus !== 'Removable' &&
              showData.OrderlyHotplugCtrlStatus !== 'Insertable'
          "
          @click="changeDialogShow(true)"
        >
          {{ $t('FDM_HOT_PLUG_OPERATION') }}
        </el-button>
        <el-tag
          v-if="showData.OrderlyHotplugCtrlStatus === 'Uninstalled'"
          id="OrderlyHotplugCtrlStatusTag"
          class="hot-plugin-tag"
          size="small"
          type="info"
        >
          {{ $t('NET_UNINSTALLED') }}
        </el-tag>
      </div>

      <div class="right-key-value-box">
        <DataList id="netCardAttr" :data-list="nicDeviceData" />
      </div>
    </div>

    <div class="port-attributes">
      <div class="title">
        {{ $t(splitPortInfo ? 'NET_PORT_DETAIL' : 'OTHER_PORT_ATTR') }}
      </div>

      <div v-if="!splitPortInfo" class="table-box">
        <el-button
          v-if="props.showData.PortCount && props.showData.PreloadPortCountAllowableValues"
          class="config-btn"
          @click="countConfigDialogShow = true"
        >
          {{ $t('NET_PORT_COUNT_CONFIG') }}
        </el-button>
        <CanOpenRowTable
          id="netCardPort"
          :columns="columns"
          :table-data="tableData"
          @expand-change="expandChange"
        />
      </div>
      <el-tabs v-else class="info-tabs">
        <el-tab-pane :label="$t('OTHER_PORT_ATTR')">
          <div class="table-box">
            <CanOpenRowTable
              id="netCardPort"
              :columns="columnsWRelated"
              :table-data="tableData"
              :selected-attrs="['OpticalModule']"
              @expand-change="expandChange"
            />
          </div>
        </el-tab-pane>
        <el-tab-pane v-if="txTableData.length" :label="$t('NET_OPTICAL_RESOURCE')">
          <div class="table-box">
            <CanOpenRowTable
              id="opticalResource"
              row-key="OpticalID"
              :columns="opticalColumns"
              :table-data="txTableData"
              @expand-change="txExpandChange"
            />
          </div>
        </el-tab-pane>
        <el-tab-pane :label="$t('NET_OPTICAL_TOPOLOGY')">
          <OpticalTopo
            v-if="topologyData.length > 0"
            :adapter-id="props.showData.AdapterId"
            :topo-data="topologyData"
            :tx-data="txTableData"
          />
        </el-tab-pane>
      </el-tabs>
      <el-dialog id="countConfigDialog" v-model="countConfigDialogShow" :title="$t('NET_PORT_COUNT_CONFIG')">
        <el-alert :title="$t('NET_PORT_COUNT_CONFIG_TIP')" :closable="false" show-icon />
        <el-form ref="countConfigFormRef">
          <el-form-item :label="$t('NET_PORT_CURRENT_COUNT')">
            {{ props.showData.PortCount }}
          </el-form-item>
          <el-form-item :label="$t('NET_PORT_ENABLE_COUNT')">
            <el-radio-group
              v-model="countConfigCount"
            >
              <el-radio 
                v-for="count in props.showData.PreloadPortCountAllowableValues"
                v-addId.radio="count"
                :value="`${count}`"
              >
                {{ count }}
              </el-radio>
            </el-radio-group>
          </el-form-item>
        </el-form>
        <template #footer>
          <el-button
            :disabled="String(props.showData.PreloadPortCount) === countConfigCount"
            type="primary"
            @click="savePortCountConfig"
          >
            {{ $t('COMMON_SAVE') }}
          </el-button>
          <el-button @click="countConfigDialogShow = false; countConfigCount = `${props.showData.PreloadPortCount}`">
            {{ $t('ALARM_CANCEL') }}
          </el-button>
        </template>
      </el-dialog>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.hot-plugin-tag {
  margin-top: 7px;
}

.hot-plugin-btn {
  height: 24px;

  &:hover {
    border-bottom-color: $APP-COLOR-HOVER;
  }
  &.disabled {
    border-bottom-color: var(--o-bg-color-placeholder);
    cursor: not-allowed;
  }

  // 禁用按钮背景填充色
  &.is-disabled,
  &.is-disabled:hover,
  &.is-disabled:active,
  &.is-disabled:focus {
    background-color: var(--o-bg-color-placeholder) !important;
    border-color: var(--o-button-color_disabled) !important;
  }
}

.n-i-c-device{
  min-height: 184px;
}

.info-tabs {
  margin-top: 16px;
}

.table-box {
  padding-top: 24px;
}

.config-btn {
  margin-bottom: 16px;
  height: 32px;
}

:deep(#countConfigDialog form) {
  margin-top: 8px !important;
}

:deep(#countConfigDialog .el-form-item) {
  margin-bottom: 0 !important;
}

:deep(#countConfigDialog .el-dialog__body) {
  padding-top: 16px !important;
  padding-bottom: 8px !important;
}

:deep(.port-attributes .info-tabs) {
  flex: 1;
  .el-tab-pane {
    height: 100%;
  }
}
</style>