<script lang="ts" setup>
import { refreshPage } from '@/utils/common'
import { reactive, ref } from 'vue'
import { pageUrl, smsTemplateCode } from '@/utils/constants'
import { useAddressStore, useMemberStore, useSettingStore } from '@/stores'
import { isDev } from '@/utils/constants'
import { onLoad, onReady } from '@dcloudio/uni-app'
import {
  miniAppLoginApi,
  quickLoginApi,
  loginByPhone,
  loginByPassword,
  registerApi,
  bindWxInfo,
} from '@/api/login'
import type { loginResult } from '@/types/member'
import { testLoginApi } from '@/api/login'

const form = reactive({
  username: '',
  password: '',
  phone: '',
  sms_captcha_code: '',
  checked: false,
})
// 当前页面操作类型
enum operateTypeEnum {
  login = 'login',
  register = 'register',
}
const operateType = ref(operateTypeEnum.login)
// 切换操作类型
const onChangeOperateType = (type: operateTypeEnum) => {
  operateType.value = type
  resetForm()
}
// 登录方式
enum loginTypeEnum {
  password = 'password',
  phone = 'phone',
  miniapp = 'miniapp',
}
const defaultLoingType =
  uni.getSystemInfoSync().uniPlatform === 'mp-weixin'
    ? loginTypeEnum.miniapp
    : loginTypeEnum.password
const loginType = ref(defaultLoingType)
// 切换登录方式
const onChangeLoginType = (type: loginTypeEnum) => {
  loginType.value = type
  resetForm()
}
// 重置表单
const resetForm = () => {
  form.password = ''
  form.sms_captcha_code = ''
  form.phone = ''
  form.username = ''

  formRef.value.clearValidate()
  formRules.username.rules[0].errorMessage =
    operateType.value === operateTypeEnum.register ? '请输入用户名' : '请输入用户名/手机号码'
}
// 校验协议
const checkAgreement = (): Promise<void> => {
  return new Promise((resolve, reject) => {
    if (form.checked) {
      resolve()
    } else {
      uni.showToast({
        icon: 'none',
        title: '请先阅读并同意相关协议',
      })
      reject('用户未勾选协议')
    }
  })
}
// 登录操作
const login = async (formRef: UniHelper.FormOnSubmitEvent) => {
  try {
    await formRef.validate()
    await checkAgreement()
    if (loginType.value === loginTypeEnum.password) {
      const res = await loginByPassword({
        username: form.username,
        password: form.password,
      })
      loginSuccess(res.result)
    } else if (loginType.value === loginTypeEnum.phone) {
      const res = await loginByPhone({
        phone: form.phone,
        sms_captcha_code: form.sms_captcha_code,
      })
      loginSuccess(res.result)
    }
  } catch (err: any) {
    if (err.data?.msg) {
      uni.showToast({
        title: err.data.msg,
        icon: 'none',
        duration: 3000,
      })
    }
    console.log(err)
  }
}
// 注册
const register = async (ref: any) => {
  try {
    await ref.validate()

    await checkAgreement()

    let login_code = ''
    // #ifdef MP-WEIXIN
    login_code = await getLoginCode()
    // #endif

    const res = await registerApi({
      username: form.username,
      password: form.password,
      phone: form.phone,
      sms_captcha_code: form.sms_captcha_code,
    })

    uni.showToast({
      title: '注册成功',
      icon: 'success',
      mask: true,
    })

    setTimeout(() => {
      refreshPage()
    }, 1500)
  } catch (err: any) {
    console.log(err)
  }
}
// 协议勾选操作
const privacyChange = (e: any) => {
  form.checked = e.detail.value.length ? true : false
}
// 跳转协议内容
const goToRichText = (type: string) => {
  const agreementData = useSettingStore().data.agreement

  let title = ''
  if (type == 'user_agreement') {
    title = '用户协议'
  }
  if (type == 'privacy_agreement') {
    title = '隐私协议'
  }

  uni.navigateTo({
    url: `${pageUrl['rich-text']}?title=${title}&content=
    ${encodeURIComponent(agreementData[type as keyof typeof agreementData])}`,
  })
}
// 表单校验规则
const formRules = {
  username: {
    rules: [
      {
        required: true,
        errorMessage: '请输入用户名/手机号码',
      },
      {
        validateFunction: (rule: any, value: string, data: any, callback: Function) => {
          if (!/^[A-Za-z0-9*]{4,11}$/.test(value)) {
            return callback('用户名要求4~11位，仅能包含字母、数字和 * ')
          }
        },
      },
    ],
  },
  password: {
    rules: [
      { required: true, errorMessage: '请输入密码' },
      {
        validateFunction: (rule: any, value: string, data: any, callback: Function) => {
          if (!/^(?!.*[&<>"'\n\r]).{6,32}$/.test(value)) {
            return callback('密码要求6到32位，不能包含 & < >"')
          }
        },
      },
    ],
  },
  phone: {
    rules: [
      { required: true, errorMessage: '请输入手机号码' },
      {
        validateFunction: (rule: any, value: string, data: any, callback: Function) => {
          if (!/^(1[3-9])\d{9}$/.test(value.toString())) {
            return callback('手机号格式不正确')
          }
        },
      },
    ],
  },
  sms_captcha_code: {
    rules: [{ required: true, errorMessage: '请输入短信验证码' }],
  },
}
const formRef = ref()
onReady(() => {
  formRef.value.setRules(formRules)
})

const resetPwdRef = ref()
const onOpenResetpwdPopup = () => {
  resetPwdRef.value?.open()
}

// #ifdef MP-WEIXIN
const quickLogin = ref(false)
// 通过小程序获取手机号登录
const userLoginByMiniapp: UniHelper.ButtonOnGetphonenumber = async (event) => {
  const code = event.detail.code!
  if (!code) return

  const login_code = await getLoginCode()
  if (login_code == '') {
    uni.showToast({
      icon: 'error',
      title: '登录异常',
    })
    return
  }
  const res = await miniAppLoginApi({ code, login_code })
  if (res.result) {
    loginSuccess(res.result)
  }
}
// 获取登录code
const getLoginCode = async (): Promise<string> => {
  return new Promise((resolve, reject) => {
    uni.login({
      provider: 'weixin',
      onlyAuthorize: true,
      success: function (event) {
        const { code } = event
        resolve(code)
      },
      fail: function (err) {
        console.warn(err)
        quickLogin.value = false
        reject(err)
      },
    })
  })
}
//快捷登录
const doQuickLogin = async (code: string) => {
  const res = await quickLoginApi(code)
  if (Object.keys(res.result).length === 0) {
    quickLogin.value = false
  } else {
    uni.showLoading({
      title: '快捷登录中',
      mask: true,
    })
    setTimeout(() => {
      loginSuccess(res.result)
    }, 1500)
  }
}
// 快捷登录检测
const checkQuickLogin = async () => {
  const login_code = await getLoginCode()
  console.log('获取到的登录code：' + login_code)
  doQuickLogin(login_code).catch((err) => {
    quickLogin.value = false
    console.warn(err)
    // 账号异常
    if (err.data.code === 50001) {
      uni.showModal({
        content: err.data.msg,
        showCancel: false,
        success: function (res) {
          uni.navigateTo({ url: pageUrl['index'] })
        },
      })
    }
  })
}
// #endif

// 测试登录
const testLogin = () => {
  testLoginApi('13312345678').then((res) => {
    loginSuccess(res.result)
  })
}

// 登录成功后处理
const loginSuccess = async (userData: loginResult) => {
  if (Object.keys(userData).length === 0) {
    uni.showToast({
      icon: 'error',
      title: '登录失败',
    })
    return
  }

  useMemberStore().setProfile(userData)

  // #ifdef MP-WEIXIN
  if (!userData.has_openid) {
    const login_code = await getLoginCode()
    console.log('获取到的登录code：' + login_code)
    bindWxInfo({
      login_code,
    })
  }
  // #endif

  uni.showToast({
    icon: 'success',
    title: '登录成功',
  })

  useAddressStore().clearSelectedAddress()

  setTimeout(() => {
    uni.$emit('refreshData')
    uni.navigateBack()
  }, 500)
}

onLoad(() => {
  // #ifdef MP-WEIXIN
  checkQuickLogin()
  // #endif
})
</script>

<template>
  <view class="page">
    <view class="logo">
      <image src="/static/images/logo.png"></image>
    </view>
    <uni-forms ref="formRef" :model="form" validateTrigger="blur">
      <!-- 用户名 -->
      <view v-if="loginType === loginTypeEnum.password || operateType === operateTypeEnum.register">
        <uni-forms-item name="username" class="input">
          <uni-easyinput
            type="text"
            maxlength="32"
            v-model.trim="form.username"
            :placeholder="
              operateType === operateTypeEnum.register ? '请输入用户名' : '请输入用户名/手机号码'
            "
          />
        </uni-forms-item>
      </view>
      <!-- 密码 -->
      <view v-if="loginType === loginTypeEnum.password || operateType === operateTypeEnum.register">
        <uni-forms-item name="password" class="input">
          <uni-easyinput type="password" v-model="form.password" placeholder="请输入密码" />
        </uni-forms-item>
      </view>
      <view v-if="loginType === loginTypeEnum.phone || operateType === operateTypeEnum.register">
        <!-- 手机号码 -->
        <uni-forms-item name="phone" class="input">
          <uni-easyinput v-model="form.phone" maxlength="11" placeholder="请输入手机号码" />
        </uni-forms-item>
        <!-- 验证码 -->
        <shop-sms-captcha
          :phone="form.phone"
          :template_code="
            operateType === operateTypeEnum.login
              ? smsTemplateCode.verifyPhone
              : smsTemplateCode.register
          "
          :username="form.username"
          :password="form.password"
          v-model:sms_captcha="form.sms_captcha_code"
        />
      </view>

      <!-- #ifdef MP-WEIXIN-->
      <view v-if="loginType === loginTypeEnum.miniapp">
        <view class="operate">
          <button
            v-if="form.checked"
            class="button phone active"
            open-type="getPhoneNumber"
            @getphonenumber="userLoginByMiniapp"
          >
            <text class="icon icon-phone" />
            <text style="margin-left: 20rpx">手机号快捷登录</text>
          </button>
          <button v-else class="button phone-disabled" @tap="checkAgreement">
            <text class="icon icon-phone" />
            <text style="margin-left: 20rpx">手机号快捷登录</text>
          </button>
        </view>
      </view>
      <!-- #endif -->

      <view
        v-if="operateType === operateTypeEnum.login && loginType === loginTypeEnum.password"
        class="reset-pwd"
      >
        <text @tap="onOpenResetpwdPopup"> 忘记密码</text>
      </view>

      <view class="operate">
        <view v-if="operateType === operateTypeEnum.login && loginType !== loginTypeEnum.miniapp">
          <button @tap="login(formRef)" :class="form.checked ? 'active' : ''">登录</button>
          <button @tap="onChangeOperateType(operateTypeEnum.register)" class="register">
            去注册
          </button></view
        >
        <view v-if="operateType === operateTypeEnum.register" class="operate">
          <button @click="register(formRef)" :class="form.checked ? 'active' : ''">注册</button>
          <button @tap="onChangeOperateType(operateTypeEnum.login)" class="register">
            回到登录
          </button>
        </view>
      </view>

      <view class="tip">
        <checkbox-group @change="privacyChange">
          <checkbox :checked="form.checked" color="#67CCC4" style="transform: scale(0.7)" />
        </checkbox-group>
        <view>
          我已阅读并同意
          <text class="contract" @tap="goToRichText('user_agreement')">《用户协议》</text> 和
          <text class="contract" @tap="goToRichText('privacy_agreement')">《隐私协议》</text>
        </view>
      </view>
      <view class="extra" v-if="operateType === operateTypeEnum.login">
        <text class="caption"><text class="span">其他登录方式</text></text>
        <view class="options">
          <button class="button" v-if="isDev" @tap="testLogin">
            <image src="/static/icons/test_user.svg" class="icon option-icon" />测试号登录
          </button>
          <button class="icon" @tap="onChangeLoginType(loginTypeEnum.password)">
            <image class="icon option-icon" src="/static/icons/password.svg" />
            密码登录
          </button>
          <button class="icon" @tap="onChangeLoginType(loginTypeEnum.phone)">
            <image class="icon option-icon" src="/static/icons/sms.svg" />
            验证码登录
          </button>
          <!-- #ifdef MP-WEIXIN -->
          <button class="icon" @tap="onChangeLoginType(loginTypeEnum.miniapp)">
            <image class="icon option-icon" src="/static/icons/wechat.svg" />快捷登录
          </button>
          <!-- #endif -->
        </view>
      </view>
    </uni-forms>
  </view>

  <!-- 重置密码 -->
  <shop-reset-password ref="resetPwdRef" v-if="loginType === loginTypeEnum.password" />
</template>

<style lang="scss" scoped>
.page {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);

  .logo {
    display: flex;
    justify-content: center;
    margin-bottom: 40rpx;
    image {
      width: 280rpx;
      height: 280rpx;
      border-radius: 50%;
    }
  }

  .input {
    width: 660rpx;
    display: flex;
  }

  .reset-pwd {
    display: flex;
    justify-content: flex-end;
    color: red;
  }

  .operate {
    margin-top: 60rpx;

    button {
      margin-bottom: 30rpx;
      width: 660rpx;
      height: 80rpx;
      line-height: 80rpx;
      border-radius: 40rpx;
      background: #ddd;
      color: #fff;
      font-size: 14px;
    }

    .active {
      background: #28bb9c;
    }

    .register {
      background: #909399;
    }
  }

  .tip {
    color: #777;
    display: flex;
    align-items: center;
    padding-top: 20rpx;
    font-size: 28rpx;

    .contract {
      color: blue;
    }
  }

  .extra {
    flex: 1;
    padding-top: 100rpx;

    .caption {
      display: flex;
      justify-content: center;
      align-items: center;
      line-height: 0;
      border-top: 0.03125rem solid #ddd;
      font-size: 0.8125rem;
      color: #999;
      position: relative;

      .span {
        background-color: #fff;
        padding: 0 10rpx;
        position: relative;
      }
    }

    .options {
      display: flex;
      justify-content: center;
      align-items: center;
      padding-top: 50rpx;

      button {
        font-size: 24rpx;
        color: #444;
        display: flex;
        flex-direction: column;
        align-items: center;

        padding: 5rpx 10rpx;
        background-color: transparent;

        &::after {
          border: none;
        }
      }

      .option-icon {
        width: 80rpx;
        height: 80rpx;
        padding-bottom: 15rpx;
      }
    }
  }
}
</style>
