<template>
  <view class="page">
    <view class="tabs-main">
      <view
        v-for="(t, i) in mainTabs"
        :key="i"
        class="tab"
        :class="{ active: mainTab === i }"
        @click="mainTab = i; hint=''; sentOtp=false"
      >
        {{ t }}
      </view>
    </view>

    <!-- 登录 -->
    <scroll-view v-show="mainTab === 0" scroll-y class="scroll">
      <view class="subtabs">
        <view
          v-for="(t, i) in loginSubs"
          :key="'l' + i"
          class="subtab"
          :class="{ on: loginSub === i }"
          @click="loginSub = i; hint=''; sentOtp=false"
        >
          {{ t }}
        </view>
      </view>

      <view v-show="loginSub === 0" class="panel">
        <input v-model="l.user" class="inp" placeholder="账号" />
        <input v-model="l.pwd" class="inp" password placeholder="密码" />
        <view v-if="pwCodeOn" class="cap-row">
          <input v-model="l.coode" class="inp flex1" placeholder="图片验证码" />
          <image v-if="capPw" class="cap-img" :src="capPw" @click="loadCap('pw')" />
          <button class="mini" type="default" @click="loadCap('pw')">换一张</button>
        </view>
      </view>

      <view v-show="loginSub === 1" class="panel">
        <input v-model="l.phone" class="inp" type="number" placeholder="手机号" maxlength="11" />
        <view class="cap-row">
          <input v-model="l.smsCoode" class="inp flex1" placeholder="图片验证码" />
          <image v-if="capSms" class="cap-img" :src="capSms" @click="loadCap('sms')" />
          <button class="mini" type="default" @click="loadCap('sms')">换一张</button>
        </view>
        <view class="row">
          <input v-model="l.smsCode" class="inp flex1" type="number" placeholder="短信验证码" />
          <button class="send" :disabled="smsCd > 0" @click="sendSms('login')">
            {{ smsCd > 0 ? smsCd + 's' : '获取短信' }}
          </button>
        </view>
      </view>

      <view v-show="loginSub === 2" class="panel">
        <input v-model="l.email" class="inp" placeholder="邮箱" />
        <view class="cap-row">
          <input v-model="l.emailCoode" class="inp flex1" placeholder="图片验证码" />
          <image v-if="capEmail" class="cap-img" :src="capEmail" @click="loadCap('email')" />
          <button class="mini" type="default" @click="loadCap('email')">换一张</button>
        </view>
        <view class="row">
          <input v-model="l.emailCode" class="inp flex1" placeholder="邮箱验证码" />
          <button class="send" :disabled="emailCd > 0" @click="sendEmail('login')">
            {{ emailCd > 0 ? emailCd + 's' : '获取邮箱码' }}
          </button>
        </view>
      </view>

      <text class="hint">{{ hint }}</text>
      <button class="primary" @click="doLogin">登录</button>
    </scroll-view>

    <!-- 注册 -->
    <scroll-view v-show="mainTab === 1" scroll-y class="scroll">
      <view class="subtabs">
        <view
          v-for="(t, i) in regSubs"
          :key="'r' + i"
          class="subtab"
          :class="{ on: regSub === i }"
          @click="regSub = i; hint=''; sentOtp=false"
        >
          {{ t }}
        </view>
      </view>

      <view v-show="regSub === 0" class="panel">
        <input v-model="r.user" class="inp" placeholder="账号" />
        <input v-model="r.pwd" class="inp" password placeholder="密码" />
        <input v-model="r.pwd2" class="inp" password placeholder="确认密码" />
        <input v-model="r.mobile" class="inp" type="number" placeholder="手机号（可选）" />
        <picker :range="mibaoList" @change="onMibao">
          <view class="picker">{{ mibaoList[r.mibaoI] }}</view>
        </picker>
        <input v-model="r.mibaoA" class="inp" placeholder="密保答案" />
        <input v-model="r.qq" class="inp" placeholder="QQ（可选）" />
        <input v-model="r.mail" class="inp" placeholder="邮箱（可选）" />
        <input v-model="r.ext" class="inp" placeholder="推广码（可选）" />
        <view v-if="regPwCodeOn" class="cap-row">
          <input v-model="r.coode" class="inp flex1" placeholder="图片验证码" />
          <image v-if="capRegPw" class="cap-img" :src="capRegPw" @click="loadCap('regpw')" />
          <button class="mini" type="default" @click="loadCap('regpw')">换一张</button>
        </view>
      </view>

      <view v-show="regSub === 1" class="panel">
        <input v-model="r.smsUser" class="inp" placeholder="注册账号" />
        <input v-model="r.smsPwd" class="inp" password placeholder="密码" />
        <input v-model="r.smsPwd2" class="inp" password placeholder="确认密码" />
        <input v-model="r.smsPhone" class="inp" type="number" placeholder="手机号" maxlength="11" />
        <view class="cap-row">
          <input v-model="r.smsImgCoode" class="inp flex1" placeholder="图片验证码" />
          <image v-if="capRegSms" class="cap-img" :src="capRegSms" @click="loadCap('regsms')" />
          <button class="mini" type="default" @click="loadCap('regsms')">换一张</button>
        </view>
        <view class="row">
          <input v-model="r.smsOtp" class="inp flex1" type="number" placeholder="短信验证码" />
          <button class="send" :disabled="smsCd > 0" @click="sendSms('register')">
            {{ smsCd > 0 ? smsCd + 's' : '获取短信' }}
          </button>
        </view>
      </view>

      <view v-show="regSub === 2" class="panel">
        <input v-model="r.emUser" class="inp" placeholder="注册账号" />
        <input v-model="r.emPwd" class="inp" password placeholder="密码" />
        <input v-model="r.emPwd2" class="inp" password placeholder="确认密码" />
        <input v-model="r.emAddr" class="inp" placeholder="邮箱" />
        <view class="cap-row">
          <input v-model="r.emImgCoode" class="inp flex1" placeholder="图片验证码" />
          <image v-if="capRegEm" class="cap-img" :src="capRegEm" @click="loadCap('regem')" />
          <button class="mini" type="default" @click="loadCap('regem')">换一张</button>
        </view>
        <view class="row">
          <input v-model="r.emOtp" class="inp flex1" placeholder="邮箱验证码" />
          <button class="send" :disabled="emailCd > 0" @click="sendEmail('register')">
            {{ emailCd > 0 ? emailCd + 's' : '获取邮箱码' }}
          </button>
        </view>
      </view>

      <text class="hint" :class="{ ok: regOk }">{{ hint }}</text>
      <button class="primary" @click="doRegister">注册</button>
    </scroll-view>

    <!-- 找回 -->
    <scroll-view v-show="mainTab === 2" scroll-y class="scroll">
      <view class="subtabs">
        <view
          class="subtab"
          :class="{ on: forgotSub === 0 }"
          @click="forgotSub = 0; hint=''; sentOtp=false"
        >
          短信找回
        </view>
        <view
          class="subtab"
          :class="{ on: forgotSub === 1 }"
          @click="forgotSub = 1; hint=''; sentOtp=false"
        >
          邮箱找回
        </view>
      </view>

      <view v-show="forgotSub === 0" class="panel">
        <input v-model="f.phone" class="inp" type="number" placeholder="手机号" maxlength="11" />
        <view class="cap-row">
          <input v-model="f.smsCoode" class="inp flex1" placeholder="图片验证码" />
          <image v-if="capFsms" class="cap-img" :src="capFsms" @click="loadCap('fsms')" />
          <button class="mini" type="default" @click="loadCap('fsms')">换一张</button>
        </view>
        <view class="row">
          <input v-model="f.smsCode" class="inp flex1" type="number" placeholder="短信验证码" />
          <button class="send" :disabled="smsCd > 0" @click="sendSms('reset')">
            {{ smsCd > 0 ? smsCd + 's' : '获取短信' }}
          </button>
        </view>
      </view>

      <view v-show="forgotSub === 1" class="panel">
        <input v-model="f.email" class="inp" placeholder="邮箱" />
        <view class="cap-row">
          <input v-model="f.emCoode" class="inp flex1" placeholder="图片验证码" />
          <image v-if="capFem" class="cap-img" :src="capFem" @click="loadCap('fem')" />
          <button class="mini" type="default" @click="loadCap('fem')">换一张</button>
        </view>
        <view class="row">
          <input v-model="f.emCode" class="inp flex1" placeholder="邮箱验证码" />
          <button class="send" :disabled="emailCd > 0" @click="sendEmail('reset')">
            {{ emailCd > 0 ? emailCd + 's' : '获取邮箱码' }}
          </button>
        </view>
      </view>

      <input v-model="f.newPwd" class="inp" password placeholder="新密码" />
      <text class="hint" :class="{ ok: regOk }">{{ hint }}</text>
      <button class="primary" @click="doReset">重置密码</button>
    </scroll-view>
  </view>
</template>

<script>
import { getMobileApi } from '@/utils/apiSingleton.js'
import { MIBAO_QUESTIONS } from '@/utils/userConfig.js'

function isPhone(t) {
  return /^1[3-9]\d{9}$/.test((t || '').trim())
}
function isEmail(t) {
  return /^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test((t || '').trim())
}

export default {
  data() {
    return {
      mainTabs: ['登录', '注册', '找回密码'],
      mainTab: 0,
      loginSubs: ['密码登录', '短信登录', '邮箱登录'],
      loginSub: 0,
      regSubs: ['密码注册', '短信注册', '邮箱注册'],
      regSub: 0,
      forgotSub: 0,
      mibaoList: MIBAO_QUESTIONS,
      pwCodeOn: true,
      regPwCodeOn: true,
      capPw: '',
      capSms: '',
      capEmail: '',
      capRegPw: '',
      capRegSms: '',
      capRegEm: '',
      capFsms: '',
      capFem: '',
      hint: '',
      regOk: false,
      sentOtp: false,
      smsCd: 0,
      emailCd: 0,
      smsTimer: null,
      emailTimer: null,
      l: {
        user: '',
        pwd: '',
        coode: '',
        phone: '',
        smsCoode: '',
        smsCode: '',
        email: '',
        emailCoode: '',
        emailCode: ''
      },
      r: {
        user: '',
        pwd: '',
        pwd2: '',
        coode: '',
        mobile: '',
        mibaoI: 0,
        mibaoA: '',
        qq: '',
        mail: '',
        ext: '',
        smsUser: '',
        smsPwd: '',
        smsPwd2: '',
        smsPhone: '',
        smsImgCoode: '',
        smsOtp: '',
        emUser: '',
        emPwd: '',
        emPwd2: '',
        emAddr: '',
        emImgCoode: '',
        emOtp: ''
      },
      f: {
        phone: '',
        smsCoode: '',
        smsCode: '',
        email: '',
        emCoode: '',
        emCode: '',
        newPwd: ''
      }
    }
  },
  onLoad() {
    this.initFlags()
  },
  onUnload() {
    this.clearTimers()
  },
  methods: {
    clearTimers() {
      if (this.smsTimer) clearInterval(this.smsTimer)
      if (this.emailTimer) clearInterval(this.emailTimer)
      this.smsTimer = null
      this.emailTimer = null
    },
    async initFlags() {
      const api = getMobileApi()
      const loginOn = await api.isCodeEnabled('login')
      const regOn = await api.isCodeEnabled('register')
      this.pwCodeOn = loginOn
      this.regPwCodeOn = regOn
      this.loadCap('pw')
      this.loadCap('sms')
      this.loadCap('email')
      this.loadCap('regpw')
      this.loadCap('regsms')
      this.loadCap('regem')
      this.loadCap('fsms')
      this.loadCap('fem')
    },
    onMibao(e) {
      this.r.mibaoI = Number(e.detail.value)
    },
    capUrlField(which) {
      const m = {
        pw: 'capPw',
        sms: 'capSms',
        email: 'capEmail',
        regpw: 'capRegPw',
        regsms: 'capRegSms',
        regem: 'capRegEm',
        fsms: 'capFsms',
        fem: 'capFem'
      }
      return m[which] || 'capPw'
    },
    async loadCap(which) {
      const api = getMobileApi()
      const { url, err } = await api.captchaURL()
      const field = this.capUrlField(which)
      if (!url) {
        this[field] = ''
        return
      }
      const sep = url.indexOf('?') >= 0 ? '&' : '?'
      this[field] = url + sep + '_=' + Date.now()
    },
    startSmsCd() {
      this.clearTimers()
      this.smsCd = 60
      this.smsTimer = setInterval(() => {
        this.smsCd--
        if (this.smsCd <= 0) {
          clearInterval(this.smsTimer)
          this.smsTimer = null
        }
      }, 1000)
    },
    startEmailCd() {
      this.clearTimers()
      this.emailCd = 60
      this.emailTimer = setInterval(() => {
        this.emailCd--
        if (this.emailCd <= 0) {
          clearInterval(this.emailTimer)
          this.emailTimer = null
        }
      }, 1000)
    },
    async sendSms(scene) {
      const api = getMobileApi()
      let mobile = ''
      let coode = ''
      if (scene === 'login') {
        mobile = this.l.phone.trim()
        coode = this.l.smsCoode
      } else if (scene === 'register') {
        mobile = this.r.smsPhone.trim()
        coode = this.r.smsImgCoode
      } else {
        mobile = this.f.phone.trim()
        coode = this.f.smsCoode
      }
      if (!isPhone(mobile)) {
        this.hint = '请先输入正确手机号'
        this.regOk = false
        return
      }
      if (!coode) {
        this.hint = '请输入图片验证码'
        this.regOk = false
        return
      }
      const r = await api.client.sendSmsCode(scene, mobile, '86', coode)
      const d = api.wrap(r, '发送短信验证码失败')
      this.hint = d.message
      this.regOk = false
      this.sentOtp = d.code === 200
      if (this.sentOtp) this.startSmsCd()
    },
    async sendEmail(scene) {
      const api = getMobileApi()
      let email = ''
      let coode = ''
      if (scene === 'login') {
        email = this.l.email.trim()
        coode = this.l.emailCoode
      } else if (scene === 'register') {
        email = this.r.emAddr.trim()
        coode = this.r.emImgCoode
      } else {
        email = this.f.email.trim()
        coode = this.f.emCoode
      }
      if (!isEmail(email)) {
        this.hint = '请先输入正确邮箱'
        this.regOk = false
        return
      }
      if (!coode) {
        this.hint = '请输入图片验证码'
        this.regOk = false
        return
      }
      const r = await api.client.sendEmailCode(scene, email, coode)
      const d = api.wrap(r, '发送邮箱验证码失败')
      this.hint = d.message
      this.regOk = false
      this.sentOtp = d.code === 200
      if (this.sentOtp) this.startEmailCd()
    },
    async doLogin() {
      const api = getMobileApi()
      this.hint = ''
      this.regOk = false
      if (this.loginSub === 0) {
        if (!this.l.user.trim()) {
          this.hint = '请输入账号'
          return
        }
        if (!this.l.pwd) {
          this.hint = '请输入密码'
          return
        }
        if (this.pwCodeOn && !this.l.coode.trim()) {
          this.hint = '请输入图片验证码'
          return
        }
        const coode = this.pwCodeOn ? this.l.coode : ''
        const r = await api.client.login(this.l.user.trim(), this.l.pwd, coode)
        const d = api.wrap(r, '账号密码登录失败')
        this.hint = d.message
        if (d.code === 1011 || d.code === 9908) {
          uni.reLaunch({ url: '/pages/main/home' })
        }
        return
      }
      if (this.loginSub === 1) {
        if (!isPhone(this.l.phone)) {
          this.hint = '手机号格式不正确'
          return
        }
        if (!this.sentOtp) {
          this.hint = '请先发送短信验证码'
          return
        }
        if (this.l.smsCode.trim().length < 4) {
          this.hint = '请输入短信验证码'
          return
        }
        const r = await api.client.loginSms(
          this.l.phone.trim(),
          '86',
          this.l.smsCode.trim(),
          this.l.smsCoode
        )
        const d = api.wrap(r, '短信登录失败')
        this.hint = d.message
        if (d.code === 1011 || d.code === 9908) {
          uni.reLaunch({ url: '/pages/main/home' })
        }
        return
      }
      if (!isEmail(this.l.email)) {
        this.hint = '邮箱格式不正确'
        return
      }
      if (!this.sentOtp) {
        this.hint = '请先发送邮箱验证码'
        return
      }
      if (this.l.emailCode.trim().length < 4) {
        this.hint = '请输入邮箱验证码'
        return
      }
      const r = await api.client.loginEmail(
        this.l.email.trim(),
        this.l.emailCode.trim(),
        this.l.emailCoode
      )
      const d = api.wrap(r, '邮箱登录失败')
      this.hint = d.message
      if (d.code === 1011 || d.code === 9908) {
        uni.reLaunch({ url: '/pages/main/home' })
      }
    },
    async doRegister() {
      const api = getMobileApi()
      this.regOk = false
      if (this.regSub === 0) {
        if (!this.r.user.trim()) {
          this.hint = '请输入账号'
          return
        }
        if (this.r.pwd !== this.r.pwd2) {
          this.hint = '两次密码不一致'
          return
        }
        if (!this.r.mibaoA.trim()) {
          this.hint = '请填写密保答案'
          return
        }
        if (this.regPwCodeOn && !this.r.coode.trim()) {
          this.hint = '请输入图片验证码'
          return
        }
        const coode = this.regPwCodeOn ? this.r.coode : ''
        const q = this.mibaoList[this.r.mibaoI]
        const r = await api.client.reg(
          this.r.user.trim(),
          this.r.pwd,
          this.r.pwd2,
          coode,
          this.r.mobile.trim(),
          q,
          this.r.mibaoA.trim(),
          this.r.qq.trim(),
          this.r.mail.trim(),
          this.r.ext.trim()
        )
        const d = api.wrap(r, '账号注册失败')
        this.hint = d.message
        this.regOk = d.message && d.message.indexOf('成功') >= 0
        return
      }
      if (this.regSub === 1) {
        if (!this.r.smsUser.trim()) {
          this.hint = '请输入注册账号'
          return
        }
        if (this.r.smsPwd !== this.r.smsPwd2) {
          this.hint = '两次密码不一致'
          return
        }
        if (!isPhone(this.r.smsPhone)) {
          this.hint = '手机号格式不正确'
          return
        }
        if (!this.sentOtp) {
          this.hint = '请先发送短信验证码'
          return
        }
        if (this.r.smsOtp.trim().length < 4) {
          this.hint = '请输入短信验证码'
          return
        }
        const r = await api.client.registerSms(
          this.r.smsUser.trim(),
          this.r.smsPhone.trim(),
          '86',
          this.r.smsOtp.trim(),
          this.r.smsPwd,
          this.r.smsPwd2,
          this.r.smsImgCoode
        )
        const d = api.wrap(r, '短信注册失败')
        this.hint = d.message
        this.regOk = d.message && d.message.indexOf('成功') >= 0
        return
      }
      if (!this.r.emUser.trim()) {
        this.hint = '请输入注册账号'
        return
      }
      if (this.r.emPwd !== this.r.emPwd2) {
        this.hint = '两次密码不一致'
        return
      }
      if (!isEmail(this.r.emAddr)) {
        this.hint = '邮箱格式不正确'
        return
      }
      if (!this.sentOtp) {
        this.hint = '请先发送邮箱验证码'
        return
      }
      if (this.r.emOtp.trim().length < 4) {
        this.hint = '请输入邮箱验证码'
        return
      }
      const r = await api.client.registerEmail(
        this.r.emUser.trim(),
        this.r.emAddr.trim(),
        this.r.emOtp.trim(),
        this.r.emPwd,
        this.r.emPwd2,
        this.r.emImgCoode
      )
      const d = api.wrap(r, '邮箱注册失败')
      this.hint = d.message
      this.regOk = d.message && d.message.indexOf('成功') >= 0
    },
    async doReset() {
      const api = getMobileApi()
      this.regOk = false
      const pwd = this.f.newPwd
      if (this.forgotSub === 0) {
        if (!isPhone(this.f.phone)) {
          this.hint = '手机号格式不正确'
          return
        }
        if (!this.sentOtp) {
          this.hint = '请先发送短信验证码'
          return
        }
        if (this.f.smsCode.trim().length < 4) {
          this.hint = '请输入短信验证码'
          return
        }
        const r = await api.client.resetSmsPwd(
          this.f.phone.trim(),
          '86',
          this.f.smsCode.trim(),
          pwd,
          pwd,
          this.f.smsCoode
        )
        const d = api.wrap(r, '短信找回失败')
        this.hint = d.message
        this.regOk = d.message && d.message.indexOf('成功') >= 0
        return
      }
      if (!isEmail(this.f.email)) {
        this.hint = '邮箱格式不正确'
        return
      }
      if (!this.sentOtp) {
        this.hint = '请先发送邮箱验证码'
        return
      }
      if (this.f.emCode.trim().length < 4) {
        this.hint = '请输入邮箱验证码'
        return
      }
      const r = await api.client.resetEmailPwd(
        this.f.email.trim(),
        this.f.emCode.trim(),
        pwd,
        pwd,
        this.f.emCoode
      )
      const d = api.wrap(r, '邮箱找回失败')
      this.hint = d.message
      this.regOk = d.message && d.message.indexOf('成功') >= 0
    }
  }
}
</script>

<style scoped>
.page {
  min-height: 100vh;
  background: linear-gradient(165deg, var(--theme-grad-a), var(--theme-grad-b));
  padding: 24rpx;
  box-sizing: border-box;
}
.tabs-main {
  display: flex;
  border-radius: 12rpx;
  overflow: hidden;
  margin-bottom: 20rpx;
  background: rgba(255, 255, 255, 0.25);
}
.tab {
  flex: 1;
  text-align: center;
  padding: 22rpx 0;
  color: #fff;
  font-size: 28rpx;
}
.tab.active {
  background: rgba(255, 255, 255, 0.95);
  color: var(--theme-primary);
  font-weight: 600;
}
.scroll {
  max-height: calc(100vh - 120rpx);
}
.subtabs {
  display: flex;
  flex-wrap: wrap;
  gap: 12rpx;
  margin-bottom: 16rpx;
}
.subtab {
  padding: 12rpx 20rpx;
  border-radius: 999rpx;
  background: rgba(255, 255, 255, 0.35);
  color: #fff;
  font-size: 24rpx;
}
.subtab.on {
  background: #fff;
  color: var(--theme-primary);
}
.panel {
  background: rgba(255, 255, 255, 0.92);
  border-radius: 16rpx;
  padding: 20rpx;
  margin-bottom: 16rpx;
}
.inp {
  border: 1px solid #e0e0e0;
  border-radius: 10rpx;
  padding: 18rpx 20rpx;
  margin-bottom: 16rpx;
  font-size: 28rpx;
}
.flex1 {
  flex: 1;
  margin-bottom: 0;
}
.cap-row {
  display: flex;
  align-items: center;
  gap: 12rpx;
  margin-bottom: 16rpx;
}
.cap-img {
  width: 200rpx;
  height: 72rpx;
  background: #f5f5f5;
}
.mini {
  font-size: 22rpx;
  padding: 0 16rpx;
  line-height: 64rpx;
}
.row {
  display: flex;
  align-items: center;
  gap: 12rpx;
  margin-bottom: 16rpx;
}
.send {
  font-size: 24rpx;
  padding: 0 20rpx;
  line-height: 72rpx;
  background: var(--theme-primary);
  color: #fff;
}
.picker {
  padding: 18rpx 20rpx;
  border: 1px solid #e0e0e0;
  border-radius: 10rpx;
  margin-bottom: 16rpx;
  font-size: 28rpx;
}
.hint {
  display: block;
  color: #c62828;
  font-size: 26rpx;
  margin: 12rpx 0;
  min-height: 36rpx;
}
.hint.ok {
  color: #2e7d32;
}
.primary {
  margin-top: 20rpx;
  background: var(--theme-primary);
  color: #fff;
  border-radius: 12rpx;
}
</style>
