<!--
 * @Author: Mm
 * @Date: 2025-03-10 10:42:57
 * @LastEditors: Mm
 * @LastEditTime: 2026-03-19 14:22:19
 * 不写bug的程序员不是一个好程序员!
-->
<script lang="ts" setup>
import type { LoginAndRegisterParams, VbenFormSchema } from '@vben/common-ui';

import type { TenantResp } from '#/api';
import type { CaptchaResponse } from '#/api/core/captcha';

import { computed, onBeforeUnmount, onMounted, ref, useTemplateRef } from 'vue';

import { AuthenticationLogin, z } from '@vben/common-ui';
import { $t } from '@vben/locales';

import { omit } from 'lodash-es';

import { tenantList } from '#/api';
import { captchaImage } from '#/api/core/captcha';
import { useAuthStore } from '#/store';
import { Button, message } from 'ant-design-vue';
import { SafetyCertificateOutlined, ChromeFilled, CopyrightOutlined } from '@ant-design/icons-vue';
import OAuthLogin from './oauth-login.vue';
import { generateOriginalNum, pkiLogin } from '#/api';
defineOptions({ name: 'Login' });
import { useAccessStore, useUserStore } from '@vben/stores';
const accessStore = useAccessStore();
const userStore = useUserStore();

const authStore = useAuthStore();

const loginFormRef = useTemplateRef('loginFormRef');

const captchaInfo = ref<CaptchaResponse>({
  captchaEnabled: false,
  img: '',
  uuid: '',
});

async function loadCaptcha() {
  const resp = await captchaImage();
  if (resp.captchaEnabled) {
    resp.img = `data:image/png;base64,${resp.img}`;
  }
  captchaInfo.value = resp;
}

const tenantInfo = ref<TenantResp>({
  tenantEnabled: false,
  voList: [],
});

async function loadTenant() {
  const resp = await tenantList();
  tenantInfo.value = resp;
  // 选中第一个租户
  if (resp.tenantEnabled && resp.voList.length > 0) {
    const firstTenantId = resp.voList[0]!.tenantId;
    loginFormRef.value?.getFormApi().setFieldValue('tenantId', firstTenantId);
  }
}

onMounted(async () => {
  await Promise.all([loadCaptcha(), loadTenant()]);
});

const formSchema = computed((): VbenFormSchema[] => {
  return [
    {
      component: 'VbenSelect',
      componentProps: {
        class: 'bg-background h-[40px] focus:border-primary',
        contentClass: 'max-h-[256px] overflow-y-auto',
        options: tenantInfo.value.voList?.map((item) => ({
          label: item.companyName,
          value: item.tenantId,
        })),
        placeholder: $t('authentication.selectAccount'),
      },
      defaultValue: '000000',
      dependencies: {
        if: () => tenantInfo.value.tenantEnabled,
        // 这里大致上是watch的一个效果
        componentProps: (model) => {
          localStorage.setItem('__oauth_tenant_id', model?.tenantId ?? '000000');
          return {};
        },
        triggerFields: ['', 'tenantId'],
      },
      fieldName: 'tenantId',
      label: $t('authentication.selectAccount'),
      rules: z.string().min(1, { message: $t('authentication.selectAccount') }),
    },
    {
      component: 'VbenInput',
      componentProps: {
        class: 'focus:border-primary',
        placeholder: $t('authentication.usernameTip'),
      },
      defaultValue: '',
      fieldName: 'username',
      label: $t('authentication.username'),
      rules: z.string().min(1, { message: $t('authentication.usernameTip') }),
    },
    {
      component: 'VbenInputPassword',
      componentProps: {
        class: 'focus:border-primary',
        placeholder: $t('authentication.password'),
      },
      defaultValue: '',
      fieldName: 'password',
      label: $t('authentication.password'),
      rules: z.string().min(5, { message: $t('authentication.passwordTip') }),
    },
    {
      component: 'VbenInputCaptcha',
      componentProps: {
        captcha: captchaInfo.value.img,
        class: 'focus:border-primary',
        onCaptchaClick: loadCaptcha,
        placeholder: $t('authentication.code'),
      },
      dependencies: {
        if: () => captchaInfo.value.captchaEnabled,
        triggerFields: [''],
      },
      fieldName: 'code',
      label: $t('authentication.code'),
      rules: z.string().min(1, { message: $t('authentication.codeTip') }),
    },
  ];
});

async function handleAccountLogin(values: LoginAndRegisterParams) {
  try {
    const requestParam: any = omit(values, ['code']);
    // 验证码
    if (captchaInfo.value.captchaEnabled) {
      requestParam.code = values.code;
      requestParam.uuid = captchaInfo.value.uuid;
    }
    // 登录
    await authStore.authLogin(requestParam);
  } catch (error) {
    console.error(error);
    // 处理验证码错误
    if (error instanceof Error) {
      // 刷新验证码
      loginFormRef.value?.getFormApi().setFieldValue('code', '');
      await loadCaptcha();
    }
  }
}

// PKI登录
const isPki = ref(true);

// 参数说明：authContent：认证原文
const authContent = ref('');
// 参数说明：initParam：vctk控件初始化参数
const initParam: string =
  '<\?xml version="1.0" encoding="utf-8"\?><authinfo><liblist><lib type="SKF" version="1.0" dllname="L29wdC9HQVNTL2xpYlNLRi9saWJTS0ZfR0FfYXBpLnNv"><algid val="SHA1" sm2_hashalg="SM3" /></lib><lib type="SKF" version="1.0" dllname="R0FLRVlfU0tGLmRsbA=="><algid val="SHA1" sm2_hashalg="SM3" /></lib><lib type="CSP" version="1.0" dllname="ZVNhZmUgQ3J5cHRvZ3JhcGhpYyBTZXJ2aWNlIFByb3ZpZGVyIHYxLjA="><algid val="SHA1" sm2_hashalg="SHA1" /></lib><lib type="CSP" version="1.0" dllname="R0FTUyBDcnlwdG9ncmFwaGljIFNlcnZpY2UgUHJvdmlkZXIgdjEuMA=="><algid val="SHA1" sm2_hashalg="SHA1" /></lib><lib type="CSP" version="1.0" dllname="R0FTU19GIENyeXB0b2dyYXBoaWMgU2VydmljZSBQcm92aWRlciB2MS4w"><algid val="SHA1" sm2_hashalg="SHA1" /></lib></liblist><checkkeytimes><item times="1" ></item></checkkeytimes></authinfo>';
// 参数说明：signResult：签名结果
const signResult = ref<any>('');
// 参数说明：signSubject：证书版发者主题
const signSubject = ref('');
const original = ref('');

function handlePKILogin() {
  generateOriginalNum()
    .then((res: any) => {
      console.log(res, '----res');

      original.value = res;
      doDataProcess(initParam);
    })
    .catch((err) => {});
}
async function doDataProcess(initParam: any) {
  // 验证认证原文是否为空
  if (original.value == '') {
    message.error('认证原文不能为空!');
    return false;
  } else {
    // 调用网关工具脚本中的detachSignStr方法进行签名，返回签名结果
    // 参数说明：initParam：vctk控件初始化参数，authContent：认证原文，signSubject：证书版本者主题
    signResult.value = detachSignStr(initParam, original.value, signSubject.value);
    if (signResult.value) {
      await authStore.authPKILogin({
        originalNum: original.value,
        signedData: signResult.value,
      });
    } else {
      return false;
    }
  }
}
const JIT_GW_ExtInterface: any = window.JIT_GW_ExtInterface;
function detachSignStr(initParam: any, authContent: any, signSubject: any) {
  // 验证认证原文不能为空
  if (authContent == '') {
    message.error('认证原文不能为空!');
    return false;
  } else {
    try {
      JIT_GW_ExtInterface.GetVersion(); //authentication component
    } catch (e) {
      message.warning('未安装控件，请进行安装控件');
      return false;
    }

    try {
      JIT_GW_ExtInterface.ClearFilter();
      // 初始化PNX控件
      JIT_GW_ExtInterface.Initialize('', initParam);
      // 控制证书为一个时，不弹出证书选择框
      JIT_GW_ExtInterface.SetChooseSingleCert(1);
      // 同DN情况下优先使用sm2证书
      // JIT_GW_ExtInterface.AddFilter(11,"2");

      // 设置是否强制弹出PIN码，需要时打开
      // if("true"== this.certAuthForm.pinCode){
      //   //加捕获异常的方法为兼容之前老版本插件，如果是老版本插件跳过此方法
      //   try{
      //   2  JIT_GW_ExtInterface.SetForcePinDialog(1);
      //   }catch(e){
      //
      //   }
      // }
    } catch (e) {
      alert('调用方法失败：' + JIT_GW_ExtInterface.GetLastErrorMessage());
      return false;
    }

    // 生成签名信息
    var sign_Result = '';
    try {
      sign_Result = JIT_GW_ExtInterface.P7SignString(authContent, true, true);
    } catch (e) {
      alert('生成签名信息失败：' + JIT_GW_ExtInterface.GetLastErrorMessage());
      return false;
    }
    if (JIT_GW_ExtInterface.GetLastError() != 0) {
      if (
        JIT_GW_ExtInterface.GetLastError() == 3758096386 ||
        JIT_GW_ExtInterface.GetLastError() == 2148532334 ||
        JIT_GW_ExtInterface.GetLastError() == 3758096385
      ) {
        alert('用户取消操作');
        return;
      } else if (
        JIT_GW_ExtInterface.GetLastError() == -536870815 ||
        JIT_GW_ExtInterface.GetLastError() == 3758096481
      ) {
        alert('没有找到有效的证书，如果使用的是KEY，请确认已经插入key');
        return;
      } else {
        alert(JIT_GW_ExtInterface.GetLastErrorMessage());
        return;
      }
    }
    // 返回签名结果
    return sign_Result;
  }
}

// 存储按键状态
const pressedKeys = new Set<string>();

// 处理键盘按下事件
function handleKeyDown(event: KeyboardEvent) {
  // 添加当前按下的键
  pressedKeys.add(event.key?.toLowerCase());

  // 检查是否满足 Ctrl + Q + Z 组合
  if (pressedKeys.has('control') && pressedKeys.has('q') && pressedKeys.has('z')) {
    event.preventDefault(); // 阻止默认行为
    isPki.value = !isPki.value; // 切换登录方式
    pressedKeys.clear(); // 清除按键状态
  }
}

// 处理键盘抬起事件
function handleKeyUp(event: KeyboardEvent) {
  // 移除松开的键
  pressedKeys.delete(event.key?.toLowerCase());
}

// 注册事件监听器
onMounted(() => {
  window.addEventListener('keydown', handleKeyDown);
  window.addEventListener('keyup', handleKeyUp);
});

// 移除事件监听器
onBeforeUnmount(() => {
  window.removeEventListener('keydown', handleKeyDown);
  window.removeEventListener('keyup', handleKeyUp);
});
</script>

<template>
  <div>
    <div class="login-container" v-if="isPki">
      <!-- 背景装饰圆圈 (增加氛围感) -->
      <div class="bg-circle circle-1"></div>
      <div class="bg-circle circle-2"></div>

      <!-- 登录卡片 (方框) -->
      <div class="login-card">
        <!-- 顶部图标区 -->
        <div class="card-header">
          <div class="icon-box">
            <SafetyCertificateOutlined />
          </div>
        </div>

        <!-- 标题区 -->
        <div class="card-title">
          <h2>欢迎使用本平台</h2>
          <p class="sub-title">请插入 PKI 进行安全身份认证</p>
        </div>

        <!-- 操作区 -->
        <div class="card-action">
          <button class="pki-btn" @click="handlePKILogin">
            <span class="btn-text">PKI 证书登录</span>
            <div class="btn-glow"></div>
          </button>

          <!-- 辅助链接 -->
          <a class="link-row" href="/chrome.exe" download="chrome.exe">
            <ChromeFilled class="link-icon" />
            <span>谷歌高版本下载</span>
          </a>
        </div>
      </div>
    </div>
    <AuthenticationLogin
      v-else
      ref="loginFormRef"
      :form-schema="formSchema"
      :loading="authStore.loginLoading"
      :show-register="true"
      :show-third-party-login="false"
      @submit="handleAccountLogin"
    >
      <!-- 可通过show-third-party-login控制是否显示第三方登录true  false -->
      <template #third-party-login>
        <OAuthLogin />
      </template>
    </AuthenticationLogin>
  </div>
</template>
<style lang="scss" scoped>
/* 
  配色变量 
  如果您有主题色，可以修改 $primary-color
*/
$primary-color: #1677ff;
$primary-gradient: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
$bg-color: #f0f2f5;

/* 背景装饰 - 让背景不那么空 */
.bg-circle {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  opacity: 0.6;
  z-index: 0;
}
.circle-1 {
  width: 400px;
  height: 400px;
  background: #bae0ff;
  top: -100px;
  left: -100px;
  animation: float 10s infinite ease-in-out alternate;
}
.circle-2 {
  width: 300px;
  height: 300px;
  background: #d6e4ff;
  bottom: -50px;
  right: -50px;
  animation: float 12s infinite ease-in-out alternate-reverse;
}

/* 核心卡片样式 */
.login-card {
  position: relative;
  z-index: 10;
  width: 420px;
  padding: 48px 40px;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(10px); /* 磨砂玻璃质感 */
  border-radius: 20px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(255, 255, 255, 0.5) inset;
  text-align: center;
  transition: transform 0.3s ease;
  animation: slideUp 0.6s cubic-bezier(0.16, 1, 0.3, 1);

  &:hover {
    transform: translateY(-5px);
    box-shadow: 0 25px 70px rgba(22, 119, 255, 0.15);
  }
}

/* 图标区域 */
.card-header {
  margin-bottom: 24px;
  display: flex;
  justify-content: center;

  .icon-box {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: #e6f4ff;
    color: $primary-color;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 32px;
    box-shadow: 0 8px 16px rgba(22, 119, 255, 0.1);
  }
}

/* 标题区域 */
.card-title {
  margin-bottom: 40px;

  h2 {
    font-size: 26px;
    font-weight: 700;
    color: #1f1f1f;
    margin-bottom: 8px;
    letter-spacing: 1px;
  }

  .sub-title {
    font-size: 14px;
    color: #8c8c8c;
    margin: 0;
  }
}

/* 按钮区域 */
.pki-btn {
  position: relative;
  width: 100%;
  height: 52px;
  border: none;
  border-radius: 12px;
  background: $primary-gradient;
  cursor: pointer;
  overflow: hidden;
  transition: all 0.3s ease;
  box-shadow: 0 10px 20px rgba(22, 119, 255, 0.3);

  .btn-text {
    position: relative;
    z-index: 2;
    color: #fff;
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 2px;
  }

  /* 按钮的高光扫光效果 */
  &::before {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
    transition: left 0.5s;
    z-index: 1;
  }

  &:hover {
    transform: scale(1.02);
    box-shadow: 0 15px 30px rgba(22, 119, 255, 0.4);

    &::before {
      left: 100%; /* 鼠标经过时扫光 */
    }
  }

  &:active {
    transform: scale(0.98);
  }
}

/* 底部链接 */
.link-row {
  margin-top: 24px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  color: #595959;
  cursor: pointer;
  padding: 8px 16px;
  border-radius: 20px;
  transition: all 0.3s;

  &:hover {
    color: $primary-color;
    background: #f5f5f5;
  }

  .link-icon {
    font-size: 16px;
  }
}

/* 底部版权 */
.footer-copyright {
  position: absolute;
  bottom: 24px;
  width: 100%;
  text-align: center;
  color: #bfbfbf;
  font-size: 12px;
  z-index: 10;
}

/* 动画定义 */
@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes float {
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(20px);
  }
}

/* 移动端适配 */
@media (max-width: 480px) {
  .login-card {
    width: 90%;
    padding: 32px 24px;
  }

  .bg-circle {
    display: none; /* 移动端为了性能和布局可能隐藏装饰 */
  }
}
</style>
