<script setup lang="ts">
import type { VbenFormSchema } from '@vben/common-ui';

import { computed, reactive, ref, watch } from 'vue';

import { useVbenForm, useVbenModal, VbenButton, z } from '@vben/common-ui';
import { useAccessStore, useUserStore } from '@vben/stores';

import { $t } from '@/locales';
import { message } from 'antdv-next';
import md5 from 'crypto-js/md5';

import {
  createAccountApi,
  getUserInfoApi,
  loginApi,
  sendSmsCodeApi,
} from '#/api';

import CaptchaInput from './CaptchaInput.vue';

defineOptions({
  name: 'LoginComponent',
});

const loading = ref(false);
const [Modal, modalApi] = useVbenModal();
const isRegister = ref(false);
const accessStore = useAccessStore();
const userStore = useUserStore();
const countdown = ref(0);
const isSending = ref(false);

const REMEMBER_ME_KEY = `REMEMBER_ME_USERNAME_${location.hostname}`;
const localUsername = localStorage.getItem(REMEMBER_ME_KEY) || '';
const rememberMe = ref(!!localUsername);
const open = defineModel<boolean>('open', { default: false });
const captchaRandomKey = ref('');

const loginFormSchema = computed((): VbenFormSchema[] => {
  return [
    {
      component: 'VbenInput',
      componentProps: {
        placeholder: '',
      },
      fieldName: 'username',
      label: $t('auth.loginName'),
      rules: z
        .string()
        .min(1, { message: $t('auth.validation.enterUsername') }),
      defaultValue: localUsername,
    },
    {
      component: 'VbenInputPassword',
      componentProps: {
        placeholder: '',
      },
      fieldName: 'password',
      label: $t('auth.password'),
      rules: z
        .string()
        .min(1, { message: $t('auth.validation.enterPassword') }),
    },
    {
      component: 'VbenInput',
      componentProps: {
        placeholder: '',
      },
      fieldName: 'captcha',
      label: $t('auth.verificationCode'),
      rules: z
        .string()
        .min(1, { message: $t('auth.validation.enterVerificationCode') }),
      formItemClass: 'captcha-form-item',
    },
  ];
});

const registerFormSchema = computed((): VbenFormSchema[] => {
  return [
    {
      component: 'VbenInput',
      componentProps: {
        placeholder: '',
      },
      fieldName: 'mobile',
      label: $t('auth.mobileNumber'),
      rules: z
        .string()
        .min(1, { message: $t('auth.validation.enterMobileNumber') })
        .regex(/^1[3-9]\d{9}$/, {
          message: $t('auth.validation.enterCorrectMobileNumber'),
        }),
    },
    {
      component: 'VbenInput',
      componentProps: {
        placeholder: '',
      },
      fieldName: 'code',
      label: $t('auth.verificationCode'),
      rules: z
        .string()
        .min(1, { message: $t('auth.validation.enterVerificationCode') }),
      formItemClass: 'verification-form-item',
    },
    {
      component: 'VbenInput',
      componentProps: {
        placeholder: '',
      },
      fieldName: 'accountName',
      label: $t('auth.accountName'),
      rules: z
        .string()
        .min(1, { message: $t('auth.validation.enterAccountName') }),
    },
    {
      component: 'VbenInputPassword',
      componentProps: {
        placeholder: '',
      },
      fieldName: 'password',
      label: $t('auth.password'),
      rules: z
        .string()
        .min(1, { message: $t('auth.validation.enterPassword') }),
    },
    {
      component: 'VbenCheckbox',
      componentProps: {
        placeholder: '',
      },
      fieldName: 'agreeTerms',
      label: '',
      rules: z.boolean().refine((val) => val === true, {
        message: $t('auth.validation.agreeTerms'),
      }),
      formItemClass: 'agree-terms-form-item',
    },
  ];
});

const [LoginForm, loginFormApi] = useVbenForm(
  reactive({
    commonConfig: {
      hideLabel: false,
      hideRequiredMark: true,
      formItemClass: 'pb-[20px]',
    },
    layout: 'vertical',
    schema: loginFormSchema,
    showDefaultActions: false,
    wrapperClass: 'text-[12px]',
  }),
);

const [RegisterForm, registerFormApi] = useVbenForm(
  reactive({
    commonConfig: {
      hideLabel: false,
      hideRequiredMark: true,
      formItemClass: 'pb-[15px]',
    },
    layout: 'vertical',
    schema: registerFormSchema,
    showDefaultActions: false,
    wrapperClass: 'text-[12px]',
  }),
);

watch(
  () => open.value,
  (val) => {
    modalApi.setState({ isOpen: val });
    isRegister.value = false;
  },
  { immediate: true },
);

function handleClose() {
  open.value = false;
}

async function handleLoginSubmit() {
  const { valid } = await loginFormApi.validate();
  const values = await loginFormApi.getValues();
  if (valid) {
    localStorage.setItem(
      REMEMBER_ME_KEY,
      rememberMe.value ? values?.username : '',
    );
    try {
      loading.value = true;
      const encryptedPassword = md5(values?.password || '').toString();
      const loginRes = await loginApi({
        account: values?.username,
        pwd: encryptedPassword,
        check_code: values?.captcha,
        check_key: captchaRandomKey.value,
      });
      if (loginRes && loginRes.isSuccess) {
        if (loginRes.token) {
          accessStore.setAccessToken(loginRes.token);
        }
        open.value = false;
        message.success($t('auth.message.loginSuccess'));
        const userInfoRes = await getUserInfoApi();
        if (userInfoRes && userInfoRes.isSuccess) {
          const userInfo = {
            account:
              userInfoRes.result?.account ||
              userInfoRes.result?.englishName ||
              '',
            avatar: userInfoRes.result?.avatarFileId || '',
            cellPhone: userInfoRes.result?.cellPhone || '',
            realName:
              userInfoRes.result?.chineseName || userInfoRes.result?.name || '',
            email: userInfoRes.result?.emailAddress || '',
            roles: [],
            userId: userInfoRes.result?.id || '',
            username: userInfoRes.result?.name || '',
          };
          userStore.setUserInfo(userInfo);
        }
      } else {
        message.error(loginRes?.error || $t('auth.message.loginFailed'));
      }
    } finally {
      loading.value = false;
    }
  }
}

async function handleSendCode() {
  const values = await registerFormApi.getValues();
  const mobile = values?.mobile;

  if (!mobile) {
    message.error($t('auth.message.enterMobileNumberFirst'));
    return;
  }

  const mobileRegex = /^1[3-9]\d{9}$/;
  if (!mobileRegex.test(mobile)) {
    message.error($t('auth.validation.enterCorrectMobileNumber'));
    return;
  }

  try {
    isSending.value = true;
    await sendSmsCodeApi({
      sms_mobile: mobile,
      sms_scene: 'sms_reg',
    });
    countdown.value = 60;

    const timer = setInterval(() => {
      countdown.value--;
      if (countdown.value <= 0) {
        clearInterval(timer);
        isSending.value = false;
      }
    }, 1000);
    message.success($t('auth.message.verificationCodeSent'));
  } catch {
    isSending.value = false;
    message.error($t('auth.message.sendVerificationCodeFailed'));
  }
}

async function handleRegisterSubmit() {
  const { valid } = await registerFormApi.validate();
  const values = await registerFormApi.getValues();
  if (valid) {
    try {
      loading.value = true;
      const encryptedPassword = md5(values?.password || '').toString();
      const registerRes = await createAccountApi({
        sms_scene: 'sms_reg',
        sms_mobile: values?.mobile,
        sms_check_code: values?.code,
        user: {
          langNameList: [
            {
              name: 'zh-CN',
              value: values?.accountName || '',
            },
            {
              name: 'en',
              value: '',
            },
          ],
          password: encryptedPassword,
        },
      });
      if (registerRes && registerRes.isSuccess) {
        message.success($t('auth.message.registerSuccess'));
        isRegister.value = false;
      } else {
        message.error(registerRes?.error || $t('auth.message.registerFailed'));
      }
    } finally {
      loading.value = false;
    }
  }
}

function handleGoToRegister() {
  isRegister.value = true;
}

function handleGoToLogin() {
  isRegister.value = false;
}

defineExpose({
  getFormApi: () => loginFormApi,
});
</script>

<template>
  <div>
    <Modal
      id="loginModal"
      :bordered="false"
      :closable="false"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :footer="false"
      :fullscreen-button="false"
      :header="false"
      class="relative sm:w-[940px]"
      content-class="p-0"
      @update:open="handleClose"
    >
      <div class="relative flex">
        <div class="hidden w-[470px] sm:flex">
          <img
            alt="login"
            class="w-[470px] object-contain"
            src="@/assets/image/login-banner.png"
          />
        </div>
        <div class="w-full px-[86px] py-[30px] sm:w-1/2">
          <div v-if="!isRegister" class="mb-6">
            <h2 class="text-[21px] font-bold">{{ $t('auth.login') }}</h2>
            <p class="text-muted-foreground mt-3 text-sm">
              {{ $t('auth.newUser') }}
              <span
                class="cursor-pointer text-[#8B0046]"
                @click="handleGoToRegister"
              >
                {{ $t('auth.createAccount') }}
              </span>
            </p>
          </div>

          <div v-if="isRegister" class="mb-6">
            <h2 class="text-[21px] font-bold">
              {{ $t('auth.createAccount') }}
            </h2>
            <p class="text-muted-foreground mt-3 text-sm">
              {{ $t('auth.alreadyHaveAccount') }}
              <span
                class="cursor-pointer text-[#8B0046]"
                @click="handleGoToLogin"
              >
                {{ $t('auth.login') }}
              </span>
            </p>
          </div>

          <div class="my-[20px] h-[1px] w-auto bg-[#E5E5E5]"></div>

          <LoginForm v-if="!isRegister">
            <template #captcha="{ field }">
              <CaptchaInput
                :model-value="field.value"
                @update:model-value="
                  (val) => {
                    loginFormApi.setFieldValue('captcha', val);
                  }
                "
                @update:random-key="
                  (val) => {
                    captchaRandomKey = val;
                  }
                "
              />
            </template>
          </LoginForm>

          <RegisterForm v-if="isRegister">
            <template #code="{ field }">
              <div class="flex w-full items-center justify-around gap-2">
                <input
                  v-model="field.value"
                  class="h-[38px] flex-1 rounded-md border border-gray-300 px-3 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-[#8B0046]"
                  placeholder=""
                  type="text"
                  @input="
                    () => {
                      registerFormApi.setFieldValue('code', field.value);
                    }
                  "
                />
                <VbenButton
                  :disabled="countdown > 0"
                  :loading="isSending"
                  class="h-[38px] whitespace-nowrap rounded-md bg-gradient-to-b from-[#8B0046] to-[#460023] px-4 text-white"
                  @click="handleSendCode"
                >
                  {{ countdown > 0 ? `${countdown}s` : $t('auth.sendCode') }}
                </VbenButton>
              </div>
            </template>
            <template #agreeTerms="{ field }">
              <label class="flex cursor-pointer items-center gap-2">
                <input
                  v-model="field.value"
                  class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-600"
                  type="checkbox"
                  @change="
                    () => {
                      registerFormApi.setFieldValue('agreeTerms', field.value);
                    }
                  "
                />
                <span class="text-sm">{{ $t('auth.agreeTerms') }}</span>
              </label>
            </template>
          </RegisterForm>

          <VbenButton
            v-if="!isRegister"
            :class="{ 'cursor-wait': loading }"
            :loading="loading"
            aria-label="login"
            class="m-auto mt-[20px] flex h-[50px] w-full cursor-pointer items-center justify-center rounded-[25px] bg-gradient-to-b from-[#8B0046] to-[#460023] text-[16px] text-white"
            @click="handleLoginSubmit"
          >
            {{ $t('auth.loginButton') }}
          </VbenButton>

          <VbenButton
            v-if="isRegister"
            :class="{ 'cursor-wait': loading }"
            :loading="loading"
            aria-label="register"
            class="m-auto mt-[20px] flex h-[50px] w-full cursor-pointer items-center justify-center rounded-[25px] bg-gradient-to-b from-[#8B0046] to-[#460023] text-[16px] text-white"
            @click="handleRegisterSubmit"
          >
            {{ $t('auth.createAccountButton') }}
          </VbenButton>
        </div>
        <div class="absolute right-[20px] top-[24px] h-[44px] w-[59.12px]">
          <img alt="" class="" src="@/assets/image/system-logo.png" />
        </div>
      </div>
      <div
        class="fixed right-[-80px] top-[0] flex h-[34px] w-[34px] cursor-pointer items-center justify-center rounded-[50%] bg-[#fff] text-[#000] transition-opacity hover:opacity-80"
        @click="handleClose"
      >
        X
      </div>
    </Modal>
  </div>
</template>
