<template>
	<passport-screen :title="copy.title" :subtitle="copy.subtitle" :kicker="copy.kicker" :crumb="copy.crumb">
		<view class="pp-signin-tabs">
			<view
				v-for="tab in tabs"
				:key="tab.id"
				class="pp-signin-tabs__item"
				:class="{ 'pp-signin-tabs__item--on': mode === tab.id }"
				@tap="switchMode(tab.id)"
			>
				<text class="pp-signin-tabs__text">{{ tab.label }}</text>
			</view>
		</view>

		<view class="pp-signin-field">
			<text class="pp-signin-field__label">{{ copy.handsetLabel }}</text>
			<view class="pp-signin-field__row">
				<region-picker v-model="region" :title="copy.regionTitle" :search-placeholder="copy.regionSearch" :empty-text="copy.regionEmpty" />
				<input
					v-model="form.handset"
					class="pp-signin-input pp-signin-input--handset"
					:placeholder="copy.handsetPlaceholder"
					placeholder-class="pp-signin-input__placeholder"
					type="number"
					maxlength="15"
					@input="onHandsetInput"
				/>
			</view>
		</view>

		<view v-if="mode === 'secret'" class="pp-signin-field">
			<view class="pp-signin-field__head">
				<text class="pp-signin-field__label">{{ copy.secretLabel }}</text>
				<text class="pp-signin-field__hint" @tap="onForgetTap">{{ copy.forgot }}</text>
			</view>
			<view class="pp-signin-input pp-signin-input--solo">
				<input
					v-model="form.secret"
					class="pp-signin-input__field"
					:placeholder="copy.secretPlaceholder"
					placeholder-class="pp-signin-input__placeholder"
					:password="!secretVisible"
					maxlength="20"
				/>
				<text class="pp-signin-input__action" @tap="secretVisible = !secretVisible">{{ secretVisible ? copy.hide : copy.show }}</text>
			</view>
		</view>

		<view v-else class="pp-signin-field">
			<view class="pp-signin-field__head">
				<text class="pp-signin-field__label">{{ copy.passcodeLabel }}</text>
				<text
					class="pp-signin-field__hint"
					:class="{ 'pp-signin-field__hint--off': !coolReady || sending }"
					@tap="onRequestPasscode"
				>
					{{ coolReady ? (sending ? copy.sending : copy.send) : `${coolLeft}s ${copy.resend}` }}
				</text>
			</view>
			<passcode-grid v-model="form.passcode" :alert="passcodeAlert" @settled="onPasscodeSettled" />
		</view>

		<button
			class="pp-signin-submit"
			:class="{ 'pp-signin-submit--busy': submitting }"
			:disabled="submitting"
			@tap="onSubmit"
		>
			<text class="pp-signin-submit__text">{{ submitting ? copy.submitting : copy.submit }}</text>
		</button>

		<view class="pp-signin-enroll" @tap="goEnroll">
			<text class="pp-signin-enroll__text">{{ copy.enrollCta }}</text>
		</view>

		<policy-pledge
			ref="pledge"
			v-model="form.accepted"
			:prefix="copy.pledgePrefix"
			:terms-label="copy.termsLabel"
			:separator="copy.pledgeJoin"
			:privacy-label="copy.privacyLabel"
		/>

		<template #footer>
			<view class="pp-signin-foot">
				<text class="pp-signin-foot__text">{{ copy.footTip }}</text>
				<text class="pp-signin-foot__cta" @tap="goEnroll">{{ copy.footCta }}</text>
			</view>
		</template>
	</passport-screen>
</template>

<script>
import PassportScreen from '@/components/passport-kit/passport-screen.vue'
import RegionPicker from '@/components/passport-kit/region-picker.vue'
import PasscodeGrid from '@/components/passport-kit/passcode-grid.vue'
import PolicyPledge from '@/components/passport-kit/policy-pledge.vue'
import resendCooldown from '@/common/mixins/resend-cooldown'
import { requestPasscode, sessionByPasscode, sessionByCredential } from '@/features/passport/credential-bridge'
import { auditSigninForm, looksLikeHandset, trimHandset } from '@/features/passport/form-rules'
import { DEFAULT_REGION } from '@/features/passport/region-dialcodes'

export default {
	components: { PassportScreen, RegionPicker, PasscodeGrid, PolicyPledge },
	mixins: [resendCooldown],
	data() {
		return {
			mode: 'passcode',
			region: DEFAULT_REGION,
			form: { handset: '', secret: '', passcode: '', accepted: true },
			secretVisible: false,
			sending: false,
			submitting: false,
			ticketId: '',
			passcodeAlert: false,
			redirect: ''
		}
	},
	computed: {
		copy() {
			const t = this.$t.bind(this)
			return {
				kicker: t('passport.kicker-welcome-back'),
				crumb: t('passport.crumb-signin'),
				title: t('passport.title-signin'),
				subtitle: t('passport.subtitle-signin'),
				handsetLabel: t('passport.label-handset'),
				handsetPlaceholder: t('passport.ph-handset'),
				secretLabel: t('passport.label-secret'),
				secretPlaceholder: t('passport.ph-secret'),
				passcodeLabel: t('passport.label-passcode'),
				send: t('passport.btn-send'),
				sending: t('passport.btn-sending'),
				resend: t('passport.btn-resend-suffix'),
				forgot: t('passport.btn-forgot'),
				show: t('passport.btn-show'),
				hide: t('passport.btn-hide'),
				submit: t('passport.btn-signin'),
				submitting: t('passport.btn-signin-busy'),
				footTip: t('passport.foot-no-account'),
				footCta: t('passport.foot-go-enroll'),
				enrollCta: t('passport.foot-go-reg-cta'),
				regionTitle: t('passport.region-title'),
				regionSearch: t('passport.region-search'),
				regionEmpty: t('passport.region-empty'),
				pledgePrefix: t('passport.pledge-prefix-signin'),
				pledgeJoin: t('passport.pledge-and'),
				termsLabel: t('passport.pledge-terms'),
				privacyLabel: t('passport.pledge-privacy')
			}
		},
		tabs() {
			const t = this.$t.bind(this)
			return [
				{ id: 'passcode', label: t('passport.tab-passcode') },
				{ id: 'secret', label: t('passport.tab-secret') }
			]
		}
	},
	onLoad(query) {
		if (query && (query.mode === 'secret' || query.mode === 'passcode')) {
			this.mode = query.mode
		}
		if (query && query.handset) {
			try {
				this.form.handset = trimHandset(decodeURIComponent(query.handset))
			} catch (_) {
				this.form.handset = trimHandset(query.handset)
			}
		}
		if (query && query.region) {
			try {
				this.region = String(decodeURIComponent(query.region)).replace(/^\+/, '')
			} catch (_) {
				this.region = String(query.region).replace(/^\+/, '')
			}
		}
		if (query && query.redirect) this.redirect = decodeURIComponent(query.redirect)
	},
	methods: {
		switchMode(id) {
			if (this.mode === id) return
			this.mode = id
			this.passcodeAlert = false
		},
		onHandsetInput(e) {
			this.form.handset = trimHandset(e.detail.value)
		},
		onPasscodeSettled() {
			this.passcodeAlert = false
		},
		flashPledge() {
			const node = this.$refs.pledge
			if (node && typeof node.flash === 'function') node.flash()
		},
		toast(msg) {
			if (this.$appKit && this.$appKit.msg) this.$appKit.msg(msg)
			else uni.showToast({ title: msg, icon: 'none' })
		},
		async onRequestPasscode() {
			if (!this.coolReady || this.sending) return
			if (!looksLikeHandset(this.form.handset)) {
				this.toast(this.$t('passport.err-handset'))
				return
			}
			this.sending = true
			try {
				const { ticketId, needHumanCheck } = await requestPasscode({
					scene: 'mobilelogin',
					handset: this.form.handset,
					region: this.region
				})
				if (needHumanCheck) {
					this.toast(this.$t('passport.tip-need-captcha'))
				} else {
					this.ticketId = ticketId
					this.coolStart(60)
					this.toast(this.$t('passport.tip-code-sent'))
				}
			} catch (err) {
				this.toast((err && err.message) || this.$t('passport.tip-code-failed'))
			} finally {
				this.sending = false
			}
		},
		onForgetTap() {
			if (!looksLikeHandset(this.form.handset)) {
				this.toast(this.$t('passport.tip-fill-phone-first'))
				return
			}
			const url = `/pages/passport/recover-phone?handset=${encodeURIComponent(this.form.handset)}&region=${encodeURIComponent(this.region)}`
			uni.navigateTo({ url })
		},
		goEnroll() {
			const params = []
			if (looksLikeHandset(this.form.handset)) {
				params.push(`handset=${encodeURIComponent(this.form.handset)}`)
				params.push(`region=${encodeURIComponent(this.region)}`)
			}
			if (this.redirect) params.push(`redirect=${encodeURIComponent(this.redirect)}`)
			const qs = params.length ? `?${params.join('&')}` : ''
			uni.navigateTo({ url: `/pages/passport/enroll${qs}` })
		},
		async onSubmit() {
			if (this.submitting) return
			const verdict = auditSigninForm({ ...this.form, mode: this.mode })
			if (!verdict.ok) {
				if (verdict.field === 'accepted') this.flashPledge()
				else if (verdict.field === 'passcode') this.passcodeAlert = true
				this.toast(this.$t(verdict.errorKey))
				return
			}

			this.submitting = true
			uni.showLoading({ title: this.copy.submitting, mask: true })
			try {
				let payload
				if (this.mode === 'secret') {
					payload = await sessionByCredential({
						account: this.form.handset,
						secret: this.form.secret,
						ticketId: this.ticketId
					})
				} else {
					payload = await sessionByPasscode({
						handset: this.form.handset,
						region: this.region,
						passcode: this.form.passcode,
						ticketId: this.ticketId
					})
				}
				if (payload) {
					this.$store.dispatch('user/login', payload)
					this.$store.dispatch('cart/sync')
				}
				this.toast(this.$t('passport.tip-signin-ok'))
				this.bounce()
			} catch (err) {
				this.passcodeAlert = this.mode === 'passcode'
				this.toast((err && err.message) || this.$t('passport.tip-signin-failed'))
			} finally {
				this.submitting = false
				uni.hideLoading()
			}
		},
		bounce() {
			const fallback = '/pages/index/index'
			const target = this.redirect || fallback
			setTimeout(() => {
				if (target.startsWith('/pages/index')
					|| target.startsWith('/pages/feed')
					|| target.startsWith('/pages/component')
					|| target.startsWith('/pages/mine')) {
					uni.switchTab({ url: target, fail: () => uni.reLaunch({ url: target }) })
				} else {
					uni.reLaunch({ url: target })
				}
			}, 300)
		}
	}
}
</script>

<style lang="scss">
.pp-signin-tabs {
	position: relative;
	display: flex;
	background: rgba(255, 255, 255, 0.08);
	border-radius: 26rpx;
	padding: 6rpx;
	margin-bottom: 36rpx;
}

.pp-signin-tabs__item {
	flex: 1;
	text-align: center;
	padding: 18rpx 0 22rpx;
	border-radius: 22rpx;
}

.pp-signin-tabs__item--on {
	background: linear-gradient(135deg, rgba(255, 181, 71, 0.85), rgba(255, 77, 106, 0.7));
	box-shadow: 0 12rpx 30rpx rgba(255, 77, 106, 0.25);
}

.pp-signin-tabs__text {
	font-size: 28rpx;
	color: rgba(255, 255, 255, 0.6);
	font-weight: 600;
	letter-spacing: 2rpx;
}

.pp-signin-tabs__item--on .pp-signin-tabs__text {
	color: #1a1f3b;
}

.pp-signin-field {
	margin-bottom: 32rpx;
}

.pp-signin-field__head {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 16rpx;
}

.pp-signin-field__label {
	display: block;
	color: rgba(255, 255, 255, 0.7);
	font-size: 24rpx;
	letter-spacing: 2rpx;
	margin-bottom: 16rpx;
}

.pp-signin-field__head .pp-signin-field__label {
	margin-bottom: 0;
}

.pp-signin-field__hint {
	color: #ffb547;
	font-size: 24rpx;
}

.pp-signin-field__hint--off {
	color: rgba(255, 255, 255, 0.4);
}

.pp-signin-field__row {
	display: flex;
	align-items: stretch;
}

.pp-signin-input {
	height: 96rpx;
	background: rgba(255, 255, 255, 0.08);
	border: 1rpx solid rgba(255, 255, 255, 0.16);
	padding: 0 28rpx;
	font-size: 30rpx;
	color: #fff;
	box-sizing: border-box;
	border-radius: 24rpx;
}

.pp-signin-input--handset {
	flex: 1;
	border-radius: 0 24rpx 24rpx 0;
	border-left: none;
}

.pp-signin-input--solo {
	display: flex;
	align-items: center;
	padding: 0 24rpx;
}

.pp-signin-input__field {
	flex: 1;
	color: #fff;
	font-size: 30rpx;
	background: transparent;
	height: 100%;
}

.pp-signin-input__placeholder {
	color: rgba(255, 255, 255, 0.35);
}

.pp-signin-input__action {
	color: rgba(255, 255, 255, 0.7);
	font-size: 24rpx;
	padding: 12rpx 4rpx;
}

.pp-signin-submit {
	width: 100%;
	height: 104rpx;
	margin-top: 12rpx;
	border-radius: 30rpx;
	background: linear-gradient(135deg, #3d5afe 0%, #6b3df0 50%, #ff4d6a 100%);
	border: none;
	box-shadow: 0 20rpx 60rpx rgba(61, 90, 254, 0.45);
	display: flex;
	align-items: center;
	justify-content: center;
}

.pp-signin-submit::after {
	border: none;
}

.pp-signin-submit--busy {
	opacity: 0.7;
}

.pp-signin-submit__text {
	color: #fff;
	font-size: 32rpx;
	font-weight: 700;
	letter-spacing: 4rpx;
}

.pp-signin-enroll {
	margin-top: 20rpx;
	height: 96rpx;
	border-radius: 30rpx;
	border: 1rpx solid rgba(255, 181, 71, 0.45);
	background: rgba(255, 181, 71, 0.1);
	display: flex;
	align-items: center;
	justify-content: center;
}

.pp-signin-enroll__text {
	color: #ffb547;
	font-size: 30rpx;
	font-weight: 700;
	letter-spacing: 3rpx;
}

.pp-signin-foot {
	display: flex;
	align-items: center;
	justify-content: center;
}

.pp-signin-foot__text {
	color: rgba(255, 255, 255, 0.55);
	font-size: 24rpx;
}

.pp-signin-foot__cta {
	color: #ffb547;
	font-size: 26rpx;
	font-weight: 700;
	margin-left: 12rpx;
	padding: 10rpx 16rpx;
	border-radius: 24rpx;
	background: rgba(255, 181, 71, 0.18);
}
</style>
