<template>
  <div id="license" :class="{ 'license-full': total > 0 }">
    <div class="license-title">{{ $t('LICENSE_INFO') }}</div>
    <el-upload
      v-if="hasUserConfigPrivil"
      id="licenseInstall"
      :auto-upload="uploadConfig.isAutoUpload"
      :accept="uploadConfig.accept"
      :show-file-list="uploadConfig.showList"
      :on-change="uploadConfig.onChange"
      :disabled="isSystemLock"
    >
      <el-button type="primary" :disabled="isSystemLock" size="default">
        {{ $t('LICENSE_INSTALL') }}
      </el-button>
      <template #tip></template>
    </el-upload>
    <div class="esn-value">
      <span class="esn-title">{{ $t('LICENSE_PRIDUCT_ESN') }}</span>
      <span>{{ esnValue }}</span>
    </div>
    <div v-if="isInstallation" class="license-card">
      <div id="topDiv">
        <p class="license-info">{{ $t('LICENSE_BASEINFO') }}</p>
        <div id="isBtnGroup">
          <div
            v-if="isDelBtn && hasUserConfigPrivil"
            id="licenseDelBtn"
            class="tab-btn"
            :class="{ 'disabled-btn': isSystemLock }"
            @click="licenseDel()"
          >
            <span>
              <img src="@/assets/common/image/license-delete.png" />
            </span>
            {{ $t('LICENSE_DELETE') }}
          </div>
          <div
            v-if="isInvalidBtn && hasUserConfigPrivil"
            id="licenseInvalidBtn"
            class="tab-btn"
            :class="{ 'disabled-btn': isSystemLock }"
            @click="licenseInvalid()"
          >
            <span>
              <img src="@/assets/common/image/license-invalid.png" />
            </span>
            {{ $t('LICENSE_REVOKE') }}
          </div>
          <div
            v-if="isExportBtn && hasUserConfigPrivil"
            id="licenseDownloadBtn"
            class="tab-btn"
            @click="downloadFile()"
          >
            <span>
              <img src="@/assets/common/image/license-export.png" />
            </span>
            {{ $t('LICENSE_EXPORT') }}
          </div>
        </div>
      </div>
      <div>
        <div>
          <el-form id="producteId" class="text-form" label-width="auto" label-position="left">
            <el-form-item
              v-for="(item, index) in leftBasicInformation.data"
              :key="item.label"
              :label="item.label"
            >
              <span
                :class="['license-span-' + index, { revoke: item.revoke }]"
                class="license-span"
              >
                {{ item.value }}
              </span>
              <span v-if="item.revokeLabel" class="revoke-code">
                {{ `${item.revokeLabel} ${item.revokeValue}` }}
              </span>
            </el-form-item>
          </el-form>
        </div>
      </div>
    </div>
    <div v-if="!isInstallation" id="noLicense" class="no-license">
      <div id="invalidCode">
        <label v-if="isInvalid">
          {{ `${traduction('LICENSE_REVOKE_CODE')}&nbsp;&nbsp; ${invalidCodeVal}` }}
        </label>
      </div>
      <div>
        <img src="@/assets/common/image/license-nodata.svg" />
        <br />
        <label v-if="!isInstallation" v-t="'LICENSE_INSTALL_ERROR'" class="no-license-text"></label>
      </div>
    </div>
    <!-- 高级特性 -->
    <div class="advanced">
      <p v-t="'LICENSE_ADVANCE_FEATURE'"></p>
      <el-table
        v-addId.table="'licenseAdvanceTable'"
        :row-class-name="setRowClass"
        :data="tableData.data"
        border
        resizable
      >
        <el-table-column :label="traduction('LICENSE_FEATURE_NUMBER')">
          <template #default="scope">
            <span class="advance-index">{{ scope.row.index }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="traduction('LICENSE_FEATURE_NAME')">
          <template #default="scope">
            <span class="advance-name">{{ scope.row.name }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="traduction('LICENSE_FEATURE_STATE')">
          <template #default="scope">
            <span class="advance-state">{{ scope.row.state }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="traduction('LICENSE_SALE_STATE')">
          <template #default="scope">
            <span
              v-if="scope.row.value == 1"
              v-t="'ENABLED'"
              class="comon-state enable advance-status"
            ></span>
            <span
              v-if="scope.row.value == 0"
              v-t="'DISABLED'"
              class="comon-state disable advance-status"
            ></span>
            <span v-if="scope.row.value == 255" class="advance-status">--</span>
          </template>
        </el-table-column>
        <el-table-column :label="traduction('LICENSE_EXPIRATION')">
          <template #default="scope">
            <span class="advance-valid">
              {{ scope.row.validDate == '' ? '--' : scope.row.validDate }}
            </span>
          </template>
        </el-table-column>
      </el-table>
      <div v-if="total > 0" class="pagination"></div>
    </div>
    <Dialog ref="dialogRef" :config="dialogConfig" @close="closeModal"></Dialog>
  </div>
</template>

<script setup lang="ts">
import { UI_REST_GENERALDOWNLOAD } from '@/api/api';
import { checkPrivil } from '@/apps/app-bmc/router/routes';
import Dialog from '@/components/Dialog/Dialog.vue';
import { UserPrivil } from '@/model/base-enum';
import { uploadLdapFile } from '@/pages/User/Ldap/services/ldap.service';
import { downloadFileWithResponse, restDownloadFile } from '@/utils/common-service';
import { loading, showFailedMessage, showSuccessMessage } from '@/utils/composition';
import { getErrorTranslate, traduction } from '@/utils/language';
import { getMessageId } from '@/utils/utils';
import { computed, onMounted, reactive, ref } from 'vue';
import useStore from '@/stores';
import {
  download,
  findLicenseInfo,
  getTask,
  licenseDelService,
  licenseInvalidService,
  uploadLicense,
} from './license.service';
import $http from '@/utils/http-service';

const store = useStore();

let isSystemLock = computed(() => {
  return store.state.glob.systemLocked;
});
const hasUserConfigPrivil = checkPrivil(UserPrivil.userConfig);

interface IinfoRow {
  label: string;
  value: string;
  revoke?: boolean;
  [propName: string]: any;
}
const isInvalid = ref(false);
const invalidCodeVal = ref('');
const leftBasicInformation = reactive({
  data: [{ label: '', value: '', revoke: false } as IinfoRow],
});
const isInstallation = ref(false);
const isDelBtn = ref(false);
const isExportBtn = ref(false);
const isInvalidBtn = ref(false);
const licenseStatusValue = ref('');
const dialogConfig = reactive({
  title: traduction('COMMON_CONFIRM'),
  content: traduction('COMMON_ASK_OK'),
  id: 'portDialog',
  alignItems: 'center',
});
const dialogRef = ref();

const esnValue = ref('--');
function alertMessage(type: string, message: string) {
  return store.state.event.setEventState({
    type: 'alertMessage',
    value: { type: type, message: traduction(message) },
  });
}

const uploadConfig = reactive({
  isAutoUpload: false,
  accept: '.xml,.XML',
  showList: false,
  onChange: (file: any) => {
    let type = file.name.substring(file.name.lastIndexOf('.') + 1);
    if (type !== 'xml' && type !== 'XML') {
      showFailedMessage(traduction('FILE_FORMAT_ERROR'));
      return false;
    } else if ((file.size as any) > 1024 * 1024) {
      showFailedMessage(traduction('COMMON_UPLOAD_FILE_MORN_1M_ERROR'));
      return false;
    }
    const formData = new FormData();
    formData.append('imgfile', file.raw, file.name);
    uploadLdapFile(formData).then(() => {
      uploadLicense(file.name).then(
        () => {
          init();
          showSuccessMessage();
        },
        (error: any) => {
          const errorCode = error?.data?.error?.[0]?.code;
          if (errorCode) {
            const errorMsg = getErrorTranslate(errorCode);
            showFailedMessage(errorMsg);
          } else {
            showFailedMessage();
          }
        },
      );
    });
    return true;
  },
});

const tableData = reactive({
  data: [
    {
      name: '1',
      state: '',
      value: '',
      validDate: '',
      index: 1,
    },
  ],
});

const total = ref(0);

interface IdataItem {
  name: string;
  state: string;
  value: string;
  validDate: string;
  index: number;
}

interface AlarmInfo {
  FileState: string;
  ProductESNMatchState: string;
  ProductESNValidState: string;
  ProductVersionMatchState: string;
  RemainCommissioningDay: number;
  RemainGraceDay: number;
}

function setLicenseType(licenseTypeParams: string, data: any) {
  let licenseType = licenseTypeParams;
  switch (licenseType) {
    case 'Commercial':
      licenseType = traduction('LICENSE_TYPE_COMMERCIAL');
      break;
    case 'Demo':
      licenseType = traduction('LICENSE_STATUS_COMMISSION');
      break;
    case 'Trial':
      licenseType = traduction('LICENSE_TYPE_TRY');
      break;
    default:
      licenseType = traduction('LICENSE_STATUS_UNKNOWN');
      break;
  }
  leftBasicInformation.data.push({
    label: traduction('LICENSE_TYPE'),
    value: licenseType,
  });
  let licenseClass = data.LicenseClass;
  if (licenseClass === 'Advanced') {
    licenseClass = traduction('LICENSE_LEVEL_TIP');
  }
  leftBasicInformation.data.push({
    label: traduction('LICENSE_LEVEL'),
    value: licenseClass,
  });
}
function setTableData(licenseInfo: any, validDateParams: string, data: any) {
  let validDate = validDateParams;
  const featureKey = licenseInfo.KeyInfo.FeatureKey ? licenseInfo.KeyInfo.FeatureKey.filter((item: any) => item.Name.indexOf('accelerator') === -1 || item.Value !== 0) : [];
  tableData.data = [];
  featureKey.forEach(
    (item: { ValidDate: string; State: any; Name: any; Value: any }, index: number) => {
      if (item.ValidDate !== '' && validDate === '') {
        validDate = item.ValidDate;
      }
      let state = '';
      switch (item.State) {
        case 'N/A':
          state = '--';
          break;
        case 'Normal':
          state = traduction('LICENSE_STATUS_NORMAL');
          break;
        case 'Commissioning':
          state = traduction('LICENSE_STATUS_COMMISSION');
          break;
        case 'Default':
          state = traduction('LICENSE_STATUS_DEFAULT');
          break;
        case 'GracePeriod': {
          const remainGraceDay = data.AlarmInfo.RemainGraceDay;
          const grace = traduction('LICENSE_STATUS_GRACE');
          const day = traduction('LICENSE_DAY');
          const day01 = traduction('LICENSE_DAY01');
          state = `${grace}${day}${remainGraceDay}${day01}`;
          break;
        }
        case 'Emergency':
          state = traduction('LICENSE_STATUS_EMERGENCY');
          break;
        default:
          state = '--';
      }

      const temp = {};
      temp['name'] = item.Name;
      temp['state'] = state;
      temp['value'] = item.Value;
      const _validate =
        item.ValidDate === 'PERMANENT' ? traduction('LICENSE_PERMANENT') : item.ValidDate;
      temp['validDate'] = _validate;
      temp['index'] = index + 1;
      tableData.data.push(temp as IdataItem);
    },
  );
  total.value = tableData.data.length;
  return validDate;
}
function setValidDate(licenseInfo: any, validDateParams: string) {
  let validDate = validDateParams;
  let flag = false;
  for (const item of licenseInfo.SaleInfo.OfferingProduct.SaleItem) {
    const featureKeys = item.FeatureKey;
    for (const subItem of featureKeys) {
      if (subItem.ValidDate !== '') {
        validDate = subItem.ValidDate;
        flag = true;
        break;
      }
    }
    if (flag) {
      break;
    }
  }
  return validDate;
}
function init() {
  loading(true);
  findLicenseInfo().then((resp: any) => {
    const data = resp.data;
    isInvalid.value = false;
    esnValue.value = data?.DeviceESN ? data?.DeviceESN : '- -';
    // 失效码（revoketicket）（不为空才显示）
    invalidCodeVal.value = data?.RevokeTicket;
    const licenseInfo = data?.LicenseInfo;
    // 基本信息
    const generalInfo = licenseInfo?.GeneralInfo;
    leftBasicInformation.data = [];
    leftBasicInformation.data.push({
      label: traduction('LICENSE_SN'),
      value: generalInfo?.LSN,
    });
    let licenseType = generalInfo?.LicenseType;
    if (licenseType) {
      setLicenseType(licenseType, data);
    }
    /**
     * 新增逻辑，先搜索SaleInfo，如果validDate为空字符串，则继续搜索KeyInfo
     * 直到找到第一个有效的截止日期位置，否则就显示空,许可证截止日期可能有多个有效值，但都是相同的，因此只需要获取第一个有效的即可
     */
    let validDate = '';
    // 先查KeyInfo,如果查不到有效值再查 SaleInfo.
    if (licenseInfo && licenseInfo?.KeyInfo) {
      validDate = setTableData(licenseInfo, validDate, data);
      // 如查不到有效值，则查SaleInfo
      if (validDate === '' && licenseInfo?.SaleInfo?.OfferingProduct?.SaleItem) {
        validDate = setValidDate(licenseInfo, validDate);
      }
      if (validDate === 'PERMANENT') {
        validDate = traduction('LICENSE_PERMANENT');
      }
      leftBasicInformation.data.push({
        label: traduction('LICENSE_EXPIRATION'),
        value: validDate,
      });
    }
    headInit(data);
  });
}
interface IheadType {
  InstalledStatus: string;
  AlarmInfo: AlarmInfo;
  LicenseStatus: string;
  RevokeTicket: string;
}
function setLicenseStatus(licenseStatus: string, data: IheadType) {
  switch (licenseStatus) {
    case 'N/A':
      licenseStatusValue.value = traduction('LICENSE_STATUS_UNKNOWN');
      break;
    case 'Default':
      licenseStatusValue.value = traduction('LICENSE_STATUS_DEFAULT');
      break;
    case 'Normal':
      licenseStatusValue.value = traduction('LICENSE_STATUS_NORMAL');
      break;
    case 'Commissioning': {
      const remainCommissioningDay = data.AlarmInfo.RemainCommissioningDay;
      licenseStatusValue.value =
        traduction('LICENSE_STATUS_COMMISSION') +
        traduction('LICENSE_DAY') +
        remainCommissioningDay +
        traduction('LICENSE_DAY01');
      break;
    }
    case 'GracePeriod': {
      const remainGraceDay = data.AlarmInfo.RemainGraceDay;
      licenseStatusValue.value =
        traduction('LICENSE_STATUS_GRACE') +
        traduction('LICENSE_DAY') +
        remainGraceDay +
        traduction('LICENSE_DAY01');
      break;
    }
    case 'Emergency':
      licenseStatusValue.value = traduction('LICENSE_STATUS_EMERGENCY');
      break;
    default:
      break;
  }
}
function headInit(data: IheadType) {
  const installedStatus = data?.InstalledStatus;
  const fileState = data?.AlarmInfo?.FileState;
  let licenseStatus = data?.LicenseStatus;
  if (installedStatus === 'NotInstalled' && !['Incorrect', 'Normal'].includes(fileState)) {
    isInstallation.value = false;
  } else {
    isInstallation.value = true;
  }
  if (installedStatus === 'NotInstalled' && fileState === 'Incorrect') {
    isDelBtn.value = true;
  } else {
    isExportBtn.value = false;
    isInvalidBtn.value = false;
  }

  if (installedStatus === 'Installed' && fileState === 'Normal') {
    isExportBtn.value = true;
    isDelBtn.value = true;
    if (licenseStatus === 'Normal' || licenseStatus === 'Commissioning') {
      isInvalidBtn.value = true;
    }
  }
  /*
   * 获取许可证的状态
   * 当状态为调测（Commissioning）/宽限（GracePeriod）时，需要显示剩余的天
   */
  setLicenseStatus(licenseStatus, data);
  // 失效码
  const revokeTicket = data.RevokeTicket;
  const first = {
    label: traduction('LICENSE_STATUS'),
    value: licenseStatusValue.value,
  };
  if (revokeTicket !== '') {
    isInvalid.value = true;
    first['revoke'] = true;
    first['revokeLabel'] = traduction('LICENSE_REVOKE_CODE');
    first['revokeValue'] = invalidCodeVal.value;
  }
  leftBasicInformation.data.unshift(first);
  loading(false);
}

function licenseDel() {
  if (isSystemLock.value) {
    return;
  }
  dialogConfig.id = 'licenseDelModal';
  dialogConfig.title = traduction('COMMON_CONFIRM');
  dialogConfig.content =
    traduction('LICENSE_DELETE_LICENSE') + traduction('LICENSE_RESTORED_DELETED');
  dialogRef.value.show();
}
function licenseInvalid() {
  if (isSystemLock.value) {
    return;
  }
  dialogConfig.id = 'licenseInvalidModal';
  dialogConfig.title = traduction('LICENSE_REVOKE');
  dialogConfig.content = traduction('LICENSE_REVOKE_LICENSE') + traduction('LICENSE_NOT_RESTORED');
  dialogRef.value.show();
}
function downloadFile() {
  download({}).then((res: any) => {
    const response = res.data;
    downloadData(response.url).then((rsp: any) => {
      const fileName = rsp.headers['content-disposition'].split('=')[1];
      downloadFileWithResponse(rsp.data, fileName);
    });
  });
}

function downloadData(path: string) {
  const data = {
    Path: path,
    TransferProtocol: 'HTTPS',
  };
  return $http.post(UI_REST_GENERALDOWNLOAD, data, { responseType: 'blob' });
}

function closeModal(reason: boolean) {
  if (reason) {
    loading(true);
    if (dialogConfig.id === 'licenseDelModal') {
      licenseDelService({})
        .then((resp: any) => {
          init();
          alertMessage('success', 'COMMON_SUCCESS');
        })
        .catch(err => {
          loading(false);
          alertMessage('error', getErrorMsg(err));
        });
    }
    if (dialogConfig.id === 'licenseInvalidModal') {
      licenseInvalidService({})
        .then((resp: any) => {
          init();
          alertMessage('success', 'COMMON_SUCCESS');
        })
        .catch(err => {
          loading(false);
          alertMessage('error', getErrorMsg(err));
        });
    }
  }
  dialogRef.value.hide();
}
function getErrorMsg(error: any) {
  const errorId = getMessageId(error.data)[0]?.code as string;
  const errorMsg = getErrorTranslate(errorId) || 'COMMON_FAILED';
  return errorMsg;
}
function setRowClass(item: any) {
  const { row } = item;
  return `advance-row-${row.index}`;
}
onMounted(() => {
  init();
});
</script>

<style lang="scss" scoped>
#license {
  background-color: var(--o-bg-color-base);
  border-radius: 4px;
  padding: 24px;
  margin-right: 24px;
  
  .license-title {
    font-size: 16px;
    color: var(--o-text-color-primary);
    line-height: 24px;
    margin-bottom: 16px;
    font-weight: bold;
  }
  .esn-value {
    margin-top: 16px;
    .esn-title {
      color: var(--o-text-color-secondary);
      margin-right: 24px;
    }
  }
  .no-license {
    height: 200px;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    > div {
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;
      &#invalidCode {
        width: 100%;
        flex-direction: row;
        justify-content: flex-start;
        margin-bottom: 16px;
      }
    }
  }
  .advanced {
    margin-top: 32px;
    position: relative;
    > p {
      font-size: 16px;
      color: var(--o-text-color-primary);
      line-height: 24px;
      margin-bottom: 16px;
      font-weight: bold;
    }
  }
  .pagination {
    .layout-patination {
      margin-left: 0;
    }
  }
  .license-card {
    padding: 0 24px 16px;
    margin-top: 16px;
    background-color: var(--o-bg-color-light);
    border-radius: var(--o-border-radius);
    #topDiv {
      height: 56px;
      line-height: 56px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      .license-info {
        font-size: 16px;
        color: var(--o-text-color-primary);
        letter-spacing: 0;
        line-height: 24px;
        font-weight: bold;
      }
      #isBtnGroup {
        display: flex;
        .tab-btn {
          margin-left: 24px;
          cursor: pointer;
          > span {
            display: inline-block;
            width: 16px;
            height: 16px;
            overflow: hidden;
            vertical-align: sub;
            line-height: 16px;
            img {
              vertical-align: sub;
              margin-right: 8px;
              position: relative;
            }
          }
          &:hover {
            color: var(--o-color-primary-secondary);
            > span {
              img {
                left: -20px;
                filter: drop-shadow(20px 0 0 var(--o-color-primary-secondary));
              }
            }
          }
        }
      }
    }
    .license-span {
      color: var(--o-text-color-primary);
    }
    .license-span-0 {
      display: inline-block;
      padding: 0 20px;
      background-color: var(--o-color-success);
      border-radius: 2px;
      color: #fff;
      height: 16px;
      line-height: 16px;
      &.revoke {
        background-color: var(--o-color-warning);
      }
    }
    .revoke-code {
      margin-left: 16px;
      color: var(--o-text-color-tertiary);
    }
  }
  .comon-state {
    display: inline-block;
    background-color: var(--o-text-color-tertiary);
    color: #fff;
    height: 16px;
    line-height: 16px;
    padding: 0 14px;
    border-radius: var(--i-button-border-radius);
    &.enable {
      background-color: var(--o-color-success);
    }
  }
  .el-form-item {
    margin-bottom: 0;
  }
  .no-license-text {
    color: var(--o-text-color-tertiary);
  }
}
</style>
