<script lang="ts" setup>
import type { FormSubmitEvent } from '#ui/types'
import { object, string, type InferType } from 'yup'

definePageMeta({
  layout: 'authenticate',
  preventLoginCheck: true,
})

useSeoMeta({
  title: '登录',
})

const route = useRoute()
const router = useRouter()
const toast = useToast()
const loginState = useLoginState()

const sms_triggered = ref(false)
const sms_sending = ref(false)
const sms_counting_down = ref(0)
const final_loading = ref(false)

const items = [
  {
    key: 'sms',
    label: '短信登录',
    icon: 'i-tabler-message-2',
    description: '使用短信验证码登录',
  },
  {
    key: 'account',
    label: '密码登录',
    icon: 'i-tabler-key',
    description: '使用已有账号和密码登录',
  },
  {
    key: 'recovery',
    label: '找回密码',
    icon: 'i-tabler-lock',
    description: '忘记密码时，可以通过手机号和验证码重置密码',
  },
]

const currentTab = ref(0)

const accountForm = reactive<req.user.Login>({ username: '', password: '' })
const smsForm = reactive({ mobile: '', sms_code: [] })

function onSubmit(form: req.user.Login) {
  console.log('Submitted form:', form)
  final_loading.value = true
  useFetchWrapped<req.user.Login, BaseResponse<resp.user.Login>>(
    'App.User_User.Login',
    {
      username: form.username,
      password: form.password,
    }
  )
    .then((res) => {
      final_loading.value = false
      if (res.ret !== 200) {
        toast.add({
          title: '登录失败',
          description: res.msg || '未知错误',
          color: 'error',
          icon: 'i-tabler-circle-x',
        })
        return
      }
      if (!res.data.is_login) {
        toast.add({
          title: '登录失败',
          description: res.msg || '账号或密码错误',
          color: 'error',
          icon: 'i-tabler-circle-x',
        })
        return
      }
      if (!res.data.token || !res.data.user_id) {
        toast.add({
          title: '登录失败',
          description: res.msg || '无法获取登录状态',
          color: 'error',
          icon: 'i-tabler-circle-x',
        })
        return
      }
      loginState.token = res.data.token
      loginState.user.id = res.data.user_id
      loginState
        .updateProfile()
        .then(() => {
          loginState.checkSession()
          toast.add({
            title: '登录成功',
            description: `${loginState.user.username}, 欢迎回来`,
            color: 'primary',
            icon: 'i-tabler-login-2',
          })
          router.replace('/')
        })
        .catch((err) => {
          toast.add({
            title: '登录失败',
            description: err.msg || '网络错误',
            color: 'error',
            icon: 'i-tabler-circle-x',
          })
        })
        .finally(() => {
          final_loading.value = false
        })
    })
    .catch((err) => {
      toast.add({
        title: '登录失败',
        description: err.msg || '网络错误',
        color: 'error',
        icon: 'i-tabler-circle-x',
      })
    })
}

const obtainSmsCode = () => {
  smsForm.sms_code = []
  sms_sending.value = true

  useFetchWrapped<req.user.SmsLogin, BaseResponse<resp.user.SmsLogin>>(
    'App.User_User.MobileLogin',
    {
      mobile: smsForm.mobile,
    }
  )
    .then((res) => {
      if (res.ret !== 200) {
        sms_sending.value = false
        toast.add({
          title: '验证码发送失败',
          description: res.msg || '未知错误',
          color: 'error',
          icon: 'i-tabler-circle-x',
        })
        return
      }
      sms_triggered.value = true
      sms_sending.value = false
      sms_counting_down.value = 60 // TODO: save timestamp to localstorage
      toast.add({
        title: '短信验证码已发送',
        color: 'primary',
        icon: 'i-tabler-circle-check',
      })
      const interval = setInterval(() => {
        sms_counting_down.value--
        if (sms_counting_down.value <= 0) {
          clearInterval(interval)
        }
      }, 1000)
    })
    .catch((err) => {
      toast.add({
        title: '验证码发送失败',
        description: err.msg || '网络错误',
        color: 'error',
        icon: 'i-tabler-circle-x',
      })
    })
}

const handle_sms_verify = (e: string[]) => {
  final_loading.value = true
  useFetchWrapped<
    req.user.SmsLoginVerify,
    BaseResponse<resp.user.SmsLoginVerify>
  >('App.User_User.MobileLoginVerify', {
    mobile: smsForm.mobile,
    sms_code: e.join(''),
  })
    .then((res) => {
      if (res.ret !== 200) {
        smsForm.sms_code = []
        toast.add({
          title: '登录失败',
          description: res.msg || '未知错误',
          color: 'error',
          icon: 'i-tabler-circle-x',
        })
        return
      }
      if (!res.data.token || !res.data.person_id) {
        smsForm.sms_code = []
        toast.add({
          title: '登录失败',
          description: res.msg || '无法获取登录状态',
          color: 'error',
          icon: 'i-tabler-circle-x',
        })
        return
      }
      loginState.token = res.data.token
      loginState.user.id = res.data.person_id
      loginState
        .updateProfile()
        .then(() => {
          loginState.checkSession()
          toast.add({
            title: '登录成功',
            description: `${loginState.user.username}, 欢迎回来`,
            color: 'primary',
            icon: 'i-tabler-login-2',
          })
          router.replace('/')
        })
        .catch((err) => {
          toast.add({
            title: '登录失败',
            description: err.msg || '网络错误',
            color: 'error',
            icon: 'i-tabler-circle-x',
          })
        })
        .finally(() => {
          final_loading.value = false
        })
    })
    .finally(() => (final_loading.value = false))
}

const forgetPasswordState = reactive({
  mobile: '',
  sms_code: '',
  password: '',
})

const forgetPasswordSchema = object({
  mobile: string()
    .required('请输入手机号')
    .matches(/^1[3-9]\d{9}$/, '手机号格式不正确'),
  sms_code: string().required('请输入验证码').length(4, '验证码长度为4位'),
  password: string().required('请输入新密码').min(6, '密码长度至少为6位'),
})

type ForgetPasswordSchema = InferType<typeof forgetPasswordSchema>

const obtainForgetSmsCode = () => {
  forgetPasswordState.sms_code = ''
  sms_sending.value = true

  useFetchWrapped<req.user.SmsChangePasswordVerify, BaseResponse<{}>>(
    'App.User_User.ForgotPasswordSms',
    {
      mobile: forgetPasswordState.mobile,
    }
  )
    .then((res) => {
      if (res.ret !== 200) {
        sms_sending.value = false
        toast.add({
          title: '验证码发送失败',
          description: res.msg || '未知错误',
          color: 'error',
          icon: 'i-tabler-circle-x',
        })
        return
      }
      sms_triggered.value = true
      sms_sending.value = false
      sms_counting_down.value = 60 // TODO: save timestamp to localstorage
      toast.add({
        title: '短信验证码已发送',
        color: 'primary',
        icon: 'i-tabler-circle-check',
      })
      const interval = setInterval(() => {
        sms_counting_down.value--
        if (sms_counting_down.value <= 0) {
          clearInterval(interval)
        }
      }, 1000)
    })
    .catch((err) => {
      toast.add({
        title: '验证码发送失败',
        description: err.msg || '网络错误',
        color: 'error',
        icon: 'i-tabler-circle-x',
      })
    })
}

const onForgetPasswordSubmit = (
  event: FormSubmitEvent<ForgetPasswordSchema>
) => {
  final_loading.value = true
  useFetchWrapped<req.user.SmsChangePassword, BaseResponse<{}>>(
    'App.User_User.ForgotPassword',
    {
      mobile: event.data.mobile,
      sms_code: event.data.sms_code,
      new_password: event.data.password,
    }
  )
    .then((res) => {
      final_loading.value = false
      if (res.ret !== 200) {
        toast.add({
          title: '重置密码失败',
          description: res.msg || '未知错误',
          color: 'error',
          icon: 'i-tabler-circle-x',
        })
        return
      }
      toast.add({
        title: '重置密码成功',
        description: '请您继续登录',
        color: 'success',
        icon: 'i-tabler-circle-check',
      })
      currentTab.value = 1
    })
    .catch((err) => {
      toast.add({
        title: '重置密码失败',
        description: err.msg || '未知错误',
        color: 'error',
        icon: 'i-tabler-circle-x',
      })
    })
}

onMounted(() => {
  const { token, user_id } = route.query
  if (!token || !user_id) {
    return
  }
  loginState.token = token.toString()
  loginState.user.id = user_id as unknown as number
  loginState
    .updateProfile()
    .then(() => {
      loginState.checkSession()
      // toast.add({
      //   title: '登录成功',
      //   description: `合作渠道认证成功`,
      //   color: 'primary',
      //   icon: 'i-tabler-login-2',
      // })
      router.replace('/')
    })
    .catch((err) => {
      toast.add({
        title: '认证失败',
        description: err.msg || 'Token 或 UserID 无效',
        color: 'error',
        icon: 'i-tabler-circle-x',
      })
      router.replace('/')
    })
    .finally(() => {
      final_loading.value = false
    })
})
</script>

<template>
  <div class="w-full min-h-screen flex flex-col justify-center items-center">
    <div class="flex flex-col items-center py-12 gap-2">
      <h1 class="text-3xl font-bold text-gray-900 dark:text-white">
        AIGC 微课视频研创平台
      </h1>
      <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
        请使用以下方式登录
      </p>
    </div>
    <div class="flex flex-col items-center">
      <UTabs
        :items="items"
        class="w-full sm:w-100"
        v-model="currentTab"
      >
        <!-- <template #default="{ item, index, selected }">
          <div class="flex items-center gap-2 relative truncate">
            <span class="truncate">{{ item.label }}</span>
            <span
              v-if="selected"
              class="absolute -right-4 w-2 h-2 rounded-full bg-primary-500 dark:bg-primary-400"
            />
          </div>
        </template> -->
        <template #content="{ item }">
          <UCard @submit.prevent="() => onSubmit(accountForm)">
            <template #header>
              <p
                class="text-base font-semibold leading-6 text-gray-900 dark:text-white"
              >
                {{ item.label }}
              </p>
              <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
                {{ item.description }}
              </p>
            </template>

            <div
              v-if="item.key === 'account'"
              class="space-y-3"
            >
              <UFormField
                label="用户名"
                name="username"
                required
              >
                <UInput
                  v-model="accountForm.username"
                  :disabled="final_loading"
                  required
                />
              </UFormField>
              <UFormField
                label="密码"
                name="password"
                required
              >
                <UInput
                  v-model="accountForm.password"
                  :disabled="final_loading"
                  type="password"
                  required
                />
              </UFormField>
            </div>

            <div
              v-else-if="item.key === 'sms'"
              class="space-y-3"
            >
              <UFormField
                label="手机号"
                name="mobile"
                required
              >
                <UButtonGroup class="w-full">
                  <UInput
                    v-model="smsForm.mobile"
                    :disabled="final_loading"
                    type="sms"
                    class="w-full"
                    required
                  >
                    <template #leading>
                      <span class="text-gray-500 dark:text-gray-400 text-xs">
                        +86
                      </span>
                    </template>
                  </UInput>
                  <UButton
                    :label="
                      sms_counting_down
                        ? `${sms_counting_down}秒后重发`
                        : '获取验证码'
                    "
                    @click="obtainSmsCode"
                    :loading="sms_sending"
                    :disabled="!!sms_counting_down || final_loading"
                    class="text-xs font-bold"
                    color="neutral"
                    variant="outline"
                  />
                </UButtonGroup>
              </UFormField>
              <Transition name="pin-root">
                <div
                  v-if="sms_triggered"
                  class="w-full overflow-hidden"
                >
                  <Label
                    for="pin-input"
                    class="pin-label"
                  >
                    验证码
                  </Label>
                  <PinInputRoot
                    id="sms-input"
                    v-model="smsForm.sms_code"
                    :disabled="sms_sending || final_loading"
                    placeholder="○"
                    class="w-full flex gap-2 justify-between md:justify-start items-center mt-1"
                    @complete="handle_sms_verify"
                    type="number"
                    otp
                    required
                  >
                    <PinInputInput
                      v-for="(id, index) in 4"
                      :key="id"
                      :index="index"
                      class="pin-input w-12 h-12 text-center rounded-lg"
                      :autofocus="index === 0"
                    />
                  </PinInputRoot>
                </div>
              </Transition>
            </div>

            <div
              v-if="item.key === 'recovery'"
              class="space-y-3"
            >
              <UForm
                class="space-y-3"
                :schema="forgetPasswordSchema"
                :state="forgetPasswordState"
                @submit="onForgetPasswordSubmit"
              >
                <UFormField
                  label="手机号"
                  name="mobile"
                  required
                >
                  <UButtonGroup class="w-full">
                    <UInput
                      v-model="forgetPasswordState.mobile"
                      :disabled="final_loading"
                      type="tel"
                      class="w-full"
                    >
                      <template #leading>
                        <span class="text-gray-500 dark:text-gray-400 text-xs">
                          +86
                        </span>
                      </template>
                    </UInput>
                    <UButton
                      :label="
                        sms_counting_down
                          ? `${sms_counting_down}秒后重发`
                          : '获取验证码'
                      "
                      @click="obtainForgetSmsCode"
                      :loading="sms_sending"
                      :disabled="!!sms_counting_down"
                      class="text-xs font-bold"
                      color="neutral"
                    />
                  </UButtonGroup>
                </UFormField>
                <UFormField
                  label="验证码"
                  name="sms_code"
                  required
                >
                  <UInput
                    v-model="forgetPasswordState.sms_code"
                    type="sms"
                    class="w-full"
                    :disabled="final_loading"
                  />
                </UFormField>
                <UFormField
                  label="新密码"
                  name="password"
                  required
                >
                  <UInput
                    v-model="forgetPasswordState.password"
                    type="password"
                    :disabled="final_loading"
                  />
                </UFormField>

                <div>
                  <UButton
                    type="submit"
                    :loading="final_loading"
                  >
                    重置密码
                  </UButton>
                </div>
              </UForm>
            </div>

            <template
              #footer
              v-if="item.key === 'account'"
            >
              <div class="flex items-center justify-between">
                <UButton
                  type="submit"
                  color="neutral"
                  :loading="final_loading"
                >
                  登录
                </UButton>
                <UButton
                  variant="link"
                  color="neutral"
                  @click="currentTab = 2"
                >
                  忘记密码
                </UButton>
              </div>
            </template>
          </UCard>
        </template>
      </UTabs>
    </div>
    <div class="pt-4">
      <UButton
        color="neutral"
        variant="ghost"
        class="text-gray-500!"
        @click="
          () => {
            router.push('/user/register')
          }
        "
      >
        注册新账号
      </UButton>
    </div>
  </div>
</template>

<style scoped></style>
