<template>
  <span>
    <span @click="getCertificate">
      <slot></slot>
    </span>
  </span>
</template>

<script>
import util from 'eoss-ui/src/utils/util';
import caPlugin from './plugin.js';

export default {
  name: 'EsCaLogin',
  props: {
    installPath: String,
    caModel: {
      type: String,
      required: true
    }, // CA登录方式，JIDA-吉大正元，SHU_GUANG-曙光，SICHUAN-四川
    identifyingId: {
      type: String,
      default() {
        return util.uuid(12);
      }
    },
    dllnames: {
      type: Array,
      default: () => [
        'L3Vzci9saWI2NC9saWJTS0ZBUEkuc28=',
        'bGliU0tGQVBJLWFybTY0LnNv',
        'L3Vzci9saWIvYWFyY2g2NC1saW51eC1nbnUvbGliU0tGQVBJLWFybTY0LnNv',
        'L3Vzci9saWIvbGliU0tGQVBJLnNv',
        'U0tGQVBJMzAwOTIuZGxs',
        'bGliU0tGQVBJLnNv',
        'L29wdC9oYWl0YWkvbGliL2xpYlNLRkFQSS5zbw==',
        'U0tGQVBJNDAwOTcuZGxs'
      ]
    },
    dllname: {
      type: Array,
      default: () => []
    },
    success: Function,
    // 是否显示证书选择框，默认为true
    showSelect: Boolean
  },
  data() {
    return {
      userList: [],
      signedData: '', //证书原文
      b64originData: '', //签名原文
      b64SignData: '', //签名结果
      idCard: '',
      certId: ''
    };
  },
  computed: {
    param() {
      // 生成不重复的 DLL 名称列表
      const dllnames = Array.from(new Set(this.dllnames.concat(this.dllname)));

      return `<?xml version="1.0" encoding="utf-8"?>
      <authinfo>
        <liblist>
        ${dllnames
          .map(
            (dllname) =>
              `<lib type="SKF" version="1.0" dllname="${dllname}"><algid val="SHA1" sm2_hashalg="SM3" /></lib>`
          )
          .join('')}
        </liblist>
      </authinfo>`;
    }
  },
  created() {
    this.init();
  },
  mounted() {},
  methods: {
    init() {
      if (!window.PNXClient) {
        // 创建 object 元素
        const pnxClientElement = document.createElement('object');
        pnxClientElement.classid = 'clsid:9DD991F7-6FB0-4004-95A4-0A55006A8C42';
        pnxClientElement.width = '0';
        pnxClientElement.height = '0';
        pnxClientElement.id = 'PNXClient';
        pnxClientElement.style.position = 'absolute';
        document.body.appendChild(pnxClientElement);
      }
    },
    getCertificate() {
      this.$emit('click');
      // 检查 PNXClient 是否存在
      if (!window.PNXClient) {
        this.$message.error('控件加载失败，请刷新页面重试！');
        this.$emit('error', { code: 0, msg: '控件加载失败，请刷新页面重试！' });
        return;
      }
      switch (this.caModel) {
        //吉大正元:
        case 'JIDA':
          try {
            caPlugin.getVersion();
          } catch (e) {
            if (this.installPath) {
              this.$confirm('未安装控件，请进行安装控件！', '控件下载', {
                confirmButtonText: '下载',
                cancelButtonText: '取消',
                type: 'warning'
              })
                .then(() => {
                  util.downloadFile(this.installPath);
                })
                .catch(() => {});
            } else {
              this.$message.error('未安装控件，请进行安装控件！');
            }
            this.$emit('error', {
              type: 1,
              msg: '未安装控件，请进行安装控件！'
            });
            return;
          }
          try {
            // 清除之前的过滤器
            caPlugin.clearFilter();
            // 初始化vctk控件
            caPlugin.initialize('', this.param);
            // 控制证书为一个时,并且不显示选择框时，不弹出证书选择框
            !this.showSelect && caPlugin.setChooseSingleCert(1);

            // 生成签名信息
            this.signedData = caPlugin.p7SignString(
              this.identifyingId,
              true,
              true
            );

            //获取错误码
            const errorCode = Number(caPlugin.getLastError());
            if (errorCode !== 0) {
              if (errorCode === 3758096386 || errorCode === 2148532334) {
                this.$message.error('用户取消操作！');
                this.$emit('error', { code: 52, msg: '用户取消操作！' });
                return;
              } else if (errorCode === -536870815 || errorCode === 3758096481) {
                this.$message.error(
                  '没有找到有效的证书，如果使用的是KEY，请确认已经插入key！'
                );
                this.$emit('error', {
                  type: 2,
                  msg: '没有找到有效的证书，如果使用的是KEY，请确认已经插入key！'
                });
                return;
              } else {
                const msg = caPlugin.getLastErrorMessage();
                this.$message.error(msg);
                this.$emit('error', { code: 3, msg });
                return;
              }
            }
            this.success && this.success(this.signedData);
            return this.signedData;
          } catch (error) {
            // 捕获其他可能的异常
            this.$message.error(`操作失败: ${error.message}`);
            this.$emit('error', { code: 4, msg: error.message });
          }
          break;
        //曙光:
        case 'SHU_GUANG':
          caPlugin
            .getMessage({ action: 'SOF_GetUserList' })
            .then((res) => {
              const { retCode, retMsg, retValue } = res;
              if (!retValue || retCode !== 0) {
                this.$message.error(
                  retCode !== 0 ? retMsg : '未找到证书，请插入证书UKEY！'
                );
                this.$emit('error', {
                  type: 2,
                  msg: retCode !== 0 ? retMsg : '未找到证书，请插入证书UKEY！'
                });
                return;
              }
              const userList = retValue.split('&&&');
              if (userList.length === 1 && !this.showSelect) {
                //如果只有一个证书,并且不显示选择框时，直接获取证书信息
                this.certId = userList[0].split('||')[1];
                this.getCertInfo(this.certId);
              } else {
                // 如果有多个证书，弹出选择框
                this.userList = userList.map((item) => {
                  const [name, certId] = item.split('||');
                  return { label: name, value: certId };
                });
                this.$prompt('', '证书选择', {
                  confirmButtonText: '确定',
                  cancelButtonText: '取消',
                  inputPattern: /^.+$/,
                  inputErrorMessage: '请选择证书！',
                  selectData: this.userList
                })
                  .then((res) => {
                    this.certId = res.value;
                    this.getCertInfo(this.certId);
                  })
                  .catch(() => {
                    this.$emit('error', { code: 52, msg: '用户取消操作！' });
                  });
              }
            })
            .catch((err) => {
              if (this.installPath) {
                this.$confirm(
                  '请检查是否安装并启用证书助手控件！',
                  '控件下载',
                  {
                    confirmButtonText: '下载',
                    cancelButtonText: '取消',
                    type: 'warning'
                  }
                )
                  .then(() => {
                    util.downloadFile(this.installPath);
                  })
                  .catch(() => {});
              } else {
                this.$message.error('请检查是否安装并启用证书助手控件！');
              }
              this.$emit('error', {
                type: 1,
                msg: '请检查是否安装并启用证书助手控件！'
              });
            });
          break;
        //四川:
        case 'SICHUAN':
          this.$message.warning('四川CA登录方式对接中！');
          this.$emit('error');
          break;
      }
    },
    getCertInfo(name) {
      caPlugin
        .getMessage({ action: 'SOF_ExportUserCert', params: [name] })
        .then((res) => {
          const { retCode, retMsg, retValue } = res;
          if (retCode !== 0) {
            this.$message.error(retMsg);
            this.$emit('error', { code: retCode, msg: retMsg });
            return;
          }
          //设置证书原文
          this.signedData = retValue
            .replace('-----BEGIN CERTIFICATE-----', '')
            .replace('-----END CERTIFICATE-----', '');
          caPlugin
            .getMessage({
              action: 'SOF_GetCertInfo',
              params: [retValue, 'SGD_CERT_SUBJECT_SN']
            })
            .then((res) => {
              const { retCode, retMsg, retValue } = res;
              if (retCode !== 0) {
                this.$message.error(retMsg);
                this.$emit('error', { code: retCode, msg: retMsg });
                return;
              }
              this.idCard = caPlugin.base64Decode(retValue);
              caPlugin
                .getMessage({
                  action: 'SOF_GenRandom',
                  params: [16]
                })
                .then((res) => {
                  const { retCode, retMsg, retValue } = res;
                  if (retCode !== 0) {
                    this.$message.error(retMsg);
                    this.$emit('error', { code: retCode, msg: retMsg });
                    return;
                  }
                  this.b64originData = retValue + this.identifyingId;
                  caPlugin
                    .getMessage({
                      action: 'SOF_SignData',
                      params: [
                        this.certId,
                        caPlugin.base64Encode(this.b64originData)
                      ]
                    })
                    .then((res) => {
                      const { retCode, retMsg, retValue } = res;
                      if (retCode !== 0) {
                        if (retCode === 184550659) {
                          this.cerLogin();
                        } else {
                          this.$message.error(retMsg);
                          this.$emit('error', { code: retCode, msg: retMsg });
                        }
                        return;
                      }
                      this.b64SignData = retValue;
                      this.success &&
                        this.success({
                          identifyingId: this.identifyingId,
                          signedData: this.signedData, //证书原文
                          b64originData: this.b64originData, //签名原文
                          b64SignData: this.b64SignData, //签名结果
                          idCard: this.idCard,
                          certId: this.certId
                        });
                    })
                    .catch((err) => {
                      this.$emit('error', { code: 5, msg: err });
                    });
                })
                .catch((err) => {
                  this.$emit('error', { code: 6, msg: err });
                });
            })
            .catch((err) => {
              this.$emit('error', { code: 7, msg: err });
            });
        })
        .catch((err) => {
          this.$emit('error', { code: 8, msg: err });
        });
    },
    cerLogin(title = '提示') {
      this.$prompt('输入密码', title, {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputPattern: /^[[\x21-\x7E]{6,16}$/,
        inputErrorMessage: '请输入密码'
      })
        .then(({ value }) => {
          caPlugin
            .getMessage({
              action: 'SOF_Login',
              params: [this.certId, value]
            })
            .then((res) => {
              const { retCode, retMsg, retValue } = res;
              if (retCode !== 0 || retValue === false) {
                if (retValue === false) {
                  caPlugin
                    .getMessage({
                      action: 'SOF_GetPinRetryCount',
                      params: [this.certId]
                    })
                    .then((res) => {
                      const { retValue } = res;
                      this.cerLogin(
                        `登录失败！剩余口令重试次数：${retValue}次`
                      );
                    });
                  return;
                }
                this.$message.error(retMsg);
                this.$emit('error', { code: retCode, msg: retMsg });
                return;
              }
              caPlugin
                .getMessage({
                  action: 'SOF_SignData',
                  params: [
                    this.certId,
                    caPlugin.base64Encode(this.b64originData)
                  ]
                })
                .then((res) => {
                  const { retCode, retMsg, retValue } = res;
                  if (retCode !== 0) {
                    if (retCode === 184550659) {
                      this.cerLogin();
                    } else {
                      this.$message.error(retMsg);
                      this.$emit('error', { code: retCode, msg: retMsg });
                    }
                    return;
                  }
                  this.b64SignData = retValue;
                  this.success &&
                    this.success({
                      identifyingId: this.identifyingId,
                      signedData: this.signedData, //证书原文
                      b64originData: this.b64originData, //签名原文
                      b64SignData: this.b64SignData, //签名结果
                      idCard: this.idCard,
                      certId: this.certId
                    });
                })
                .catch((err) => {
                  this.$emit('error', { code: 9, msg: err });
                });
            })
            .catch(() => {
              this.$emit('error', { code: 10, msg: err });
            });
        })
        .catch(() => {
          this.$emit('error', { code: 11, msg: err });
        });
    }
  }
};
</script>

<style scoped></style>
