<template>
	<div class="trade-operation-stats-shop">
		<el-card shadow="hover">
			<template #header
				><div class="card-header"><span>店铺维度统计</span></div></template
			>
			<div class="chart-container">
				<el-card>
					<template #header
						><div class="card-header">销售趋势 - {{ selectedShopName }}</div></template
					>
					<div ref="salesChartRef" class="chart"></div>
				</el-card>
			</div>
			<div class="stats-cards">
				<el-card class="stats-card"
					><div class="stats-card-title">总销售额</div>
					<div class="stats-card-value">{{ statsData.totalSales || 0 }}</div>
					<div class="stats-card-change" :class="{ positive: statsData.salesGrowth > 0, negative: statsData.salesGrowth < 0 }">
						{{ statsData.salesGrowth > 0 ? '+' : '' }}{{ statsData.salesGrowth || 0 }}%
					</div></el-card
				>
				<el-card class="stats-card"
					><div class="stats-card-title">订单量</div>
					<div class="stats-card-value">{{ statsData.orderCount || 0 }}</div>
					<div class="stats-card-change" :class="{ positive: statsData.orderGrowth > 0, negative: statsData.orderGrowth < 0 }">
						{{ statsData.orderGrowth > 0 ? '+' : '' }}{{ statsData.orderGrowth || 0 }}%
					</div></el-card
				>
				<el-card class="stats-card"
					><div class="stats-card-title">退款率</div>
					<div class="stats-card-value">{{ statsData.refundRate || 0 }}%</div>
					<div class="stats-card-change" :class="{ positive: statsData.refundRateChange < 0, negative: statsData.refundRateChange > 0 }">
						{{ statsData.refundRateChange > 0 ? '+' : '' }}{{ statsData.refundRateChange || 0 }}%
					</div></el-card
				>
				<el-card class="stats-card"
					><div class="stats-card-title">物流履约率</div>
					<div class="stats-card-value">{{ statsData.logisticsRate || 0 }}%</div>
					<div class="stats-card-change" :class="{ positive: statsData.logisticsRateGrowth > 0, negative: statsData.logisticsRateGrowth < 0 }">
						{{ statsData.logisticsRateGrowth > 0 ? '+' : '' }}{{ statsData.logisticsRateGrowth || 0 }}%
					</div></el-card
				>
			</div>
			<div class="shop-list">
				<el-card>
					<template #header><div class="card-header">店铺列表</div></template>
					<div class="search-container">
						<el-form :model="searchParams" :inline="true" class="search-form">
							<el-form-item label="店铺搜索">
								<el-input
									v-model="searchParams.shopKeyword"
									placeholder="请输入店铺名称或店铺ID"
									clearable
									@keyup.enter="handleSearch"
								/>
							</el-form-item>
							<el-form-item label="时间范围"
								><el-date-picker
									v-model="searchParams.dateRange"
									type="daterange"
									range-separator="至"
									start-placeholder="开始日期"
									end-placeholder="结束日期"
									value-format="YYYY-MM-DD"
									:shortcuts="dateShortcuts"
							/></el-form-item>
							<el-form-item label="时间粒度">
								<el-radio-group v-model="searchParams.granularity" class="granularity-group">
									<el-radio-button v-for="option in granularityOptions" :key="option.value" :label="option.value">
										{{ option.label }}
									</el-radio-button>
								</el-radio-group>
							</el-form-item>
							<el-form-item
								><el-button type="primary" @click="handleSearch">查询</el-button><el-button @click="handleReset">重置</el-button></el-form-item
							>
						</el-form>
					</div>
					<el-table :data="pagedShopList" style="width: 100%" @row-click="handleShopClick">
						<el-table-column prop="id" label="店铺ID" width="100" />
						<el-table-column prop="name" label="店铺名称" />
						<el-table-column prop="type" label="店铺类型"
							><template #default="scope"
								><el-tag size="small">{{ scope.row.type === 'physical' ? '线下店铺' : '线上店铺' }}</el-tag></template
							></el-table-column
						>
						<el-table-column prop="status" label="状态"
							><template #default="scope"
								><el-tag size="small" :type="scope.row.status === 'active' ? 'success' : 'danger'">{{
									scope.row.status === 'active' ? '营业中' : '已关闭'
								}}</el-tag></template
							></el-table-column
						>
						<el-table-column label="操作"
							><template #default="scope"
								><el-button type="primary" size="small" @click.stop="handleShopSelect(scope.row.id)">查看详情</el-button></template
							></el-table-column
						>
					</el-table>
					<div class="pagination-container">
						<el-pagination
							v-model:current-page="pagination.currentPage"
							v-model:page-size="pagination.pageSize"
							:page-sizes="[5, 10, 20, 50]"
							layout="total, sizes, prev, pager, next, jumper"
							:total="pagination.total"
							@size-change="handleSizeChange"
							@current-change="handleCurrentChange"
						/>
					</div>
				</el-card>
			</div>
		</el-card>
	</div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from 'vue';
import * as echarts from 'echarts';
const granularityOptions = [
	{ label: '小时', value: 'hour' },
	{ label: '日', value: 'day' },
	{ label: '周', value: 'week' },
	{ label: '月', value: 'month' },
	{ label: '季度', value: 'quarter' },
	{ label: '年', value: 'year' },
];
const searchParams = reactive({ shopId: 'all', shopKeyword: '', dateRange: [], granularity: 'day' });
const dateShortcuts = [
	{
		text: '最近7天',
		value: () => {
			const end = new Date();
			const start = new Date();
			start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
			return [start, end];
		},
	},
	{
		text: '最近30天',
		value: () => {
			const end = new Date();
			const start = new Date();
			start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
			return [start, end];
		},
	},
	{
		text: '最近90天',
		value: () => {
			const end = new Date();
			const start = new Date();
			start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
			return [start, end];
		},
	},
	{
		text: '今年',
		value: () => {
			const end = new Date();
			const start = new Date(new Date().getFullYear(), 0, 1);
			return [start, end];
		},
	},
	{
		text: '去年',
		value: () => {
			const end = new Date(new Date().getFullYear() - 1, 11, 31);
			const start = new Date(new Date().getFullYear() - 1, 0, 1);
			return [start, end];
		},
	},
];
interface Shop {
	id: string;
	name: string;
	type: string;
	status: string;
}
const shopList = ref<Shop[]>([]);
const filteredShopList = computed(() => {
	const keyword = searchParams.shopKeyword.trim().toLowerCase();
	if (!keyword) return shopList.value;
	return shopList.value.filter((shop) => shop.name.toLowerCase().includes(keyword) || String(shop.id).toLowerCase().includes(keyword));
});
const pagination = reactive({ currentPage: 1, pageSize: 5, total: 0 });
const pagedShopList = computed(() =>
	filteredShopList.value.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize)
);
const statsData = reactive({
	totalSales: 1258000,
	orderCount: 5230,
	refundRate: 2.5,
	logisticsRate: 98.2,
	salesGrowth: 15.8,
	orderGrowth: 12.3,
	refundRateChange: -0.5,
	logisticsRateGrowth: 1.2,
});
const salesChartRef = ref();
let salesChart: echarts.ECharts | null = null;
const getMockShopList = () => [
	{ id: '1', name: '店铺A', type: 'physical', status: 'active' },
	{ id: '2', name: '店铺B', type: 'online', status: 'active' },
	{ id: '3', name: '店铺C', type: 'physical', status: 'active' },
	{ id: '4', name: '店铺D', type: 'online', status: 'active' },
	{ id: '5', name: '店铺E', type: 'physical', status: 'active' },
];
const selectedShopName = computed(() => {
	if (searchParams.shopId === 'all') return '全部店铺';
	const shop = shopList.value.find((s) => String(s.id) === searchParams.shopId);
	return shop ? shop.name : '未知店铺';
});
const DAY_IN_MS = 24 * 60 * 60 * 1000;
const toDate = (value?: string | Date) => {
	if (!value) return new Date();
	return value instanceof Date ? new Date(value.getTime()) : new Date(`${value}T00:00:00`);
};
const formatDate = (date: Date) => {
	const year = date.getFullYear();
	const month = `${date.getMonth() + 1}`.padStart(2, '0');
	const day = `${date.getDate()}`.padStart(2, '0');
	return `${year}-${month}-${day}`;
};
const getDateRange = () => {
	if (Array.isArray(searchParams.dateRange) && searchParams.dateRange.length === 2) {
		const [start, end] = searchParams.dateRange as Array<string | Date>;
		return { start: toDate(start), end: toDate(end) };
	}
	const end = new Date();
	const start = new Date(end.getTime() - 6 * DAY_IN_MS);
	return { start, end };
};
const getWeekLabel = (date: Date) => {
	const firstDay = new Date(date.getFullYear(), 0, 1);
	const dayOffset = Math.floor((date.getTime() - firstDay.getTime()) / DAY_IN_MS);
	return `${date.getFullYear()}年第${Math.floor(dayOffset / 7) + 1}周`;
};
const getQuarterLabel = (date: Date) => `${date.getFullYear()}年Q${Math.floor(date.getMonth() / 3) + 1}`;
const buildTrendLabels = () => {
	const { start, end } = getDateRange();
	const labels: string[] = [];
	const cursor = new Date(start.getTime());
	if (searchParams.granularity === 'hour') {
		return Array.from({ length: 24 }, (_, index) => `${index}:00`);
	}
	if (searchParams.granularity === 'day') {
		while (cursor <= end) {
			labels.push(formatDate(cursor));
			cursor.setDate(cursor.getDate() + 1);
		}
		return labels;
	}
	if (searchParams.granularity === 'week') {
		while (cursor <= end) {
			labels.push(getWeekLabel(cursor));
			cursor.setDate(cursor.getDate() + 7);
		}
		return [...new Set(labels)];
	}
	if (searchParams.granularity === 'month') {
		cursor.setDate(1);
		while (cursor <= end) {
			labels.push(`${cursor.getFullYear()}-${`${cursor.getMonth() + 1}`.padStart(2, '0')}`);
			cursor.setMonth(cursor.getMonth() + 1);
		}
		return labels;
	}
	if (searchParams.granularity === 'quarter') {
		cursor.setMonth(Math.floor(cursor.getMonth() / 3) * 3, 1);
		while (cursor <= end) {
			labels.push(getQuarterLabel(cursor));
			cursor.setMonth(cursor.getMonth() + 3);
		}
		return [...new Set(labels)];
	}
	cursor.setMonth(0, 1);
	while (cursor <= end) {
		labels.push(`${cursor.getFullYear()}年`);
		cursor.setFullYear(cursor.getFullYear() + 1);
	}
	return [...new Set(labels)];
};
const getMockSalesTrend = (shopId: string) => {
	const selectedShopId = shopId === 'all' ? 0 : parseInt(shopId, 10) || 0;
	const labels = buildTrendLabels();
	const baseSales = 880000 + selectedShopId * 120000;
	const baseOrders = 3200 + selectedShopId * 380;
	return labels.map((date, index) => {
		const trendFactor = 1 + index * 0.035;
		const seasonalFactor = 0.92 + ((index + selectedShopId) % 5) * 0.045;
		return {
			date,
			sales: Math.round(baseSales * trendFactor * seasonalFactor),
			orders: Math.round(baseOrders * trendFactor * (0.95 + (index % 4) * 0.03)),
		};
	});
};
const syncSelectedShop = () => {
	if (searchParams.shopId === 'all') return;
	const hasSelectedShop = filteredShopList.value.some((shop) => String(shop.id) === searchParams.shopId);
	if (!hasSelectedShop) {
		searchParams.shopId = 'all';
	}
};
const handleSearch = () => {
	pagination.currentPage = 1;
	syncSelectedShop();
	pagination.total = filteredShopList.value.length;
	const salesTrend = getMockSalesTrend(searchParams.shopId);
	const totalSales = salesTrend.reduce((sum, item) => sum + item.sales, 0);
	const totalOrders = salesTrend.reduce((sum, item) => sum + item.orders, 0);
	const selectedShopId = searchParams.shopId === 'all' ? 0 : parseInt(searchParams.shopId, 10) || 0;
	Object.assign(statsData, {
		totalSales,
		orderCount: totalOrders,
		refundRate: Number((2.1 + selectedShopId * 0.18).toFixed(2)),
		logisticsRate: Number((97.2 + selectedShopId * 0.25).toFixed(2)),
		salesGrowth: Number((8 + salesTrend.length * 0.6 + selectedShopId).toFixed(1)),
		orderGrowth: Number((6 + salesTrend.length * 0.45 + selectedShopId * 0.8).toFixed(1)),
		refundRateChange: Number((-0.8 + selectedShopId * 0.12).toFixed(1)),
		logisticsRateGrowth: Number((0.6 + salesTrend.length * 0.08).toFixed(1)),
	});
	initSalesChart(salesTrend);
};
const handleReset = () => {
	searchParams.shopId = 'all';
	searchParams.shopKeyword = '';
	searchParams.dateRange = [];
	searchParams.granularity = 'day';
	pagination.currentPage = 1;
	handleSearch();
};
const handleShopClick = (shop: Shop) => {
	searchParams.shopId = String(shop.id);
	handleSearch();
};
const handleShopSelect = (shopId: string) => {
	searchParams.shopId = String(shopId);
	handleSearch();
};
const handleSizeChange = (size: number) => {
	pagination.pageSize = size;
	pagination.currentPage = 1;
};
const handleCurrentChange = (current: number) => {
	pagination.currentPage = current;
};
const initSalesChart = (salesTrend: any[]) => {
	if (!salesChartRef.value) return;
	if (salesChart) salesChart.dispose();
	salesChart = echarts.init(salesChartRef.value);
	const isSingle = salesTrend.length <= 1;
	salesChart.setOption({
		tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { backgroundColor: '#6a7985' } } },
		legend: { data: ['销售额', '订单量'] },
		grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
		xAxis: { type: 'category', boundaryGap: isSingle, data: salesTrend.map((item) => item.date) },
		yAxis: [
			{ type: 'value', name: '销售额', position: 'left' },
			{ type: 'value', name: '订单量', position: 'right' },
		],
		series: [
			{ name: '销售额', type: 'line', data: salesTrend.map((item) => item.sales), smooth: true, showSymbol: true, symbolSize: isSingle ? 10 : 6 },
			{
				name: '订单量',
				type: 'line',
				yAxisIndex: 1,
				data: salesTrend.map((item) => item.orders),
				smooth: true,
				showSymbol: true,
				symbolSize: isSingle ? 10 : 6,
			},
		],
	});
};
watch(
	() => filteredShopList.value.length,
	(length) => {
		pagination.total = length;
		const maxPage = Math.max(1, Math.ceil(length / pagination.pageSize));
		if (pagination.currentPage > maxPage) {
			pagination.currentPage = maxPage;
		}
	}
);
watch(
	() => searchParams.granularity,
	() => handleSearch()
);
onMounted(() => {
	shopList.value = getMockShopList();
	pagination.total = shopList.value.length;
	handleSearch();
	window.addEventListener('resize', () => salesChart?.resize());
});
</script>

<style scoped>
.trade-operation-stats-shop {
	padding: 20px;
}
.card-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	font-size: 16px;
	font-weight: 600;
}
.search-container {
	margin-bottom: 16px;
}
.search-form {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
}
.search-form :deep(.el-form-item) {
	margin-right: 12px;
	margin-bottom: 12px;
}
.granularity-group {
	flex-wrap: wrap;
}
.stats-cards {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 20px;
	margin-bottom: 20px;
}
.stats-card {
	text-align: center;
	padding: 20px;
}
.stats-card-title {
	font-size: 14px;
	color: #606266;
	margin-bottom: 10px;
}
.stats-card-value {
	font-size: 24px;
	font-weight: bold;
	margin-bottom: 5px;
}
.stats-card-change {
	font-size: 12px;
}
.positive {
	color: #67c23a;
}
.negative {
	color: #f56c6c;
}
.chart-container {
	margin: 0 0 20px;
}
.chart {
	width: 100%;
	height: 400px;
}
.shop-list {
	margin-top: 20px;
}
.pagination-container {
	margin-top: 16px;
	display: flex;
	justify-content: flex-end;
}
</style>

