﻿<template>
	<view class="app-page" :class="themeClass">
		<section-card title="月度预算" subtitle="设置总预算与分类预算，控制消费节奏">
			<view class="budget-hero surface-strong">
				<view>
					<text class="tiny-text">本月总预算</text>
					<text class="budget-number">{{ formatCurrency(totalBudget) }}</text>
				</view>
				<view>
					<text class="tiny-text">本月已支出</text>
					<text class="budget-number negative">{{ formatCurrency(spentTotal) }}</text>
				</view>
			</view>
			<view class="progress-track">
				<view class="progress-fill" :style="{ width: usagePercentWidth }"></view>
			</view>
			<view class="budget-foot">
				<text class="tiny-text">使用进度 {{ usagePercentLabel }}</text>
				<text class="tiny-text">{{ remainingBudget >= 0 ? `剩余 ${formatCurrency(remainingBudget)}` : `已超支 ${formatCurrency(Math.abs(remainingBudget))}` }}</text>
			</view>
			<view class="budget-foot secondary-foot">
				<text class="tiny-text">{{ totalBudget ? `日均可用 ${formatCurrency(dailyAllowance)}` : '设置预算后可查看剩余额度分配' }}</text>
			</view>
			<view class="editor-row">
				<view class="input-shell"><input v-model="totalBudgetInput" type="digit" placeholder="输入本月总预算" /></view>
				<view class="primary-button save-btn" @click="saveTotalBudget">保存</view>
			</view>
		</section-card>

		<section-card v-if="overBudgetRows.length" title="超支提醒" subtitle="当前分类预算已被突破，建议尽快调整">
			<view class="alert-list">
				<view v-for="item in overBudgetRows" :key="item.id" class="alert-item">
					<text class="alert-title">{{ item.name }}</text>
					<text class="alert-text">预算 {{ formatCurrency(item.budget) }}，已支出 {{ formatCurrency(item.spent) }}</text>
				</view>
			</view>
		</section-card>

		<section-card title="分类预算" subtitle="为高频分类分别设置预算，减少超支风险">
			<view class="category-list">
				<view v-for="item in categoryRows" :key="item.id" class="category-card surface-strong">
					<view class="category-head">
						<view class="category-title-row">
							<view class="category-dot" :style="{ background: item.color }"></view>
							<text class="category-title">{{ item.name }}</text>
						</view>
						<text class="tiny-text">已花 {{ formatCurrency(item.spent) }}</text>
					</view>
					<view class="progress-track thin-track">
						<view class="progress-fill" :style="{ width: item.progressWidth }"></view>
					</view>
					<view class="budget-foot">
						<text class="tiny-text">预算 {{ formatCurrency(item.budget) }}</text>
						<text class="tiny-text" :class="item.budget > 0 && item.spent > item.budget ? 'negative' : ''">{{ item.progressLabel }}</text>
					</view>
					<view class="editor-row">
						<view class="input-shell"><input v-model="categoryBudgetDrafts[item.id]" type="digit" placeholder="设置分类预算" /></view>
						<view class="ghost-button save-btn" @click="saveCategoryBudget(item.id)">保存</view>
					</view>
				</view>
			</view>
		</section-card>

		<app-tab-bar current="budget" />
	</view>
</template>

<script setup>
import { computed, reactive, ref, watch } from 'vue'
import SectionCard from '../../components/SectionCard.vue'
import AppTabBar from '../../components/AppTabBar.vue'
import { useAppStore } from '../../utils/store'
import { getDaysLeftInMonth, isSameMonth, toMonthKey } from '../../utils/date'
import { clampPercent, formatCurrency, formatPercent } from '../../utils/money'

const store = useAppStore()
const currentMonth = computed(() => toMonthKey())
const themeClass = computed(() => (store.state.settings.theme === 'dark' ? 'theme-dark' : ''))
const totalBudgetInput = ref(String(store.state.budgets.total || ''))
const categoryBudgetDrafts = reactive({})

const expenseBills = computed(() => store.state.bills.filter((item) => item.type === 'expense' && isSameMonth(item.date, currentMonth.value)))
const spentTotal = computed(() => expenseBills.value.reduce((sum, item) => sum + Number(item.amount), 0))
const totalBudget = computed(() => Number(store.state.budgets.total) || 0)
const remainingBudget = computed(() => totalBudget.value - spentTotal.value)
const dailyAllowance = computed(() => Math.max(remainingBudget.value, 0) / Math.max(1, getDaysLeftInMonth(currentMonth.value)))
const usagePercentLabel = computed(() => (totalBudget.value ? formatPercent(spentTotal.value / Math.max(totalBudget.value, 1)) : '未设置'))
const usagePercentWidth = computed(() => clampPercent(spentTotal.value / Math.max(totalBudget.value || 1, 1)))

const categoryRows = computed(() => store.state.categories.expense.map((category) => {
	const spent = expenseBills.value
		.filter((item) => item.categoryId === category.id)
		.reduce((sum, item) => sum + Number(item.amount), 0)
	const budget = Number(store.state.budgets.categoryBudgets[category.id] || 0)
	return {
		...category,
		spent,
		budget,
		progressLabel: budget ? formatPercent(spent / Math.max(budget, 1)) : '未设置',
		progressWidth: clampPercent(spent / Math.max(budget || 1, 1))
	}
}))

const overBudgetRows = computed(() => categoryRows.value.filter((item) => item.budget > 0 && item.spent > item.budget))

watch(
	() => store.state.budgets.total,
	(value) => {
		totalBudgetInput.value = String(value || '')
	},
	{ immediate: true }
)

watch(
	categoryRows,
	(rows) => {
		rows.forEach((item) => {
			categoryBudgetDrafts[item.id] = String(item.budget || '')
		})
	},
	{ immediate: true }
)

function saveTotalBudget() {
	store.setBudgetTotal(totalBudgetInput.value)
	uni.showToast({ title: '总预算已保存', icon: 'none' })
}

function saveCategoryBudget(categoryId) {
	store.setCategoryBudget(categoryId, categoryBudgetDrafts[categoryId])
	uni.showToast({ title: '分类预算已保存', icon: 'none' })
}
</script>

<style lang="scss" scoped>
.budget-hero,
.category-card {
	padding: 24rpx;
	border-radius: 24rpx;
}

.budget-hero,
.category-head,
.category-title-row,
.budget-foot,
.editor-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16rpx;
}

.secondary-foot {
	margin-top: 10rpx;
}

.budget-number {
	display: block;
	margin-top: 10rpx;
	font-size: 34rpx;
	font-weight: 700;
	color: var(--text-primary);
}

.progress-track {
	overflow: hidden;
	height: 18rpx;
	margin: 24rpx 0 16rpx;
	border-radius: 999rpx;
	background: var(--surface-muted);
}

.thin-track {
	height: 14rpx;
	margin: 18rpx 0 14rpx;
}

.progress-fill {
	height: 100%;
	border-radius: inherit;
	background: linear-gradient(90deg, #5f8df5 0%, #1f6f5f 100%);
}

.editor-row {
	margin-top: 20rpx;
}

.editor-row .input-shell {
	flex: 1;
}

.save-btn {
	flex: 0 0 180rpx;
}

.alert-list,
.category-list {
	display: flex;
	flex-direction: column;
	gap: 18rpx;
}

.alert-item {
	padding: 20rpx 22rpx;
	border-radius: 22rpx;
	background: var(--danger-soft);
}

.alert-title {
	font-size: 28rpx;
	font-weight: 600;
	color: var(--danger);
}

.alert-text {
	display: block;
	margin-top: 8rpx;
	font-size: 22rpx;
	color: var(--danger);
}

.category-dot {
	width: 16rpx;
	height: 16rpx;
	border-radius: 50%;
}

.category-title {
	font-size: 28rpx;
	font-weight: 600;
	color: var(--text-primary);
}
</style>
