<template>
	<view class="passcode-grid" :class="'passcode-grid--' + theme" @tap="focusInput">
		<view
			v-for="(_, idx) in cells"
			:key="idx"
			class="passcode-grid__cell"
			:class="{
				'passcode-grid__cell--cursor': focused && idx === cursorAt,
				'passcode-grid__cell--filled': idx < length,
				'passcode-grid__cell--alert': alert && !disabled
			}"
		>
			<text v-if="cells[idx]" class="passcode-grid__char">{{ cells[idx] }}</text>
			<view v-else-if="focused && idx === cursorAt" class="passcode-grid__caret" />
		</view>

		<input
			ref="capture"
			class="passcode-grid__capture"
			type="number"
			:value="value"
			:focus="focused"
			:maxlength="cellCount"
			:disabled="disabled"
			@input="onCapture"
			@blur="onBlur"
			@focus="onFocus"
		/>
	</view>
</template>

<script>
export default {
	name: 'PasscodeGrid',
	props: {
		value: { type: String, default: '' },
		cellCount: { type: Number, default: 6 },
		disabled: { type: Boolean, default: false },
		alert: { type: Boolean, default: false },
		/** dark：通行证深色页；light：账号安全浅色页 */
		theme: { type: String, default: 'dark' }
	},
	data() {
		return {
			focused: false
		}
	},
	computed: {
		length() {
			return String(this.value || '').length
		},
		cursorAt() {
			return Math.min(this.length, this.cellCount - 1)
		},
		cells() {
			const slots = new Array(this.cellCount).fill('')
			const seq = String(this.value || '').slice(0, this.cellCount).split('')
			seq.forEach((ch, i) => {
				slots[i] = ch
			})
			return slots
		}
	},
	methods: {
		focusInput() {
			if (this.disabled) return
			this.focused = true
			this.$nextTick(() => {
				const node = this.$refs.capture
				if (node && typeof node.focus === 'function') node.focus()
			})
			this.$emit('focus')
		},
		onFocus() {
			this.focused = true
		},
		onBlur() {
			this.focused = false
		},
		onCapture(e) {
			const raw = String(e.detail.value || '').replace(/\D+/g, '').slice(0, this.cellCount)
			this.$emit('input', raw)
			if (raw.length === this.cellCount) this.$emit('settled', raw)
		}
	}
}
</script>

<style lang="scss">
.passcode-grid {
	position: relative;
	display: flex;
	justify-content: space-between;
}

.passcode-grid__cell {
	width: 78rpx;
	height: 96rpx;
	border-radius: 22rpx;
	border: 2rpx solid rgba(255, 255, 255, 0.22);
	background: rgba(255, 255, 255, 0.08);
	box-sizing: border-box;
	display: flex;
	align-items: center;
	justify-content: center;
}

.passcode-grid--light .passcode-grid__cell {
	border-color: #e5e9f2;
	background: #f7f9fc;
}

.passcode-grid__cell--filled {
	border-color: rgba(255, 255, 255, 0.38);
	background: rgba(255, 255, 255, 0.12);
}

.passcode-grid--light .passcode-grid__cell--filled {
	border-color: #4a8cff;
	background: #eef4ff;
}

.passcode-grid__cell--cursor {
	border-color: #ffb547;
	box-shadow: 0 0 24rpx rgba(255, 181, 71, 0.35);
}

.passcode-grid--light .passcode-grid__cell--cursor {
	border-color: #4a8cff;
	box-shadow: 0 0 16rpx rgba(74, 140, 255, 0.25);
}

.passcode-grid__cell--alert {
	border-color: #ff4d6a;
	background: rgba(255, 77, 106, 0.12);
}

.passcode-grid--light .passcode-grid__cell--alert {
	border-color: #ef4444;
	background: #fef2f2;
}

.passcode-grid__char {
	font-size: 40rpx;
	font-weight: 700;
	color: #fff;
}

.passcode-grid--light .passcode-grid__char {
	color: #1a1d26;
}

.passcode-grid__caret {
	width: 4rpx;
	height: 38rpx;
	background: #ffb547;
	border-radius: 4rpx;
	animation: passcodeBlink 1s steps(2, start) infinite;
}

.passcode-grid--light .passcode-grid__caret {
	background: #4a8cff;
}

.passcode-grid__capture {
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	bottom: 0;
	width: 100%;
	height: 100%;
	opacity: 0;
	color: transparent;
	background: transparent;
	border: 0;
	caret-color: transparent;
	z-index: 2;
}

@keyframes passcodeBlink {
	0% { opacity: 0; }
	50% { opacity: 1; }
	100% { opacity: 0; }
}
</style>
