<template>
  <div class="login">
    <van-nav-bar title="自然人开票" />

    <div class="login-content">
      <div class="text">感谢您参加{{ pubName }}项目，请您登录系统开具发票。</div>

      <div class="bold-text">已注册电子税务局</div>

      <div class="form">
        <!-- 手机号输入 -->
        <van-cell-group inset class="grop">
          <van-field
            class="input"
            v-model="formData.mobile"
            placeholder="请输入手机号"
            clearable
            type="tel"
            maxlength="30"
            @update:model-value="onInputMobile"
          />
        </van-cell-group>

        <!-- 密码 -->
        <van-cell-group inset class="grop">
          <van-field
            class="input"
            v-model="formData.password"
            placeholder="请输入密码"
            clearable
            :type="passwordType"
            maxlength="30"
          >
            <template #right-icon>
              <span @click="switchPasswordType">
                <van-icon :name="passwordType === 'password' ? 'eye' : 'closed-eye'" />
              </span>
            </template>
          </van-field>
        </van-cell-group>

        <!-- 验证码输入 + 按钮 -->
        <van-cell-group inset class="grop">
          <van-field
            class="input code-input"
            v-model="formData.code"
            placeholder="请输入验证码"
            clearable
            type="tel"
            maxlength="6"
            @update:model-value="onInputCode"
          />
          <button class="code-btn" :disabled="isCounting || !formData.mobile" @click="sendCode">
            {{ isCounting ? countDown + 's后重发' : '获取验证码' }}
          </button>
        </van-cell-group>
        <div class="tips">如忘记密码，请下载电子税务局APP进行密码找回</div>

        <!-- 同意协议 -->
        <div class="agree">
          <label>
            <van-checkbox v-model="agree" checked-color="#0072f8" shape="square" icon-size="4vw">
              我已阅读并同意
              <a @click.self.stop="toAgreement('auth')">《授权协议》</a>
              <a @click.self.stop="toAgreement('privacy')">《隐私权政策》</a>
            </van-checkbox>
          </label>
        </div>

        <!-- 登录按钮 -->
        <div class="login-btn btn" @click="loginBtn">登录</div>
      </div>

      <div class="bold-text">未注册电子税务局</div>
      <div class="register-btn btn" @click="registerUrl">立即注册</div>
      <div class="footer">客服电话：18611825128（微信同号）</div>
      <div class="footer">技术支持：要易云（北京）科技有限公司</div>

      <!-- 失败弹窗 -->
      <ModernDialog
        v-model:show="showDialog"
        title="提示"
        :message="codeMessage"
        cancelText="返回继续登录"
        @cancel="onCancel"
      />

      <!-- 注册弹窗 -->
      <ModernDialog
        v-model:show="loginDialog"
        title="提示"
        :message="loginMessage"
        cancelText="返回"
        @cancel="loginCancel"
        confirmText="立即注册"
        @confirm="loginConfirm"
      />

      <!-- 修改密码弹窗 -->
      <ModernDialog
        v-model:show="changePasswordDialog"
        title="提示"
        message="您的登录被税局识别到存在登录异地税局风险，请下载“电子税务局”APP并完成修改密码再次返回进行登录。"
        cancelText="我知道了"
        @cancel="changePasswordDCancel"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onBeforeMount, onActivated } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { showFailToast, showSuccessToast, showToast, showLoadingToast } from 'vant'
import {
  getPubNameApi,
  sendEtsSmsApi,
  loginEtssmsApi,
  registerUrlApi,
} from '@/services/modules/login'
import { getStatusApi } from '@/services/modules/invoiceInformation'
import type {
  SendTtsSmsRequest,
  LoginEtssmsRequest,
  RegisterUrlRequest,
} from '@/services/modules/login/type.d'
import { useUserStore } from '@/stores/modules/user'
import { useDebounceFn } from '@/utils/util'
import { REGISTER_URL_KEY } from '@/constants/storage'
import ModernDialog from '@/components/ModernDialog.vue'

const userStore = useUserStore()
const router = useRouter()
const route = useRoute()

const passwordType = ref<'text' | 'password'>('password')
const switchPasswordType = () => {
  passwordType.value = passwordType.value === 'password' ? 'text' : 'password'
}

/* 表单数据 */
const formData = reactive<LoginEtssmsRequest>({
  mobile: '',
  code: '',
  pushRecordId: '',
  password: '',
})

const sendEtsSms = reactive<SendTtsSmsRequest>({
  mobile: '',
  pushRecordId: '',
  password: '',
})

/* 限制手机号只能输入数字，最多 30 位 */
const onInputMobile = (val: string) => {
  formData.mobile = val.replace(/\D/g, '').slice(0, 30)
}

/* 限制验证码只能输入数字，最多 6 位 */
const onInputCode = (val: string) => {
  formData.code = val.replace(/\D/g, '').slice(0, 6)
}

/* 是否同意协议 */
const agree = ref(false)

/* 验证码按钮逻辑 */
const isCounting = ref(false)
const countDown = ref(60)
let timer: number | undefined

const sending = ref(false)
const showDialog = ref(false)
const codeMessage = ref()
const onCancel = () => {
  showDialog.value = false
}

const changePasswordDialog = ref(false)

const changePasswordDCancel = () => {
  changePasswordDialog.value = false
}
/* 发送验证码 */
const sendCode = async () => {
  if (sending.value) return
  if (!/^1\d{10}$/.test(formData.mobile)) {
    showToast('请输入正确的手机号')
    return
  }
  if (!formData.password) {
    showToast('密码不能为空')
    return
  }
  sending.value = true
  const toast = showLoadingToast({ message: '发送中…', forbidClick: true, duration: 3000 })
  sendEtsSms.mobile = formData.mobile
  sendEtsSms.password = formData.password
  try {
    const res = await sendEtsSmsApi(sendEtsSms)
    if (res.code === 0 && res.data) {
      showSuccessToast('发送成功')
      startCountDown()
    } else {
      codeMessage.value = res.msg
      showDialog.value = true
    }
    toast.close()
  } catch (err: any) {
    toast.close()

    const { code, message } = err
    if (code === 401) {
      loginMessage.value = message
      loginDialog.value = true
      return
    }

    showFailToast(err?.message || '获取验证码失败')
  } finally {
    sending.value = false
  }
}

/* 倒计时逻辑 */
const startCountDown = () => {
  isCounting.value = true
  countDown.value = 60
  timer = window.setInterval(() => {
    countDown.value--
    if (countDown.value <= 0) {
      isCounting.value = false
      clearInterval(timer)
    }
  }, 1000)
}

const loginDialog = ref(false)
const loginMessage = ref('')
const loginCancel = () => {
  loginDialog.value = false
}

const loginConfirm = () => {
  registerUrl()
}
/* 登录逻辑 */
const loginBtn = useDebounceFn(async () => {
  if (!formData.mobile) {
    showFailToast('请输入手机号')
    return
  }
  if (!formData.password) {
    showFailToast('密码不能为空')
    return
  }
  if (!formData.code) {
    showFailToast('验证码不能为空')
    return
  }
  if (!agree.value) {
    showFailToast('请勾选阅读并同意')
    return
  }
  const toast = showLoadingToast({
    message: '登录中…',
    forbidClick: true,
    duration: 0,
  })

  // 已提交状态映射
  const isSubmitStatusMap = ['PENDING', 'FINISHED', 'RED_INK_ENTRY', 'NOT_APPROVED', 'DISCARD']
  const isSubmitEventStatusMap = [
    'SUBMITTED',
    'PENDING_PAYMENT',
    'PAID',
    'PENDING_FINAL_INVOICING',
    'INVOICE_FAILED',
    'FINAL_INVOICE_SUBMITTED',
    'INVOICE_DOWNLOADABLE',
  ]

  try {
    const res: any = await loginEtssmsApi(formData)
    if (res?.access_token) {
      toast.close()
      userStore.setAccessToken(res.access_token)
      const statusRes = await getStatusApi({ pushRecordId: formData.pushRecordId })
      // 修改认证下的状态内容，如果已经提交，跳转到成功页
      if (statusRes.code == 0) {
        const { invoiceStatus, eventStatus } = statusRes.data
        const isInvoiceSubmitted = invoiceStatus && isSubmitStatusMap.includes(invoiceStatus)
        const isEventSubmitted = eventStatus && isSubmitEventStatusMap.includes(eventStatus)
        if (isInvoiceSubmitted && isEventSubmitted) {
          return router.replace({
            path: '/login-success',
          })
        }
      }
      router.replace({ path: '/invoice-information' })
    } else if (res.code == 401) {
      loginMessage.value = res.msg
      loginDialog.value = true
    } else if (res.code == 402) {
      changePasswordDialog.value = true
    }
  } catch (err: any) {
    toast.close()
    const { code, message } = err || {}
    if (code && message) {
      showFailToast(message)
    }
  }
}, 800)

// 获取注册链接
const registerUrlParams = ref<RegisterUrlRequest>({
  areaId: '',
  returnUrl: '',
  pushRecordId: '',
})
const registerUrl = useDebounceFn(async () => {
  try {
    const res = await registerUrlApi(registerUrlParams.value)
    if (res.code === 0 && res.data.url) {
      // 保存一次性链接
      sessionStorage.setItem(REGISTER_URL_KEY, res.data.url as string)
      return router.push({ path: 'register' })
    }
    showFailToast('获取注册链接失败')
  } catch (err: any) {
    showFailToast(err?.message || '获取注册链接失败')
  }
}, 800)
// 项目名称
const pubName = ref('')

const getPubName = async () => {
  try {
    const res = await getPubNameApi({
      pushRecordId: sendEtsSms.pushRecordId,
    })
    if (res.code === 0) {
      pubName.value = res.data.projectName
      registerUrlParams.value.areaId = res.data.cityCode
      userStore.setNeedFaceId(res.data.needFaceId)
      registerUrlParams.value.pushRecordId = sendEtsSms.pushRecordId
    } else {
      codeMessage.value = res.msg
      showDialog.value = true
    }
  } catch (err) {
    console.log('err', err)
  }
}
/* 协议跳转 */
const toAgreement = (type: string) => {
  router.push({
    path: '/agreement',
    query: { type },
  })
}

const resetLoginState = () => {
  formData.mobile = ''
  formData.code = ''
  agree.value = false
  isCounting.value = false
  countDown.value = 60
  sending.value = false
  showDialog.value = false
  loginDialog.value = false
  changePasswordDialog.value = false

  if (timer) {
    clearInterval(timer)
    timer = undefined
  }
}

onActivated(() => {
  if (route.query.from === 'reject') {
    resetLoginState()
    router.replace({
      path: route.path,
      query: {
        pushRecordId: route.query.pushRecordId,
      },
    })
  }
})

onBeforeMount(() => {
  registerUrlParams.value.returnUrl = `${location.origin}/h5${route.fullPath}`
  const pushRecordId = route.query.pushRecordId
  if (!pushRecordId) {
    userStore.setPushRecordId('')
    formData.pushRecordId = ''
    sendEtsSms.pushRecordId = ''
    showToast('登录链接存在不完整或者输入错误')
    return
  }
  userStore.setPushRecordId(pushRecordId as string)
  sendEtsSms.pushRecordId = pushRecordId as string
  formData.pushRecordId = pushRecordId as string
  getPubName()
})
</script>

<style lang="scss" scoped>
.login {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, #ffffff 0%, #f5f7fb 100%);
  overflow-x: hidden;

  .van-nav-bar {
    background-color: #fff;
    border-bottom: 1px solid #f2f2f2;
    font-weight: 600;
  }

  .login-content {
    flex: 1;
    padding: 6vw 6vw 12vw;
    display: flex;
    flex-direction: column;
    align-items: center;

    .text {
      width: 90%;
      font-size: 4vw;
      text-align: center;
      line-height: 6vw;
      color: #333;
      margin-top: 8vw;
      margin-bottom: 6vw;
    }

    .bold-text {
      width: 100%;
      font-weight: 700;
      font-size: 4.5vw;
      text-align: left;
      color: #222;
      margin: 4vw 0 2vw;
    }

    .form {
      width: 96%;
      margin-top: 20px;
      background: #fff;
      border-radius: 3vw;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
      padding: 6vw 4vw;
      margin-bottom: 8vw;

      .grop {
        margin-top: 3vw;
        display: flex;
        align-items: center;
        justify-content: space-between;
      }

      .input {
        width: 100%;
        border-radius: 6vw;
        border: 1px solid #e5e5e5;
        padding-left: 5vw;
        font-size: 3.8vw;
        background: #fff;
        transition: 0.3s;
        &:focus {
          border-color: #0072f8;
          box-shadow: 0 0 8px rgba(254, 120, 61, 0.3);
        }
      }

      .code-input {
        width: 55%;
      }

      .code-btn {
        background: linear-gradient(90deg, #0072f8 0%, #3a9fff 100%);
        border: none;
        border-radius: 25px;
        height: 9vw;
        width: 30%;
        color: #fff;
        font-weight: 600;
        font-size: 3.4vw;
        cursor: pointer;
        transition: all 0.3s;
        &:active {
          opacity: 0.85;
        }
        &:disabled {
          background: #ccc;
          cursor: not-allowed;
        }
      }
      .tips {
        font-size: 3vw;
        color: #999;
        margin-top: 3vw;
        text-align: center;
      }

      .agree {
        text-align: left;
        font-size: 3vw;
        line-height: 5vw;
        margin: 4vw 0;
        color: #666;
        padding-left: 36px;
        .custom-checkbox {
          accent-color: #0072f8;
        }
        label {
          display: flex;
          align-items: center;
          flex-wrap: wrap;
          input {
            width: 3.5vw;
            height: 3.5vw;
            margin-right: 6px;
          }
        }
        a {
          color: #0072f8;
          text-decoration: none;
          margin-left: 2px;
        }
      }
    }

    .btn {
      box-sizing: border-box;
      width: 80%;
      height: 12vw;
      border-radius: 6vw;
      color: #fff;
      font-size: 4vw;
      line-height: 12vw;
      text-align: center;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s ease;
      margin: 4vw 0;
      &:active {
        transform: scale(0.98);
      }
    }

    .login-btn {
      margin: 0 auto;
      background: linear-gradient(90deg, #0072f8 0%, #3a9fff 100%);
      box-shadow: 0 4px 12px rgba(0, 114, 248, 0.25);
    }

    .register-btn {
      background: linear-gradient(90deg, #ff8036 0%, #ffa253 100%);
      box-shadow: 0 4px 12px rgba(255, 128, 54, 0.3);
    }

    .footer {
      width: 100%;
      text-align: center;
      color: #999;
      font-size: 3vw;
      margin-top: 25px;
    }
  }
}
</style>
