<template>
  <div class="login-main">
    <div class="login-left">
      <BoxDog/>
    </div>
    <div class="login-right">

      <span class="login-right-title">
        <img src="@/assets/images/logo-schisandra.png" @click="()=>{
          router.push('/')
        }" style="width: 30px; height: 30px;cursor: pointer;" alt="">
        {{ t("login.title") }}
      </span>
      <ACard class="login-card" bordered :hoverable="false">
        <ATabs :centered="false" size="large">
          <!--    短信登录      -->
          <ATabPane key="phoneLogin">
            <template #tab>
                <span class="login-tab-span">
                      {{ t("login.phoneLogin") }}
                 </span>
            </template>
            <AForm ref="phoneLoginFormRef" :rules="rules" :model="phoneLoginForm">
              <AFormItem
                  class="login-form-item"
                  name="phone">
                <span class="login-card-span">{{ t("login.phone") }}</span>
                <AInput v-model:value="phoneLoginForm.phone" class="login-form-input" size="large"
                        :placeholder=phoneValidate allow-clear
                        autocomplete="off"
                >
                  <template #prefix>
                    <TabletOutlined/>
                  </template>
                </AInput>
              </AFormItem>
              <AFormItem
                  class="login-form-item"
                  name="captcha">
                <AFlex :vertical="true">
                  <span class="login-card-span">{{ t("login.phoneCaptcha") }}</span>
                  <AFlex :vertical="false" align="center" justify="center">
                    <AInput v-model:value="phoneLoginForm.captcha" size="large" :placeholder=captchaValidate
                            allow-clear>
                      <template #prefix>
                        <SafetyOutlined/>
                      </template>
                    </AInput>
                    <AButton v-if="!state.showCountDown" @click="sendCaptchaThrottle" style="margin-left: 10px"
                             size="large">{{
                        t("login.sendCaptcha")
                      }}
                    </AButton>
                    <AButton v-if="state.showCountDown" disabled style="margin-left: 10px" size="large">{{
                        state.countDownTime
                      }}s{{ t("login.reSendCaptcha") }}
                    </AButton>
                  </AFlex>
                </AFlex>

              </AFormItem>
              <AFormItem id="phone_login_auto" name="auto_login">
                <AFlex :vertical="false" justify="space-between">
                  <ACheckbox id="phone_login_auto_checkbox" v-model:checked="phoneLoginForm.auto_login">
                    {{ t("login.autoLogin") }}
                  </ACheckbox>
                </AFlex>

              </AFormItem>
              <AFormItem>
                <AButton @click="phoneLoginSubmitDebounce" type="primary" size="large" class="login-form-button">
                  {{ t("login.loginAndRegister") }}
                </AButton>
              </AFormItem>
            </AForm>
            <LoginFooter/>
          </ATabPane>
          <!--    账号登录      -->
          <ATabPane key="accountLogin">
            <template #tab>
                <span class="login-tab-span">
                      {{ t("login.accountLogin") }}
                 </span>
            </template>
            <AForm ref="accountLoginFormRef" :rules="rules" :model="accountLoginForm" autocomplete="off">
              <AFormItem
                  class="login-form-item"
                  name="account">
                <span class="login-card-span">{{ t("login.account") }}</span>
                <AInput v-model:value="accountLoginForm.account" class="login-form-input" size="large"
                        :placeholder=accountValidate allow-clear autocomplete="off">
                  <template #prefix>
                    <user-outlined/>
                  </template>
                </AInput>
              </AFormItem>
              <AFormItem
                  class="login-form-item"
                  name="password">
                <AFlex :vertical="true">
                  <span class="login-card-span">{{ t("login.password") }}</span>
                  <AInputPassword v-model:value="accountLoginForm.password" class="login-form-input" size="large"
                                  :placeholder=passwordValidate allow-clear autocomplete="off">
                    <template #prefix>
                      <SafetyOutlined/>
                    </template>
                  </AInputPassword>
                </AFlex>
              </AFormItem>
              <AFormItem id="account_login_auto" name="auto_login">
                <AFlex :vertical="false" justify="space-between">
                  <ACheckbox id="account_login_auto_checkbox" v-model:checked="accountLoginForm.auto_login">
                    {{ t("login.autoLogin") }}
                  </ACheckbox>
                  <a @click="()=>{
                    router.push('/resetpass')
                  }">{{ t("login.forgotPassword") }}</a>
                </AFlex>

              </AFormItem>
              <AFormItem>
                <AButton @click="accountLoginSubmitDebounce" type="primary" size="large" class="login-form-button">
                  {{
                    t("login.login")
                  }}
                </AButton>
              </AFormItem>
            </AForm>
            <LoginFooter/>
          </ATabPane>
        </ATabs>
        <ATooltip placement="left">
          <template #title>
            <span>{{ t("login.qrLogin") }}</span>
          </template>
          <div @click="()=>{
            router.push('/qrlogin');
          }" class="login-right-qrcode"/>
        </ATooltip>
      </ACard>
    </div>
    <div v-if="showPhoneRotateCaptcha" class="mask">
      <!--    滑动验证码 -->
      <gocaptcha-rotate
          class="gocaptcha-rotate"
          v-if="showPhoneRotateCaptcha"
          :data="captchaData"
          :config="{
            title: t('login.rotateCaptchaTitle'),
          }"
          :events="phoneLoginRotateEvent"
      />
    </div>
    <div v-if="showAccountRotateCaptcha" class="mask">
      <!--    滑动验证码 -->
      <gocaptcha-rotate
          class="gocaptcha-rotate"
          v-if="showAccountRotateCaptcha"
          :data="captchaData"
          :config="{
            title: t('login.rotateCaptchaTitle'),
          }"
          :events="accountLoginRotateEvent"
      />
    </div>

    <div class="area">
      <ul class="circles">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
    </div>
  </div>
</template>
<script setup lang="ts">
import {Rule} from "ant-design-vue/lib/form";
import {onMounted, reactive, ref, UnwrapRef} from "vue";
import {AccountLogin, PhoneLogin} from "@/types/user";
import {useI18n} from "vue-i18n";
import BoxDog from "@/components/BoxDog/BoxDog.vue";
import LoginFooter from "@/views/Login/LoginFooter.vue";
import {useRouter} from "vue-router";
import {checkRotatedCaptcha, getRotatedCaptchaData} from "@/api/captcha";
import {message} from "ant-design-vue";
import {accountLoginApi, phoneLoginApi, sendMessage} from "@/api/user";
import useStore from "@/store";
import {useDebounceFn, useThrottleFn} from "@vueuse/core";

const router = useRouter();
const {t} = useI18n();
const accountLoginFormRef = ref<any>();
const phoneLoginFormRef = ref<any>();
const showPhoneRotateCaptcha = ref<boolean>(false);
const showAccountRotateCaptcha = ref<boolean>(false);
const captchaData = reactive({angle: 0, image: "", thumb: "", key: ""});
const captchaErrorCount = ref<number>(0);
const phoneLoginRotateEvent = {
  confirm: (angle: number) => {
    checkPhoneLoginCaptchaDebounce(angle);
  },
  close: () => {
    showPhoneRotateCaptcha.value = false;
  },
  refresh: () => {
    refreshCaptcha();
  },
};
const accountLoginRotateEvent = {
  confirm: (angle: number) => {
    checkAccountLoginCaptchaDebounce(angle);
  },
  close: () => {
    showAccountRotateCaptcha.value = false;
  },
  refresh: () => {
    refreshCaptcha();
  },
};
// 账号登录表单数据
const accountLoginForm: UnwrapRef<AccountLogin> = reactive({
  account: '',
  password: '',
  auto_login: true,
});
// 手机登录表单数据
const phoneLoginForm: UnwrapRef<PhoneLogin> = reactive({
  phone: '',
  captcha: '',
  auto_login: true,
});
// 表单验证提示
const accountValidate = ref<string>(t('login.accountValidate'));
const passwordValidate = ref<string>(t('login.passwordValidate'));
const phoneValidate = ref<string>(t('login.phoneValidate'));
const captchaValidate = ref<string>(t('login.captchaValidate'));
// 表单验证规则
const rules: Record<string, Rule[]> = {
  account: [
    {required: true, message: t('login.accountValidate'), trigger: 'change'},
  ],
  password: [
    {
      required: true, message: t('login.passwordValidate'), trigger: 'change'
    },
    {
      pattern: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{6,18}$/,
      message: t('login.passwordRule'),
    },
  ],
  phone: [
    {required: true, message: t('login.phoneValidate'), trigger: 'change'},
    {pattern: /^1[2-9]\d{9}$/, message: t('login.phoneValidate')}
  ],
  captcha: [
    {
      required: true, message: t('login.captchaValidate'), trigger: 'change'
    },
  ]
};

const state: any = reactive<any>({
  countDownTime: 60,
  showCountDown: false,
});

/**
 * 验证码发送倒计时
 */
const countDown = () => {
  const startTime = localStorage.getItem('start_time_send_captcha');
  const nowTime = new Date().getTime();
  let surplus: number = 60;
  let timer: any;
  if (startTime) {
    surplus = 60 - Math.floor((nowTime - Number(startTime)) / 1000);
    surplus = surplus <= 0 ? 0 : surplus;
  } else {
    localStorage.setItem('start_time_send_captcha', String(nowTime));
  }
  state.countDownTime = surplus;
  if (timer) {
    clearInterval(timer);
  }
  timer = setInterval(() => {
    if (state.countDownTime <= 0) {
      localStorage.removeItem('start_time_send_captcha');
      clearInterval(timer);
      state.countDownTime = 60;
      state.showCountDown = false;
    } else {
      state.countDownTime--;
      state.showCountDown = true;
    }
  }, 1000);
};
onMounted(() => {
  const sendEndTime = localStorage.getItem('start_time_send_captcha');
  if (sendEndTime) {
    state.showCountDown = true;
    countDown();
  }
});

/**
 *  发送验证码节流
 */
const sendCaptchaThrottle = useThrottleFn(sendCaptcha, 3000);

/**
 * 发送验证码
 */
async function sendCaptcha() {
  phoneLoginFormRef.value
      .validateFields("phone")
      .then(() => {
        getRotateCaptcha().then(() => {
          showPhoneRotateCaptcha.value = true;
        });
      })
      .catch((error: any) => {
        console.log('error', error);
      });
}

/**
 *  账号登录  防抖
 */
const accountLoginSubmitDebounce = useDebounceFn(accountLoginSubmit, 3000);

/**
 * 账号登录提交
 */
async function accountLoginSubmit() {
  accountLoginFormRef.value
      .validate()
      .then(() => {
        getRotateCaptcha().then(() => {
          showAccountRotateCaptcha.value = true;
        });
      })
      .catch((error: any) => {
        console.log('error', error);
      });
}

/**
 * 手机登录提交  防抖
 */
const phoneLoginSubmitDebounce = useDebounceFn(phoneLoginSubmit, 3000);

/**
 * 手机登录提交
 */
async function phoneLoginSubmit() {
  phoneLoginFormRef.value
      .validate()
      .then(async () => {
        const res: any = await phoneLoginApi(phoneLoginForm);
        if (res.code === 0 && res.success) {
          const userStore = useStore().user;
          const {uid, access_token, refresh_token, expires_at} = res.data;
          userStore.user.uid = uid;
          userStore.user.accessToken = access_token;
          userStore.user.refreshToken = refresh_token;
          userStore.user.expiresAt = expires_at;
          message.success(t('login.loginSuccess'));
          setTimeout(() => {
            router.push('/main');
          }, 1000);
        } else {
          message.error(res.message);
        }
      })
      .catch((error: any) => {
        console.error(error);
      });
}

/**
 * 刷新验证码  节流
 */
const refreshCaptcha = useThrottleFn(getRotateCaptcha, 3000);

/**
 * 获取旋转验证码数据
 */
async function getRotateCaptcha() {
  const data: any = await getRotatedCaptchaData();
  if (data.code === 0 && data.data) {
    const {angle, image, thumb, key} = data.data;
    captchaData.angle = angle;
    captchaData.image = image;
    captchaData.thumb = thumb;
    captchaData.key = key;
  } else {
    message.error(t('login.systemError'));
  }
}

/**
 *  检查手机登录旋转验证码   防抖
 */
const checkPhoneLoginCaptchaDebounce = useDebounceFn(checkPhoneLoginCaptcha, 500);

/**
 * 验证旋转验证码
 * @param angle
 */
async function checkPhoneLoginCaptcha(angle: number) {
  if (captchaErrorCount.value >= 2) {
    message.error(t('login.captchaError'));
    getRotateCaptcha().then(() => {
      captchaErrorCount.value = 0;
    });
  } else {
    const result: any = await checkRotatedCaptcha(angle, captchaData.key);
    if (result.code === 0 && result.success) {
      showPhoneRotateCaptcha.value = false;
      const result: boolean = await sendMessageByPhone();
      if (result) {
        countDown();
      }
    } else if (result.code === 1011) {
      message.error(t('login.captchaExpired'));
      getRotateCaptcha().then(() => {
        captchaErrorCount.value = 0;
      });
    } else {
      captchaErrorCount.value++;
      message.error(t('login.captchaError'));
    }
  }
}

/**
 * 检查账户登录旋转验证码  防抖
 */
const checkAccountLoginCaptchaDebounce = useDebounceFn(checkAccountLoginCaptcha, 500);

/**
 * 检查账户登录旋转验证码
 * @param angle
 */
async function checkAccountLoginCaptcha(angle: number) {
  if (captchaErrorCount.value >= 2) {
    message.error(t('login.captchaError'));
    getRotateCaptcha().then(() => {
      captchaErrorCount.value = 0;
    });
  } else {
    const result: any = await checkRotatedCaptcha(angle, captchaData.key);
    if (result.code === 0 && result.success) {
      showAccountRotateCaptcha.value = false;
      const res: any = await accountLoginApi(accountLoginForm);
      if (res.code === 0 && res.success) {
        const userStore = useStore().user;
        const {uid, access_token, refresh_token, expires_at} = res.data;
        userStore.user.uid = uid;
        userStore.user.accessToken = access_token;
        userStore.user.refreshToken = refresh_token;
        userStore.user.expiresAt = expires_at;
        message.success(t('login.loginSuccess'));
        setTimeout(() => {
          router.push('/main');
        }, 1000);
      } else {
        message.error(t('login.loginError'));
      }
    } else if (result.code === 1011) {
      message.error(t('login.captchaExpired'));
      getRotateCaptcha().then(() => {
        captchaErrorCount.value = 0;
      });
    } else {
      captchaErrorCount.value++;
      message.error(t('login.captchaError'));
    }
  }
}

/**
 * 发送手机验证码
 */
async function sendMessageByPhone(): Promise<boolean> {
  const phone: string = phoneLoginForm.phone as string;
  const res: any = await sendMessage(phone);
  if (res.code === 0 && res.success) {
    message.success(t('login.sendCaptchaSuccess'));
    return true;
  } else {
    message.error(res.data);
    return false;
  }
}
</script>
<style src="./index.scss" scoped lang="scss">

</style>
