<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue';
import { getLoginInfo } from '@/utils/common-api';
// 组件引用
import LangSwitch from '@/components/LangSwitch/LangSwitch.vue';
import SecurityNotice from './SecurityNotice/SecurityNotice.vue';
import LoginDetails from './LoginDetails/LoginDetails.vue';
import { getStoreData, setStoreData } from '@/utils/composition';
import { LOGIN_TYPE } from '@/model/base-enum';
import { getPrivils, getSessions, getTwoFactor, getV1Info, getDiyImgUrl } from './login-service';
import { AxiosResponse } from 'axios';
import { traduction } from '@/utils/language';
import { getSsoErrorMsg, openOnlineHelp, escapeHeader } from '@/utils/utils';
import { useRouter } from 'vue-router';
import {
  getLogoImage,
  getBackgroundImage,
  saveSessionData,
  saveUserPermission,
} from '@/utils/common-service';

const $router = useRouter();
// 安全公告内容容器的最大高度，内容超出最大高度时，显示tip信息，否则不显示tip信息
const bgImg = ref(null);
const securityRef = ref();

// 获取定制信息
const ptcInfo = localStorage.getItem('ptc');
const ptcInfoJson = JSON.parse(ptcInfo as string);
const pageInfo = reactive({
  userNameLen: 16,
  passwordLen: 20,
  CopyRight: '',
  FQDN: '',
  ProductName: '',
  SecurityBanner: '',
  SoftwareName: '',
  KerberosDomain: undefined,
  showCode: false,
  afterHide: 0,
  lockDuration: 300,
  ldapDomains: [],
  qrCode: '',
  size: '',
  position: '',
  logo: '',
});

let sessionInfo = reactive({});
const loginType = ref(LOGIN_TYPE.undetermined);
const loginStateMsg = ref('');
const retryCount = ref(0);
const completeState = ref(false);
const restartInfo = reactive({});
const diyImgSrc = ref('');

// 只要是跳到了登录页，我们就认为是会话已经被注销了，有效的Tabs个数归0
localStorage.setItem('tabs', JSON.stringify(0));
// 登录页重置当前tab页的超时状态
setStoreData('glob', 'isTimeOut', false);

// 登录时查询相关的页面数据
getLoginInfo().then(res => {
  const data = res.data;
  pageInfo.CopyRight = data.Copyright ? `Copyright © ${data.Copyright}` : '';
  pageInfo.FQDN = data.FQDN;
  pageInfo.ProductName = data.ProductName;
  pageInfo.SoftwareName = data.SoftwareName;
  pageInfo.showCode = data.QRCodeState !== 'Hide';
  pageInfo.KerberosDomain = data.KerberosDomain;
  pageInfo.SecurityBanner = data.SecurityBanner;
  pageInfo.lockDuration = data.AccountLockoutDuration;
  pageInfo.ldapDomains = data.LDAPDomain;
  setStoreData('loct', 'smsName', data.SmsName || 'iBMA');
  setStoreData('loct', 'pName', data.ProductName);
  setStoreData('loct', 'sn', data.SoftwareName);

  // 采用调用组件方法的形式来显示或隐藏安全公告（因为公告为空值与组件的默认空值一致时会导致无法触发组件的watch事件）
  if (data.SecurityBanner !== null) {
    securityRef.value.show();
  } else {
    securityRef.value.hide();
  }

  // 定制化信息
  resetPageInfoFromPtcInfo();
});

getDiyImgUrl().then(() => {
  diyImgSrc.value = `${window.location.origin}/volcanoLogo.svg`;
}).catch(() => {
  diyImgSrc.value = '';
});

function resetPageInfoFromPtcInfo() {
  if (ptcInfoJson) {
    addCustomizeKey('copyright', 'CopyRight');
    addCustomizeKey('notice', 'SecurityBanner');
    addCustomizeKey('software', 'SoftwareName');
    addCustomizeKey('qrEnable', 'showCode');
    addCustomizeKey('qrCode', 'qrCode');
    addCustomizeKey('size', 'size');
    addCustomizeKey('position', 'position');
    addCustomizeKey('logo', 'logo');
  }
}

function addCustomizeKey(customKey: string, pageInfoKey: string) {
  if (ptcInfoJson[customKey] !== undefined && ptcInfoJson[customKey] !== '') {
    pageInfo[pageInfoKey] = ptcInfoJson[customKey];
  }
}

/** 背景图，Logo定制
 *  图片优先级
 *  0：最高 web定制工具预览功能
 *  1：其次 H3C定制风格
 *  2：最低 系统默认的，hpm、白牌包定制的图片
 */
const cardMode = ref('');
const webStyle = getStoreData('glob', 'webStyle');
let backgrounUrl = ref('');
let logoUrl = ref('');

setImageUrl();

function setImageUrl() {
  // 获取登录页背景图和Logo
  backgrounUrl.value = getBackgroundImage();
  logoUrl.value = getLogoImage();
}

function getDefaultBackImg() {
  backgrounUrl.value = '/image/login.jpg';
}

// 定制Position
if (ptcInfoJson && ptcInfoJson.size === 'large') {
  cardMode.value = 'large';
}

function goHome() {
  $router.push('/navigate/home');
}

// 检查是否是SSO登录
function checkSSO() {
  const ssoLoginInfo = localStorage.getItem('ssoLoginInfo');
  if (ssoLoginInfo !== null && ssoLoginInfo !== '') {
    const ssoLoctJson = JSON.parse(ssoLoginInfo);
    setStoreData('loct', 'loginType', LOGIN_TYPE.sso);
    loginType.value = LOGIN_TYPE.sso;
    loginStateMsg.value = traduction('LOGIN_WAY_SSO');
    localStorage.removeItem('ssoLoginInfo');

    const stateCode = Number(ssoLoctJson.stateCode);
    if (stateCode === 0) {
      getSessionAndPrivil(LOGIN_TYPE.sso, ssoLoctJson.token, ssoLoctJson.index);
    } else {
      loginStateMsg.value = traduction(getSsoErrorMsg(stateCode));
      setTimeout(() => {
        loginType.value = LOGIN_TYPE.common;
        loginStateMsg.value = '';
      }, 10000);
    }
  } else {
    if (localStorage.getItem('ssoError')) {
      return;
    }
    checkTwofac();
  }
}

function checkTwofac() {
  /**
   * 双因素状态 stateCode
   * 0: 正常账户密码登录
   * 1：双因素登录状态
   * 4：这个状态很特殊，因为双因素从开启到生效预计3秒时间，在3秒内去请求该接口会返回4的状态，因此当遇到状态为4时，需要重试5次
   */
  retryCount.value++;
  getTwoFactor().then(
    (handleRes: AxiosResponse) => {
      const data = handleRes.data;
      loginType.value = LOGIN_TYPE.twoFactor;

      // 双因素已登出
      let stateCode = data.stateCode;
      if (stateCode !== 0 && getStoreData('loct', 'isExited')) {
        completeState.value = true;
        loginStateMsg.value = traduction('LOGIN_TWOFATOR_STATE_3');
        return;
      }
      errorHandle(stateCode, data);
    },
    () => {
      loginType.value = LOGIN_TYPE.common;
      loginStateMsg.value = '';
    },
  );
}

// 双因素登录错误处理
function errorHandle(stateCode: number, res: any) {
  switch (stateCode) {
    case 0:
      // 普通账户密码登录
      loginType.value = LOGIN_TYPE.common;
      loginStateMsg.value = '';
      break;
    case 1:
      loginStateMsg.value = traduction('LOGIN_WAY_TWOFACTOR');
      getSessionAndPrivil(LOGIN_TYPE.twoFactor, res.token, res.Session);
      break;
    case 4:
      loginStateMsg.value = traduction('LOGIN_WAY_TWOFACTOR');
      if (retryCount.value >= 5) {
        loginStateMsg.value = traduction('LOGIN_TWOFATOR_STATE_4');
        completeState.value = true;
      } else {
        setTimeout(checkTwofac, 1000);
      }
      break;
    case 2:
    case 3:
    case 5:
    case 6:
    case 7:
      completeState.value = true;
      loginStateMsg.value = traduction('LOGIN_TWOFATOR_STATE_' + stateCode);
      break;
    default:
      loginType.value = LOGIN_TYPE.common;
      loginStateMsg.value = '';
  }
}

// SSO跳转登录和双因素登录查询成功时，查询Session信息和权限信息
function getSessionAndPrivil(loginTyle: number, token: string, sessionId: string) {
  const headers = {
    'X-CSRF-Token': escapeHeader(token),
  };
  getSessions(headers).then((res: AxiosResponse) => {
    const sInfo = (res.data as any)?.Members.filter(
      (item: { SessionID: string; Role: string; [key: string]: any }) => {
        return item.SessionID === sessionId;
      },
    )[0];
    if (sInfo) {
      setStoreData('loct', 'to', token);
      const sessionData = {
        Role: sInfo.Role,
        SessionID: sInfo.SessionID,
        UserID: sInfo.UserID,
        UserName: sInfo.UserName,
        IP: sInfo.IPAddress,
        LoginTime: sInfo.LoginTime,
      };
      getPrivils().then((privil: any) => {
        setStoreData('loct', 'loginType', loginTyle);
        if (loginTyle === LOGIN_TYPE.twoFactor) {
          setStoreData('loct', 'twofac', true);
          setStoreData('loct', 'nopwd', true);
        }
        saveSessionData(sessionData);
        // sInfo.Role这里返回的是字符串，Login接口返回的Session的Role是个数组
        saveUserPermission(sInfo.Role, privil.data.Members);
        goHome();
      });
    }
  });
}

// 打开帮助文档
function openHelpDocument() {
  const route = $router.currentRoute.value.fullPath.split('/').pop() || '';
  openOnlineHelp(route);
}

// 查询固件升级重启
function restartService() {
  const firmwareToLogin = localStorage.getItem('firmwareToLogin');
  if (firmwareToLogin && firmwareToLogin === 'true') {
    setTimerV1();
  }
}

function setTimerV1() {
  restartInfo['reset'] = true;
  restartInfo['errorMessage'] = traduction('IBMC_LOGIN_PLEASE_AGAIN');
  // 定时轮询，检测重启状态
  setTimeout(() => {
    let timer: any = null;
    timer = setInterval(() => {
      getV1Info()
        .then(res => {
          if (!res.data) {
            return;
          }
          if (timer !== null) {
            restartInfo['reset'] = false;
            localStorage.setItem('firmwareToLogin', JSON.stringify(false));
            clearInterval(timer);
            window.location.reload();
          }
        })
        .catch(error => {
          restartInfo['reset'] = true;
          restartInfo['errorMessage'] = traduction('IBMC_LOGIN_PLEASE_AGAIN');
        });
    }, 5000);
  }, 3000);
}

onMounted(() => {
  /**
   * 登录流程
   * 1. 查询是否是SSO登录
   * 2. 查询是否是双因素登录
   * 3. 以上都不是则是普通账号密码登录
   */
  checkSSO();
  restartService();
  // 处理sso跳转kvm错误
  if (localStorage.getItem('ssoError')) {
    loginType.value = LOGIN_TYPE.sso;
    loginStateMsg.value = traduction(getSsoErrorMsg(0));
    setTimeout(() => {
      loginType.value = LOGIN_TYPE.common;
      loginStateMsg.value = '';
    }, 10000);
    localStorage.removeItem('ssoError');
    sessionStorage.removeItem('kvmHtml5Info');
    localStorage.removeItem('kvmHtml5Info');
  }
});
</script>

<template>
  <div id="login-container">
    <!-- 背景图 -->
    <div class="login-left-img">
      <img ref="bgImg" class="loginBgImg" :src="backgrounUrl" @error="getDefaultBackImg" />
    </div>
    <img v-if="diyImgSrc" class="diy-img" :src="diyImgSrc" />
    <!-- 语言切换 -->
    <div id="langContainer" class="lang-container">
      <LangSwitch :flag="true" />
      <el-tooltip :content="$t('REMOTE_HELP_DOCUMENT')" trigger-keys>
        <span id="loginHelpIcon" class="icon-help" @click="openHelpDocument()"></span>
      </el-tooltip>
    </div>

    <!-- 安全公告 -->
    <SecurityNotice ref="securityRef" :content="pageInfo.SecurityBanner" :card-mode="cardMode" />

    <!-- 登录详情 -->
    <LoginDetails
      :login-type="loginType"
      :session-info="sessionInfo"
      :state-message="loginStateMsg"
      :complete="completeState"
      :page-info="pageInfo"
      :restart-info="restartInfo"
    />

    <!-- 版权信息 -->
    <div id="loginCopyright" class="login-copyright" :class="{ large: cardMode === 'large' }">
      {{ pageInfo.CopyRight }}
    </div>
  </div>
</template>

<style lang="scss" scoped>
@import './login.scss';
</style>

<style lang="scss">
// 登录页的下拉框padding修改
.el-select-dropdown__item {
  padding-left: 15px;
  padding-right: 15px;
  max-width: 364px;
  .domain-item {
    width: 100%;
    font-size: $FONT-14;
    padding-left: 5px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}
.diy-img {
  display: block;
  position: relative;
  z-index: 1000;
  margin: 30px 0 0 30px;
  width: 196px;
  height: 56px;
}
</style>
