<template>
	<view class="login-page">
		<view class="page-inner">
			<view class="header">
				<text class="title">欢迎回来</text>
				<text class="subtitle">登录云泽，开启你的旅程</text>
			</view>

			<view class="tabs">
				<view
					class="tab"
					:class="{ active: loginType === 'phone' }"
					@tap="loginType = 'phone'"
				>手机登录</view>
				<view
					class="tab"
					:class="{ active: loginType === 'account' }"
					@tap="loginType = 'account'"
				>账号登录</view>
			</view>

			<view class="form-card">
				<view class="form">
					<view class="field">
						<u-input
							v-model="tenantName"
							placeholder="请输入租户名称"
							border="none"
							color="#303133"
							:customStyle="inputStyle"
							:placeholderStyle="placeholderStyle"
						/>
					</view>

					<template v-if="loginType === 'phone'">
						<view class="field">
							<u-input
								v-model="phone"
								placeholder="请输入手机号"
								type="number"
								maxlength="11"
								border="none"
								color="#303133"
								:customStyle="inputStyle"
								:placeholderStyle="placeholderStyle"
							>
								<template #prefix>
									<text class="prefix">+86</text>
								</template>
							</u-input>
						</view>
						<view class="field field-row">
							<u-input
								v-model="smsCode"
								placeholder="请输入验证码"
								type="number"
								maxlength="6"
								border="none"
								color="#303133"
								:customStyle="inputStyle"
								:placeholderStyle="placeholderStyle"
							/>
							<text
								class="code-link"
								:class="{ disabled: countdown > 0 || sendingCode }"
								@tap="sendPhoneCode"
							>{{ countdown > 0 ? `${countdown}s 后重发` : (sendingCode ? '发送中' : '获取验证码') }}</text>
						</view>
					</template>

					<template v-else>
						<view class="field">
							<u-input
								v-model="username"
								placeholder="请输入账号"
								border="none"
								color="#303133"
								:customStyle="inputStyle"
								:placeholderStyle="placeholderStyle"
							/>
						</view>
						<view class="field">
							<u-input
								v-model="password"
								placeholder="请输入密码"
								type="password"
								border="none"
								color="#303133"
								:customStyle="inputStyle"
								:placeholderStyle="placeholderStyle"
							/>
						</view>
						<!-- 后台开启短信/邮箱登录校验时展示 -->
						<view v-if="needLoginCode" class="field field-row">
							<u-input
								v-model="verifyCode"
								placeholder="请输入登录验证码"
								type="number"
								maxlength="8"
								border="none"
								color="#303133"
								:customStyle="inputStyle"
								:placeholderStyle="placeholderStyle"
							/>
							<text
								class="code-link"
								:class="{ disabled: countdown > 0 || sendingCode }"
								@tap="sendAccountVerifyCode"
							>{{ countdown > 0 ? `${countdown}s 后重发` : (sendingCode ? '发送中' : '获取验证码') }}</text>
						</view>
						<view v-if="verifyHint" class="verify-hint">
							<text>{{ verifyHint }}</text>
						</view>
						<view class="remember-row" @tap="rememberMe = !rememberMe">
							<view class="remember-dot" :class="{ on: rememberMe }">
								<text v-if="rememberMe" class="remember-check">✓</text>
							</view>
							<text class="remember-text">记住我</text>
						</view>
					</template>

					<view class="btn-primary" :class="{ disabled: submitting }" @tap="handleLogin">
						{{ submitting ? '登录中...' : '登 录' }}
					</view>

					<view class="link-row">
						<text class="link" @tap="goRegister">注册账号</text>
						<text class="link" @tap="goForget">忘记密码</text>
					</view>
				</view>
			</view>

			<view class="agreement" @tap="agreed = !agreed">
				<view class="agree-dot" :class="{ on: agreed }">
					<text v-if="agreed" class="agree-check">✓</text>
				</view>
				<text class="agree-text">
					登录即表示同意
					<text class="agree-link">《用户协议》</text>
					和
					<text class="agree-link">《隐私政策》</text>
				</text>
			</view>
		</view>
	</view>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'
import {
	login,
	loginBySms,
	sendLoginCode,
	fetchVerifyConfig
} from '@/api/auth.js'
import {
	loginSuccess,
	isLoggedIn,
	setTenantName,
	getTenantName,
	getRememberLogin,
	saveRememberLogin,
	clearRememberLogin
} from '@/utils/auth.js'
import { showGeetest4 } from '@/utils/geetest.js'

const loginType = ref('account')
const tenantName = ref('')
const phone = ref('')
const smsCode = ref('')
const username = ref('')
const password = ref('')
const verifyCode = ref('')
const agreed = ref(true)
const rememberMe = ref(false)
const countdown = ref(0)
const sendingCode = ref(false)
const submitting = ref(false)
const openVerify = ref(false)
const verifyType = ref('')
let timer = null

const inputStyle = {
	backgroundColor: 'transparent',
	padding: '0 8rpx',
	height: '96rpx',
	fontSize: '28rpx'
}
const placeholderStyle = 'color: #909399; font-size: 28rpx'

const needLoginCode = computed(() => {
	return openVerify.value && (verifyType.value === 'sms' || verifyType.value === 'email')
})

const needGeetest = computed(() => {
	return loginType.value === 'account' && !needLoginCode.value
})

const verifyHint = computed(() => {
	if (!openVerify.value) return ''
	if (verifyType.value === 'sms') return '已开启短信验证，请先获取验证码'
	if (verifyType.value === 'email') return '已开启邮箱验证，请先获取验证码'
	return ''
})

onMounted(async () => {
	if (isLoggedIn()) {
		uni.reLaunch({ url: '/pages/dashboard/dashboard' })
		return
	}
	const remembered = getRememberLogin()
	if (remembered.rememberMe) {
		rememberMe.value = true
		tenantName.value = remembered.tenantName
		username.value = remembered.account
		password.value = remembered.password
	} else {
		tenantName.value = getTenantName()
	}
	const cfg = await fetchVerifyConfig()
	openVerify.value = cfg.openVerify
	verifyType.value = cfg.verifyType
})

onUnmounted(() => {
	if (timer) clearInterval(timer)
})

function startCountdown() {
	countdown.value = 60
	if (timer) clearInterval(timer)
	timer = setInterval(() => {
		countdown.value--
		if (countdown.value <= 0) {
			clearInterval(timer)
			timer = null
		}
	}, 1000)
}

async function sendPhoneCode() {
	if (countdown.value > 0 || sendingCode.value) return
	if (!tenantName.value.trim()) {
		uni.showToast({ title: '请输入租户名称', icon: 'none' })
		return
	}
	if (!/^1\d{10}$/.test(phone.value)) {
		uni.showToast({ title: '请输入正确手机号', icon: 'none' })
		return
	}
	sendingCode.value = true
	try {
		await sendLoginCode({
			tenant_name: tenantName.value.trim(),
			account: phone.value.trim(),
			channel: 'sms'
		})
		uni.showToast({ title: '验证码已发送', icon: 'success' })
		startCountdown()
	} catch {
		// toast 已在 request 中处理
	} finally {
		sendingCode.value = false
	}
}

async function sendAccountVerifyCode() {
	if (countdown.value > 0 || sendingCode.value) return
	if (!tenantName.value.trim()) {
		uni.showToast({ title: '请输入租户名称', icon: 'none' })
		return
	}
	if (!username.value.trim()) {
		uni.showToast({ title: '请输入账号', icon: 'none' })
		return
	}
	const channel = verifyType.value === 'email' ? 'email' : 'sms'
	sendingCode.value = true
	try {
		await sendLoginCode({
			tenant_name: tenantName.value.trim(),
			account: username.value.trim(),
			channel
		})
		uni.showToast({ title: '验证码已发送', icon: 'success' })
		startCountdown()
	} catch {
		// handled
	} finally {
		sendingCode.value = false
	}
}

function navigateAfterLogin() {
	uni.showToast({ title: '登录成功', icon: 'success' })
	setTimeout(() => {
		uni.reLaunch({ url: '/pages/dashboard/dashboard' })
	}, 400)
}

async function submitAccountLogin(geetestResult = null) {
	if (!username.value.trim()) {
		uni.showToast({ title: '请输入账号', icon: 'none' })
		return false
	}
	if (!password.value.trim()) {
		uni.showToast({ title: '请输入密码', icon: 'none' })
		return false
	}
	if (needLoginCode.value && !verifyCode.value.trim()) {
		uni.showToast({ title: '请输入登录验证码', icon: 'none' })
		return false
	}

	const payload = {
		tenant_name: tenantName.value.trim(),
		account: username.value.trim(),
		password: password.value
	}
	if (needLoginCode.value) {
		payload.code = verifyCode.value.trim()
	}
	if (geetestResult) {
		Object.assign(payload, geetestResult)
	}

	const data = await login(payload)
	setTenantName(tenantName.value.trim())
	loginSuccess({
		token: data.token,
		user: data.user
	})
	if (rememberMe.value) {
		saveRememberLogin({
			tenantName: tenantName.value.trim(),
			account: username.value.trim(),
			password: password.value
		})
	} else {
		clearRememberLogin()
	}
	return true
}

async function handleLogin() {
	if (submitting.value) return
	if (!agreed.value) {
		uni.showToast({ title: '请先同意用户协议', icon: 'none' })
		return
	}
	if (!tenantName.value.trim()) {
		uni.showToast({ title: '请输入租户名称', icon: 'none' })
		return
	}

	submitting.value = true
	try {
		if (loginType.value === 'phone') {
			if (!/^1\d{10}$/.test(phone.value)) {
				uni.showToast({ title: '请输入正确手机号', icon: 'none' })
				return
			}
			if (!smsCode.value || smsCode.value.length < 4) {
				uni.showToast({ title: '请输入验证码', icon: 'none' })
				return
			}
			const data = await loginBySms({
				tenant_name: tenantName.value.trim(),
				phone: phone.value.trim(),
				code: smsCode.value.trim()
			})
			setTenantName(tenantName.value.trim())
			loginSuccess({
				token: data.token,
				user: data.user || { phone: phone.value, nickname: '用户' + phone.value.slice(-4) }
			})
			navigateAfterLogin()
			return
		}

		if (needGeetest.value) {
			if (!username.value.trim()) {
				uni.showToast({ title: '请输入账号', icon: 'none' })
				return
			}
			if (!password.value.trim()) {
				uni.showToast({ title: '请输入密码', icon: 'none' })
				return
			}
			try {
				const geetestResult = await showGeetest4()
				const ok = await submitAccountLogin(geetestResult)
				if (ok) navigateAfterLogin()
			} catch (err) {
				const msg = err?.message || '人机验证失败'
				if (msg !== '人机验证未通过') {
					uni.showToast({ title: msg, icon: 'none' })
				}
			}
			return
		}

		const ok = await submitAccountLogin()
		if (ok) navigateAfterLogin()
	} catch {
		// toast 已处理
	} finally {
		submitting.value = false
	}
}

function goRegister() {
	uni.navigateTo({ url: '/pages/login/register' })
}

function goForget() {
	uni.navigateTo({ url: '/pages/login/forget' })
}
</script>

<style lang="scss" scoped>
@import '@/src/styles/page-common.scss';

.login-page {
	min-height: 100vh;
	background: $color-bg-page;
}

.page-inner {
	padding: 0 48rpx;
	padding-top: calc(var(--status-bar-height, 44px) + 80rpx);
}

.header {
	margin-bottom: 64rpx;
}

.title {
	display: block;
	font-size: 48rpx;
	font-weight: 600;
	color: $color-text;
}

.subtitle {
	display: block;
	font-size: 28rpx;
	color: $color-text-muted;
	margin-top: 12rpx;
}

.tabs {
	display: flex;
	background: $color-card;
	border-radius: $radius-md;
	padding: 6rpx;
	margin-bottom: 32rpx;
	box-shadow: $shadow-card;
}

.tab {
	flex: 1;
	text-align: center;
	font-size: 28rpx;
	color: $color-text-secondary;
	padding: 18rpx 0;
	border-radius: $radius-sm;

	&.active {
		color: $color-primary;
		font-weight: 600;
		background: $color-primary-bg;
	}
}

.form-card {
	@include card;
	padding: 32rpx 28rpx;
}

.form {
	display: flex;
	flex-direction: column;
	gap: 24rpx;
}

.field {
	background: $color-bg-page;
	border-radius: $radius-md;
	padding: 0 24rpx;
	overflow: hidden;
}

.field-row {
	display: flex;
	align-items: center;
}

.prefix {
	font-size: 28rpx;
	color: $color-text;
	padding-right: 20rpx;
	margin-right: 20rpx;
	border-right: 1rpx solid $color-border;
}

.code-link {
	flex-shrink: 0;
	font-size: 26rpx;
	color: $color-primary;
	padding-left: 16rpx;
	white-space: nowrap;

	&.disabled {
		color: $color-text-muted;
	}
}

.verify-hint {
	font-size: 22rpx;
	color: $color-text-muted;
	line-height: 1.5;
	padding: 0 4rpx;
}

.remember-row {
	display: flex;
	align-items: center;
	gap: 12rpx;
	padding: 4rpx;
}

.remember-dot {
	width: 32rpx;
	height: 32rpx;
	border-radius: 50%;
	border: 1rpx solid $color-border;
	background: $color-card;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;

	&.on {
		background: $color-primary;
		border-color: $color-primary;
	}
}

.remember-check {
	font-size: 18rpx;
	color: #fff;
}

.remember-text {
	font-size: 26rpx;
	color: $color-text-secondary;
}

.btn-primary {
	height: 96rpx;
	background: $color-primary;
	border-radius: $radius-md;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 32rpx;
	font-weight: 600;
	color: #fff;
	margin-top: 8rpx;

	&:active {
		background: $color-primary-dark;
	}

	&.disabled {
		opacity: 0.7;
	}
}

.link-row {
	display: flex;
	justify-content: space-between;
	padding: 8rpx 4rpx 0;
}

.link {
	font-size: 26rpx;
	color: $color-primary;
}

.agreement {
	display: flex;
	align-items: flex-start;
	gap: 12rpx;
	margin-top: 32rpx;
	padding-bottom: 60rpx;
}

.agree-dot {
	width: 32rpx;
	height: 32rpx;
	border-radius: 50%;
	border: 1rpx solid $color-border;
	background: $color-card;
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	margin-top: 2rpx;

	&.on {
		background: $color-primary;
		border-color: $color-primary;
	}
}

.agree-check {
	font-size: 18rpx;
	color: #fff;
}

.agree-text {
	font-size: 24rpx;
	color: $color-text-muted;
	line-height: 1.7;
}

.agree-link {
	color: $color-primary;
}
</style>
