<template>
	<view class="calculator">
		<customNavbar title="计算器" :showHome="true" />

		<textarea class="display" 	auto-height v-model="expression" disabled />

		<view class="keys">
			<view
				v-for="item in keys"
				:key="item"
				class="key"
				:class="{
					operator: operators.includes(item) || item === '%',
					equal: item === '=',
					control: ['C','⌫'].includes(item)
				}"
				@click="press(item)"
				@touchstart="onTouchStart(item)"
				@touchend="onTouchEnd"
			>
				{{ item }}
			</view>
		</view>
	</view>
</template>

<script>
export default {
	data() {
		return {
			expression: '',
			timer: null,
			operators: ['+', '-', '*', '/'],
			keys: [
				'7','8','9','/',
				'4','5','6','*',
				'1','2','3','-',
				'0','.','%','+',
				'C','⌫','='
			]
		}
	},
	methods: {
		press(key) {
			const ops = this.operators

			if (key === 'C') {
				this.expression = ''
				return
			}

			if (key === '⌫') {
				return
			}

			if (key === '%') {
				this.applyPercent()
				return
			}

			if (key === '=') {
				if (!this.expression) return

				while (/[+\-*/.]$/.test(this.expression)) {
					this.expression = this.expression.slice(0, -1)
				}

				if (!/^\d+(\.\d+)?([+\-*/]\d+(\.\d+)?)*$/.test(this.expression)) {
					uni.showToast({ title: '格式错误', icon: 'none' })
					return
				}

				this.expression = this.calculate(this.expression)
				return
			}

			if (ops.includes(key)) {
				if (!this.expression) return
				if (ops.includes(this.expression.slice(-1))) {
					this.expression =
						this.expression.slice(0, -1) + key
					return
				}
			}

			if (key === '.') {
				const last = this.expression.split(/[+\-*/]/).pop()
				if (last.includes('.')) return
			}

			this.expression += key
		},

		/* 长按删除 */
		onTouchStart(key) {
			if (key !== '⌫') return

			this.expression = this.expression.slice(0, -1)

			this.timer = setInterval(() => {
				if (!this.expression) {
					clearInterval(this.timer)
					return
				}
				this.expression = this.expression.slice(0, -1)
			}, 120)
		},

		onTouchEnd() {
			clearInterval(this.timer)
			this.timer = null
		},

		/* 百分号处理（核心） */
		applyPercent() {
			if (!this.expression) return

			const match = this.expression.match(/(\d+(\.\d+)?)([+\-*/])?(\d+(\.\d+)?)?$/)
			if (!match) return

			const base = parseFloat(match[1])
			const op = match[3]
			const value = match[4] ? parseFloat(match[4]) : null

			let percentValue

			if (!op) {
				percentValue = base / 100
				this.expression = percentValue.toString()
				return
			}

			if (op === '+' || op === '-') {
				percentValue = base * (value / 100)
			} else {
				percentValue = value / 100
			}

			this.expression =
				this.expression.slice(0, match.index) +
				base +
				op +
				percentValue
		},

		/* 计算（无 eval） */
		calculate(exp) {
			const nums = exp.split(/[\+\-\*\/]/).map(Number)
			const ops = exp.match(/[\+\-\*\/]/g) || []

			for (let i = 0; i < ops.length; ) {
				if (ops[i] === '*' || ops[i] === '/') {
					const r =
						ops[i] === '*'
							? nums[i] * nums[i + 1]
							: nums[i] / nums[i + 1]

					nums.splice(i, 2, r)
					ops.splice(i, 1)
				} else {
					i++
				}
			}

			let result = nums[0]
			for (let i = 0; i < ops.length; i++) {
				result =
					ops[i] === '+'
						? result + nums[i + 1]
						: result - nums[i + 1]
			}

			return Number(result.toFixed(10)).toString()
		}
	}
}
</script>

<style scoped>
.calculator {
	padding: 30rpx;
	padding-top: 175rpx;
	background: #f7f8fa;
	min-height: 100vh;
}

.display {
	font-size: 70rpx;
	font-weight: 600;
	min-height: 400rpx;
	width: 95%;
	border-radius: 12rpx;
	background: #fff;
	padding: 0 24rpx;
	margin-bottom: 30rpx;
	box-shadow: 0 8rpx 20rpx rgba(0,0,0,0.08);
}

.keys {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 24rpx;
}

.key {
	background: #ffffff;
	text-align: center;
	padding: 36rpx 0;
	font-size: 70rpx;
	font-weight: 500;
	border-radius: 16rpx;
	box-shadow: 0 10rpx 20rpx rgba(0,0,0,0.08);
}

.key:active {
	transform: scale(0.95);
}

.operator {
	background: #ffe8d9;
	color: #ff7a18;
	box-shadow: 0 10rpx 20rpx rgba(255,122,24,0.35);
	font-size: 70rpx;
}

.control {
	background: #ff4d4f;
	color: #fff;
	box-shadow: 0 10rpx 20rpx rgba(255,77,79,0.4);
}

.equal {
    width: 215%;
	background: linear-gradient(135deg, #4facfe, #00f2fe);
	color: #fff;
	font-size: 70rpx;
	font-weight: 600;
	box-shadow: 0 12rpx 28rpx rgba(79,172,254,0.5);
}
</style>
