<script setup lang="ts">
import {Label, PinInputInput, PinInputRoot} from 'radix-vue'
import {useFetchWrapped} from '~/composables/useFetchWrapped';

const toast = useToast()
const modal = useModal()
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: '使用已有账号和密码登录',
  },
]

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: 'red',
        icon: 'i-tabler-circle-x',
      })
      return
    }
    if (!res.data.is_login) {
      toast.add({
        title: '登录失败',
        description: res.msg || '账号或密码错误',
        color: 'red',
        icon: 'i-tabler-circle-x',
      })
      return
    }
    if (!res.data.token || !res.data.user_id) {
      toast.add({
        title: '登录失败',
        description: res.msg || '无法获取登录状态',
        color: 'red',
        icon: 'i-tabler-circle-x',
      })
      return
    }
    loginState.token = res.data.token
    loginState.user.id = res.data.user_id
    loginState.updateProfile().then(() => {
      loginState.checkSession()
      modal.close()
      toast.add({
        title: '登录成功',
        description: `${loginState.user.username}, 欢迎回来`,
        color: 'primary',
        icon: 'i-tabler-login-2',
      })
    }).catch(err => {
      toast.add({
        title: '登录失败',
        description: err.msg || '网络错误',
        color: 'red',
        icon: 'i-tabler-circle-x',
      })
    }).finally(() => {
      final_loading.value = false
    })
  }).catch(err => {
    toast.add({
      title: '登录失败',
      description: err.msg || '网络错误',
      color: 'red',
      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: 'red',
        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: 'indigo', 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: 'red',
      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: 'red',
        icon: 'i-tabler-circle-x',
      })
      return
    }
    if (!res.data.token || !res.data.person_id) {
      smsForm.sms_code = []
      toast.add({
        title: '登录失败',
        description: res.msg || '无法获取登录状态',
        color: 'red',
        icon: 'i-tabler-circle-x',
      })
      return
    }
    loginState.token = res.data.token
    loginState.user.id = res.data.person_id
    loginState.updateProfile().then(() => {
      loginState.checkSession()
      modal.close()
      toast.add({
        title: '登录成功',
        description: `${loginState.user.username}, 欢迎回来`,
        color: 'primary',
        icon: 'i-tabler-login-2',
      })
    }).catch(err => {
      toast.add({
        title: '登录失败',
        description: err.msg || '网络错误',
        color: 'red',
        icon: 'i-tabler-circle-x',
      })
    }).finally(() => {
      final_loading.value = false
    })
  }).finally(() => final_loading.value = false)
}
</script>

<template>
  <UModal prevent-close>
    <UCard>
      <template #header>
        <div class="flex items-center justify-between">
          <h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
            登录眩生花 AI 助手
          </h3>
          <UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1"
                   @click="modal.close()"/>
        </div>
      </template>

      <UTabs :items="items" class="w-full">
        <template #default="{ item, index, selected }">
          <div class="flex items-center gap-2 relative truncate">
            <UIcon :name="item.icon" class="w-4 h-4 flex-shrink-0"/>
            <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 #item="{ 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">
              <UFormGroup label="用户名" name="username" required>
                <UInput v-model="accountForm.username" :disabled="final_loading" required/>
              </UFormGroup>
              <UFormGroup label="密码" name="password" required>
                <UInput v-model="accountForm.password" :disabled="final_loading" type="password" required/>
              </UFormGroup>
            </div>

            <div v-else-if="item.key === 'sms'" class="space-y-3">
              <UFormGroup 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="gray"/>
                </UButtonGroup>
              </UFormGroup>
              <Transition name="pin-root">
                <div v-if="sms_triggered">
                  <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"
                      :autofocus="index === 0"
                    />
                  </PinInputRoot>
                </div>
              </Transition>
            </div>

            <template #footer v-if="item.key !== 'sms'">
              <UButton type="submit" color="black" :loading="final_loading">
                登录
              </UButton>
            </template>
          </UCard>
        </template>
      </UTabs>

    </UCard>
  </UModal>
</template>

<style scoped>
.pin-root-enter-active,
.pin-root-leave-active {
  @apply transition duration-500;
}

.pin-root-enter-from,
.pin-root-leave-to {
  @apply opacity-0 -translate-y-2;
}

.pin-input {
  @apply w-full md:w-16 aspect-square rounded text-center shadow caret-transparent;
  @apply outline-0 ring-indigo-500 focus:ring font-bold;
}

.pin-label {
  @apply block text-sm font-medium text-gray-700 dark:text-gray-200 after:content-['*'] after:ms-0.5 after:text-red-500 dark:after:text-red-400;
}
</style>