<script lang="ts">
  import * as Card from '$lib/components/ui/card';
  import * as Select from '$lib/components/ui/select';
  import * as Drawer from '$lib/components/ui/drawer';
  import Activity from '@lucide/svelte/icons/activity';
  import TrendingUp from '@lucide/svelte/icons/trending-up';
  import TrendingDown from '@lucide/svelte/icons/trending-down';
  import Calendar from '@lucide/svelte/icons/calendar';
  import AreaChart from '@lucide/svelte/icons/area-chart';
  import LineChart from '@lucide/svelte/icons/line-chart';
  import { Button } from '$lib/components/ui/button';
  import type { UIBill } from '$lib/models/bill';
  import { pieColors } from '$lib/constants/chart';
  import { formatLocalDate } from '$lib/utils';
  import BillRecordsTable from './BillRecordsTable.svelte';

  interface Props {
    records: UIBill[];
    categories?: string[];
    onUpdate?: (updated: UIBill, original: UIBill) => void;
    onDelete?: (deleted: UIBill) => void;
  }

  let { records = $bindable(), categories = [], onUpdate, onDelete }: Props = $props();
  
  function handleRecordUpdated(updated: UIBill, original: UIBill) {
    // 更新 records 数组
    const idx = records.findIndex(r => 
      r === original ||
      (r.time === original.time && r.merchant === original.merchant && r.amount === original.amount)
    );
    if (idx !== -1) {
      records[idx] = updated;
      records = [...records];
    }
    
    // 更新 selectedDateRecords（如果账单在当前选中的日期记录中）
    const dateIdx = selectedDateRecords.findIndex(r => 
      r === original ||
      (r.time === original.time && r.merchant === original.merchant && r.amount === original.amount)
    );
    if (dateIdx !== -1) {
      selectedDateRecords[dateIdx] = updated;
      selectedDateRecords = [...selectedDateRecords];
    }
    
    // 传播到父组件
    onUpdate?.(updated, original);
  }

  function handleRecordDeleted(deleted: UIBill) {
    const idx = records.findIndex(r =>
      r === deleted ||
      (r.time === deleted.time && r.merchant === deleted.merchant && r.amount === deleted.amount)
    );
    if (idx !== -1) {
      records.splice(idx, 1);
      records = [...records];
    }

    const dateIdx = selectedDateRecords.findIndex(r =>
      r === deleted ||
      (r.time === deleted.time && r.merchant === deleted.merchant && r.amount === deleted.amount)
    );
    if (dateIdx !== -1) {
      selectedDateRecords.splice(dateIdx, 1);
      selectedDateRecords = [...selectedDateRecords];
    }

    onDelete?.(deleted);
  }
  
  // Dialog 状态
  let dialogOpen = $state(false);
  let selectedDate = $state<Date | null>(null);
  let selectedDateRecords = $state<UIBill[]>([]);

  // 时间范围选项
  type TimeRange = '7d' | 'week' | '30d' | 'month' | '3m' | 'year';
  let timeRange = $state<TimeRange>('month');
  
  // 图表类型
  type ChartType = 'area' | 'line';
  let chartType = $state<ChartType>('area');
  
  // 隐藏的类别
  let hiddenCategories = $state<Set<string>>(new Set());
  
  function toggleCategory(category: string) {
    const newSet = new Set(hiddenCategories);
    if (newSet.has(category)) {
      newSet.delete(category);
    } else {
      newSet.add(category);
    }
    hiddenCategories = newSet;
  }

  // 提取日期字符串 (YYYY-MM-DD) - 兼容多种格式
  function extractDateStr(timeStr: string): string {
    // 处理 ISO 格式 (2025-12-29T10:30:00Z) 或空格格式 (2025-12-29 10:30:00)
    return timeStr.split('T')[0].split(' ')[0];
  }

  const timeRangeOptions = [
    { value: '7d', label: '最近 7 天' },
    { value: 'week', label: '本周' },
    { value: '30d', label: '最近 30 天' },
    { value: 'month', label: '本月' },
    { value: '3m', label: '最近 3 个月' },
    { value: 'year', label: '本年' }
  ];

  // 获取截止日期
  function getCutoffDate(range: TimeRange): Date {
    const now = new Date();
    switch (range) {
      case '7d':
        return new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
      case 'week':
        // 本周一
        const day = now.getDay();
        const diff = now.getDate() - day + (day === 0 ? -6 : 1);
        return new Date(now.getFullYear(), now.getMonth(), diff);
      case '30d':
        return new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
      case 'month':
        // 本月第一天
        return new Date(now.getFullYear(), now.getMonth(), 1);
      case '3m':
        return new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000);
      case 'year':
        // 本年第一天
        return new Date(now.getFullYear(), 0, 1);
      default:
        return new Date(now.getFullYear(), now.getMonth(), 1);
    }
  }

  // 聚合粒度类型
  type AggregationType = 'day' | 'week' | 'month';
  
  // 获取周的起始日期（周一）
  function getWeekStart(date: Date): string {
    const d = new Date(date);
    const day = d.getDay();
    const diff = d.getDate() - day + (day === 0 ? -6 : 1); // 调整到周一
    d.setDate(diff);
    return formatLocalDate(d);
  }
  
  // 获取月份标识
  function getMonthKey(date: Date): string {
    return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
  }
  
  // 格式化聚合后的标签
  function formatAggregationLabel(key: string, type: AggregationType): string {
    if (type === 'day') {
      const d = new Date(key);
      return `${d.getMonth() + 1}/${d.getDate()}`;
    } else if (type === 'week') {
      const d = new Date(key);
      return `${d.getMonth() + 1}/${d.getDate()}周`;
    } else {
      const [year, month] = key.split('-');
      return `${month}月`;
    }
  }

  // 按日期和分类分组数据（支持智能聚合）
  let processedData = $derived(() => {
    const cutoffDate = getCutoffDate(timeRange);
    
    // 过滤支出记录
    const expenseRecords = records.filter(r => {
      if (r.incomeExpense !== '支出') return false;
      const recordDate = new Date(extractDateStr(r.time));
      return recordDate >= cutoffDate;
    });

    if (expenseRecords.length === 0) return { data: [], categories: [], maxValue: 0, aggregationType: 'day' as AggregationType };

    // 先按天分组，计算天数
    const dailyMap = new Map<string, Map<string, number>>();
    const categoryTotals: Record<string, number> = {};

    expenseRecords.forEach(record => {
      const dateStr = extractDateStr(record.time);
      const category = record.category || '其他';
      const amount = record.amount || 0;

      categoryTotals[category] = (categoryTotals[category] || 0) + amount;

      if (!dailyMap.has(dateStr)) {
        dailyMap.set(dateStr, new Map());
      }
      const dayData = dailyMap.get(dateStr)!;
      dayData.set(category, (dayData.get(category) || 0) + amount);
    });

    // 填充缺失的日期（零支出日期）
    const now = new Date();
    const allDates: string[] = [];
    const cursor = new Date(cutoffDate);
    while (cursor <= now) {
      allDates.push(formatLocalDate(cursor));
      cursor.setDate(cursor.getDate() + 1);
    }
    allDates.forEach(dateStr => {
      if (!dailyMap.has(dateStr)) {
        dailyMap.set(dateStr, new Map());
      }
    });

    const dayCount = dailyMap.size;
    
    // 根据天数决定聚合粒度
    let aggregationType: AggregationType = 'day';
    if (dayCount > 90) {
      aggregationType = 'month';
    } else if (dayCount > 30) {
      aggregationType = 'week';
    }

    // 按聚合粒度重新分组
    const aggregatedMap = new Map<string, Map<string, number>>();
    
    dailyMap.forEach((dayData, dateStr) => {
      const date = new Date(dateStr);
      let key: string;
      
      if (aggregationType === 'day') {
        key = dateStr;
      } else if (aggregationType === 'week') {
        key = getWeekStart(date);
      } else {
        key = getMonthKey(date);
      }
      
      if (!aggregatedMap.has(key)) {
        aggregatedMap.set(key, new Map());
      }
      const aggData = aggregatedMap.get(key)!;
      dayData.forEach((amount, cat) => {
        aggData.set(cat, (aggData.get(cat) || 0) + amount);
      });
    });

    // 获取前5大分类
    const sortedCategories = Object.entries(categoryTotals)
      .sort((a, b) => b[1] - a[1])
      .slice(0, 5)
      .map(([cat]) => cat);

    // 转换为数组格式并计算堆叠值
    const data = Array.from(aggregatedMap.entries())
      .map(([key, aggData]) => {
        // 为不同聚合类型创建正确的日期对象
        let date: Date;
        if (aggregationType === 'month') {
          const [year, month] = key.split('-');
          date = new Date(parseInt(year), parseInt(month) - 1, 15); // 月中
        } else {
          date = new Date(key);
        }
        
        const result: Record<string, any> = { 
          date,
          dateStr: key,
          label: formatAggregationLabel(key, aggregationType)
        };
        
        let cumulative = 0;
        sortedCategories.forEach(cat => {
          const value = aggData.get(cat) || 0;
          result[cat] = value;
          // 只有未隐藏的类别参与堆叠
          if (!hiddenCategories.has(cat)) {
            result[`${cat}_y0`] = cumulative;
            result[`${cat}_y1`] = cumulative + value;
            cumulative += value;
          } else {
            result[`${cat}_y0`] = 0;
            result[`${cat}_y1`] = 0;
          }
        });
        
        // 其他分类汇总
        let otherSum = 0;
        aggData.forEach((amount, cat) => {
          if (!sortedCategories.includes(cat)) {
            otherSum += amount;
          }
        });
        if (otherSum > 0) {
          result['其他'] = otherSum;
          if (!hiddenCategories.has('其他')) {
            result['其他_y0'] = cumulative;
            result['其他_y1'] = cumulative + otherSum;
            cumulative += otherSum;
          } else {
            result['其他_y0'] = 0;
            result['其他_y1'] = 0;
          }
        }
        
        result.total = cumulative;
        return result;
      })
      .sort((a, b) => a.date.getTime() - b.date.getTime());

    const finalCategories = [...sortedCategories];
    if (data.some(d => d['其他'] > 0)) {
      finalCategories.push('其他');
    }

    const maxValue = Math.max(...data.map(d => d.total || 0), 1);

    return { data, categories: finalCategories, maxValue, aggregationType, dayCount };
  });

  // 获取颜色
  function getColor(index: number): string {
    return pieColors[index % pieColors.length];
  }

  // 趋势计算
  let trendInfo = $derived(() => {
    const { data } = processedData();
    if (data.length < 2) return null;
    
    const lastTotal = data[data.length - 1].total || 0;
    const prevTotal = data[data.length - 2].total || 0;
    
    const change = lastTotal - prevTotal;
    const changePercent = prevTotal > 0 ? (change / prevTotal) * 100 : 0;
    return { change, changePercent, lastTotal };
  });

  // 获取描述文本
  let descriptionText = $derived(() => {
    const { data, aggregationType, dayCount } = processedData();
    const label = timeRangeOptions.find(o => o.value === timeRange)?.label || '最近 3 个月';
    
    let aggregationHint = '';
    if (aggregationType === 'week') {
      aggregationHint = `，按周聚合 (${data.length} 周)`;
    } else if (aggregationType === 'month') {
      aggregationHint = `，按月聚合 (${data.length} 月)`;
    } else {
      aggregationHint = ` (${dayCount || data.length} 天)`;
    }
    
    return `${label}各分类支出趋势${aggregationHint}`;
  });

  function handleTimeRangeChange(value: string | undefined) {
    if (value && ['7d', 'week', '30d', 'month', '3m', 'year'].includes(value)) {
      timeRange = value as TimeRange;
    }
  }

  // SVG 尺寸
  const chartWidth = 800;
  const chartHeight = 250;
  const padding = { top: 20, right: 20, bottom: 40, left: 60 };
  const innerWidth = chartWidth - padding.left - padding.right;
  const innerHeight = chartHeight - padding.top - padding.bottom;

  // 坐标转换
  function xScale(date: Date, data: any[]): number {
    if (data.length <= 1) return padding.left;
    const minDate = data[0].date.getTime();
    const maxDate = data[data.length - 1].date.getTime();
    const range = maxDate - minDate || 1;
    return padding.left + ((date.getTime() - minDate) / range) * innerWidth;
  }

  function yScale(value: number, maxValue: number): number {
    if (maxValue === 0) return padding.top + innerHeight;
    return padding.top + innerHeight - (value / maxValue) * innerHeight;
  }

  // 生成平滑曲线的控制点 (Catmull-Rom to Bezier)
  function getCurveControlPoints(
    p0: { x: number; y: number },
    p1: { x: number; y: number },
    p2: { x: number; y: number },
    p3: { x: number; y: number },
    tension: number = 0.3
  ): { cp1: { x: number; y: number }; cp2: { x: number; y: number } } {
    const d1 = Math.sqrt(Math.pow(p1.x - p0.x, 2) + Math.pow(p1.y - p0.y, 2));
    const d2 = Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
    const d3 = Math.sqrt(Math.pow(p3.x - p2.x, 2) + Math.pow(p3.y - p2.y, 2));
    
    const d1a = Math.pow(d1, tension);
    const d2a = Math.pow(d2, tension);
    const d3a = Math.pow(d3, tension);
    
    const cp1 = {
      x: p1.x + (d1a !== 0 ? (p2.x - p0.x) * d2a / (d1a + d2a) / 6 * tension * 6 : 0),
      y: p1.y + (d1a !== 0 ? (p2.y - p0.y) * d2a / (d1a + d2a) / 6 * tension * 6 : 0)
    };
    
    const cp2 = {
      x: p2.x - (d3a !== 0 ? (p3.x - p1.x) * d2a / (d2a + d3a) / 6 * tension * 6 : 0),
      y: p2.y - (d3a !== 0 ? (p3.y - p1.y) * d2a / (d2a + d3a) / 6 * tension * 6 : 0)
    };
    
    return { cp1, cp2 };
  }

  // 生成平滑曲线路径
  function generateSmoothPath(points: { x: number; y: number }[]): string {
    if (points.length < 2) return '';
    if (points.length === 2) {
      return `L ${points[1].x},${points[1].y}`;
    }
    
    let path = '';
    
    for (let i = 0; i < points.length - 1; i++) {
      const p0 = points[Math.max(0, i - 1)];
      const p1 = points[i];
      const p2 = points[i + 1];
      const p3 = points[Math.min(points.length - 1, i + 2)];
      
      const { cp1, cp2 } = getCurveControlPoints(p0, p1, p2, p3);
      
      path += ` C ${cp1.x},${cp1.y} ${cp2.x},${cp2.y} ${p2.x},${p2.y}`;
    }
    
    return path;
  }

  // 生成面积路径（平滑曲线版本）
  function generateAreaPath(category: string, data: any[], maxValue: number): string {
    if (data.length === 0) return '';
    
    const topPoints: { x: number; y: number }[] = [];
    const bottomPoints: { x: number; y: number }[] = [];
    
    data.forEach((d) => {
      const x = xScale(d.date, data);
      const y1 = yScale(d[`${category}_y1`] || 0, maxValue);
      const y0 = yScale(d[`${category}_y0`] || 0, maxValue);
      topPoints.push({ x, y: y1 });
      bottomPoints.unshift({ x, y: y0 });
    });
    
    // 起始点
    const startPoint = topPoints[0];
    let path = `M ${startPoint.x},${startPoint.y}`;
    
    // 顶部曲线
    path += generateSmoothPath(topPoints);
    
    // 连接到底部起点
    const bottomStart = bottomPoints[0];
    path += ` L ${bottomStart.x},${bottomStart.y}`;
    
    // 底部曲线
    path += generateSmoothPath(bottomPoints);
    
    // 闭合路径
    path += ' Z';
    
    return path;
  }

  // 生成线性图路径（总金额曲线）
  function generateTotalLinePath(data: any[], maxValue: number): string {
    if (data.length === 0) return '';
    
    // 计算每天的总支出（所有可见分类的总和）
    const points: { x: number; y: number }[] = data.map((d) => {
      // 使用 total 字段，这是所有可见分类的累计值
      const total = d.total || 0;
      return {
        x: xScale(d.date, data),
        y: yScale(total, maxValue)
      };
    });
    
    // 起始点
    const startPoint = points[0];
    let path = `M ${startPoint.x},${startPoint.y}`;
    
    // 平滑曲线
    path += generateSmoothPath(points);
    
    return path;
  }

  // 生成线性图的数据点坐标（总金额）
  function getTotalLinePoints(data: any[], maxValue: number): { x: number; y: number; value: number }[] {
    return data.map((d) => ({
      x: xScale(d.date, data),
      y: yScale(d.total || 0, maxValue),
      value: d.total || 0
    }));
  }

  // 生成 X 轴刻度
  function getXTicks(data: any[]): { x: number; label: string }[] {
    if (data.length === 0) return [];
    const step = Math.max(1, Math.floor(data.length / 6));
    return data.filter((_, i) => i % step === 0 || i === data.length - 1).map(d => ({
      x: xScale(d.date, data),
      label: d.label || `${d.date.getMonth() + 1}/${d.date.getDate()}`
    }));
  }

  // 生成 Y 轴刻度
  function getYTicks(maxValue: number): { y: number; label: string }[] {
    if (maxValue === 0) return [];
    const ticks = [];
    const step = Math.ceil(maxValue / 4 / 100) * 100;
    for (let v = 0; v <= maxValue; v += step) {
      ticks.push({
        y: yScale(v, maxValue),
        label: `¥${v}`
      });
    }
    return ticks;
  }

  // Tooltip 状态
  let tooltipData = $state<any>(null);
  let tooltipX = $state(0);
  let tooltipY = $state(0);

  function handleMouseMove(event: MouseEvent, data: any[], maxValue: number) {
    const svg = event.currentTarget as SVGSVGElement;
    const rect = svg.getBoundingClientRect();
    
    // 将像素坐标转换为 viewBox 坐标
    const pixelX = event.clientX - rect.left;
    const scaleRatio = chartWidth / rect.width;
    const viewBoxX = pixelX * scaleRatio;
    
    // 找到最近的数据点
    let closestIdx = 0;
    let closestDist = Infinity;
    data.forEach((d, i) => {
      const dx = Math.abs(xScale(d.date, data) - viewBoxX);
      if (dx < closestDist) {
        closestDist = dx;
        closestIdx = i;
      }
    });
    
    // 阈值也需要按比例调整
    if (closestDist < 50 * scaleRatio) {
      tooltipData = data[closestIdx];
      tooltipX = xScale(data[closestIdx].date, data);
      tooltipY = event.clientY - rect.top;
    } else {
      tooltipData = null;
    }
  }

  function handleMouseLeave() {
    tooltipData = null;
  }

  function openDateDetails(clickedDate: Date) {
    const dateStr = formatLocalDate(clickedDate);

    selectedDate = clickedDate;
    selectedDateRecords = records.filter(r => {
      if (r.incomeExpense !== '支出') return false;
      const recordDateStr = extractDateStr(r.time);
      return recordDateStr === dateStr;
    });

    dialogOpen = true;
  }

  // 点击打开 Dialog
  function handleClick(event: MouseEvent, data: any[], maxValue: number) {
    if (data.length === 0) return;
    
    const svg = event.currentTarget as SVGSVGElement;
    const rect = svg.getBoundingClientRect();
    
    // 将像素坐标转换为 viewBox 坐标
    const pixelX = event.clientX - rect.left;
    const scaleRatio = chartWidth / rect.width;
    const viewBoxX = pixelX * scaleRatio;
    
    // 找到最近的数据点
    let closestIdx = 0;
    let closestDist = Infinity;
    data.forEach((d, i) => {
      const dx = Math.abs(xScale(d.date, data) - viewBoxX);
      if (dx < closestDist) {
        closestDist = dx;
        closestIdx = i;
      }
    });
    
    // 点击图表任意位置都触发，选择最近的日期
    const clickedDate = data[closestIdx].date;
    openDateDetails(clickedDate);
  }

  // 计算选中日期的统计
  let selectedDateStats = $derived.by(() => {
    if (!selectedDate || selectedDateRecords.length === 0) return null;
    
    const categoryMap = new Map<string, { amount: number; count: number }>();
    let total = 0;
    
    selectedDateRecords.forEach(r => {
      const cat = r.category || '其他';
      const amount = r.amount || 0;
      total += amount;
      
      if (!categoryMap.has(cat)) {
        categoryMap.set(cat, { amount: 0, count: 0 });
      }
      const stat = categoryMap.get(cat)!;
      stat.amount += amount;
      stat.count += 1;
    });
    
    const categories = Array.from(categoryMap.entries())
      .map(([category, stat]) => ({ category, ...stat }))
      .sort((a, b) => b.amount - a.amount);
    
    return { total, categories, count: selectedDateRecords.length };
  });
</script>

{#if processedData().data.length > 1}
  {@const { data, categories, maxValue } = processedData()}
  <Card.Root class="transition-all duration-200 hover:shadow-lg hover:-translate-y-1">
    <Card.Header class="flex flex-row items-center justify-between pb-2">
      <div class="space-y-1.5">
        <Card.Title class="flex items-center gap-2">
          <Activity class="h-5 w-5" />
          每日支出趋势
        </Card.Title>
        <Card.Description>
          {descriptionText()}
        </Card.Description>
      </div>
      <div class="flex items-center gap-2">
        <!-- 图表类型切换 -->
        <div class="flex items-center rounded-md border bg-muted/50 p-0.5">
          <button
            class="flex items-center justify-center h-7 w-7 rounded transition-colors {chartType === 'area' ? 'bg-background shadow-sm' : 'hover:bg-background/50'}"
            onclick={() => chartType = 'area'}
            title="堆叠面积图"
          >
            <AreaChart class="h-4 w-4 {chartType === 'area' ? 'text-primary' : 'text-muted-foreground'}" />
          </button>
          <button
            class="flex items-center justify-center h-7 w-7 rounded transition-colors {chartType === 'line' ? 'bg-background shadow-sm' : 'hover:bg-background/50'}"
            onclick={() => chartType = 'line'}
            title="线性图"
          >
            <LineChart class="h-4 w-4 {chartType === 'line' ? 'text-primary' : 'text-muted-foreground'}" />
          </button>
        </div>
        
        <!-- 时间范围选择 -->
        <Select.Root type="single" value={timeRange} onValueChange={handleTimeRangeChange}>
          <Select.Trigger class="w-[140px] h-8 text-xs">
            {timeRangeOptions.find(o => o.value === timeRange)?.label}
          </Select.Trigger>
          <Select.Content>
            {#each timeRangeOptions as option}
              <Select.Item value={option.value}>{option.label}</Select.Item>
            {/each}
          </Select.Content>
        </Select.Root>
      </div>
    </Card.Header>
    <Card.Content>
      <!-- 图例 -->
      <div class="flex flex-wrap gap-4 mb-4">
        {#if chartType === 'area'}
          <!-- 堆叠面积图：分类图例 (点击可切换显示) -->
          {#each categories as category, i}
            {@const isHidden = hiddenCategories.has(category)}
            <button 
              class="flex items-center gap-2 cursor-pointer hover:opacity-80 transition-opacity outline-none"
              onclick={() => toggleCategory(category)}
              title={isHidden ? '点击显示' : '点击隐藏'}
            >
              <div 
                class="w-3 h-3 rounded-sm transition-opacity {isHidden ? 'opacity-30' : ''}" 
                style="background-color: {getColor(i)}"
              ></div>
              <span 
                class="text-xs transition-colors {isHidden ? 'text-muted-foreground/40 line-through' : 'text-muted-foreground'}"
              >{category}</span>
            </button>
          {/each}
        {:else}
          <!-- 线性图：总支出图例 -->
          <div class="flex items-center gap-2">
            <div 
              class="w-3 h-3 rounded-full" 
              style="background-color: oklch(0.65 0.2 25)"
            ></div>
            <span class="text-xs text-muted-foreground">总支出</span>
          </div>
        {/if}
      </div>

      <!-- 趋势图 (自定义 SVG) -->
      <div class="relative w-full" style="aspect-ratio: {chartWidth}/{chartHeight};">
        <svg 
          viewBox="0 0 {chartWidth} {chartHeight}" 
          class="w-full h-full cursor-pointer outline-none focus:outline-none"
          role="button"
          aria-label="每日支出趋势图表，点击可查看当日详情"
          tabindex="0"
          onmousemove={(e) => handleMouseMove(e, data, maxValue)}
          onmouseleave={handleMouseLeave}
          onclick={(e) => handleClick(e, data, maxValue)}
          onkeydown={(e) => {
            if (e.key === 'Enter' || e.key === ' ') {
              e.preventDefault();
              const last = data[data.length - 1];
              if (last?.date) openDateDetails(last.date);
            }
          }}
        >
          <!-- Y 轴 -->
          <line 
            x1={padding.left} 
            y1={padding.top} 
            x2={padding.left} 
            y2={padding.top + innerHeight}
            stroke="currentColor"
            stroke-opacity="0.2"
          />
          
          <!-- Y 轴刻度 -->
          {#each getYTicks(maxValue) as tick}
            <line 
              x1={padding.left} 
              y1={tick.y} 
              x2={padding.left + innerWidth} 
              y2={tick.y}
              stroke="currentColor"
              stroke-opacity="0.1"
              stroke-dasharray="4"
            />
            <text 
              x={padding.left - 8} 
              y={tick.y + 4}
              text-anchor="end"
              class="fill-muted-foreground text-[10px]"
            >
              {tick.label}
            </text>
          {/each}
          
          <!-- X 轴 -->
          <line 
            x1={padding.left} 
            y1={padding.top + innerHeight} 
            x2={padding.left + innerWidth} 
            y2={padding.top + innerHeight}
            stroke="currentColor"
            stroke-opacity="0.2"
          />
          
          <!-- X 轴刻度 -->
          {#each getXTicks(data) as tick}
            <text 
              x={tick.x} 
              y={padding.top + innerHeight + 20}
              text-anchor="middle"
              class="fill-muted-foreground text-[10px]"
            >
              {tick.label}
            </text>
          {/each}
          
          {#if chartType === 'area'}
            <!-- 堆叠面积图 (从后向前渲染) -->
            {#each [...categories].reverse() as category, i}
              {@const colorIdx = categories.length - 1 - i}
              <path
                d={generateAreaPath(category, data, maxValue)}
                fill={getColor(colorIdx)}
                fill-opacity="0.7"
                class="transition-opacity hover:opacity-90"
              />
            {/each}
          {:else}
            <!-- 线性图（总金额） -->
            <!-- 曲线 -->
            <path
              d={generateTotalLinePath(data, maxValue)}
              fill="none"
              stroke="oklch(0.65 0.2 25)"
              stroke-width="3"
              stroke-linecap="round"
              stroke-linejoin="round"
              class="transition-opacity"
            />
            <!-- 数据点 -->
            {#each getTotalLinePoints(data, maxValue) as point}
              <circle
                cx={point.x}
                cy={point.y}
                r="4"
                fill="oklch(0.65 0.2 25)"
                stroke="white"
                stroke-width="2"
                class="transition-all"
              />
            {/each}
          {/if}
          
          <!-- Tooltip 辅助线 -->
          {#if tooltipData}
            <line
              x1={tooltipX}
              y1={padding.top}
              x2={tooltipX}
              y2={padding.top + innerHeight}
              stroke="currentColor"
              stroke-opacity="0.3"
              stroke-dasharray="4"
            />
            <!-- 数据点 -->
            {#each categories as category, i}
              {#if tooltipData[category] > 0}
                <circle
                  cx={tooltipX}
                  cy={yScale(tooltipData[`${category}_y1`] || 0, maxValue)}
                  r="4"
                  fill={getColor(i)}
                  stroke="white"
                  stroke-width="2"
                />
              {/if}
            {/each}
          {/if}
        </svg>
        
        <!-- Tooltip -->
        {#if tooltipData}
          {@const tooltipLeftPercent = (tooltipX / chartWidth) * 100}
          {@const adjustedLeft = tooltipLeftPercent > 75 ? tooltipLeftPercent - 25 : tooltipLeftPercent + 2}
          <div 
            class="absolute pointer-events-none z-10 border-border/50 bg-background rounded-lg border px-3 py-2 text-xs shadow-xl min-w-[160px]"
            style="left: {adjustedLeft}%; top: 15%;"
          >
            <div class="font-medium text-foreground mb-2">
              {tooltipData.label || tooltipData.date.toLocaleDateString('zh-CN')}
            </div>
            <div class="space-y-1">
              {#each categories as category, i}
                {#if tooltipData[category] > 0}
                  <div class="flex items-center justify-between gap-4">
                    <div class="flex items-center gap-2">
                      <div 
                        class="w-2 h-2 rounded-full" 
                        style="background-color: {getColor(i)}"
                      ></div>
                      <span class="text-muted-foreground">{category}</span>
                    </div>
                    <span class="font-mono font-medium">¥{tooltipData[category].toFixed(2)}</span>
                  </div>
                {/if}
              {/each}
            </div>
            <div class="border-t border-border mt-2 pt-2 flex justify-between">
              <span class="text-muted-foreground">合计</span>
              <span class="font-mono font-bold">¥{tooltipData.total.toFixed(2)}</span>
            </div>
          </div>
        {/if}
      </div>

      <!-- 趋势指标 -->
      <div class="flex items-center justify-center gap-2 mt-4 text-sm">
        {#if trendInfo()}
          {@const info = trendInfo()}
          {#if info!.change >= 0}
            <TrendingUp class="h-4 w-4 text-red-500" />
            <span class="text-red-500">+{Math.abs(info!.changePercent).toFixed(1)}%</span>
          {:else}
            <TrendingDown class="h-4 w-4 text-green-500" />
            <span class="text-green-500">-{Math.abs(info!.changePercent).toFixed(1)}%</span>
          {/if}
          <span class="text-muted-foreground">较前一天</span>
        {/if}
      </div>
      
      <!-- 提示文字 -->
      <p class="text-center text-xs text-muted-foreground mt-2">
        点击图表查看当日详情
      </p>
    </Card.Content>
  </Card.Root>
{/if}

<!-- 当日详情 Drawer -->
<Drawer.Root bind:open={dialogOpen}>
  <Drawer.Content class="md:max-w-4xl">
    <Drawer.Header>
      <Drawer.Title class="flex items-center gap-2">
        <Calendar class="h-5 w-5" />
        {#if selectedDate}
          {selectedDate.toLocaleDateString('zh-CN', { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' })}
        {/if}
      </Drawer.Title>
      <Drawer.Description>
        {#if selectedDateStats}
          {@const stats = selectedDateStats}
          共 {stats!.count} 笔支出，合计 ¥{stats!.total.toFixed(2)}
        {/if}
      </Drawer.Description>
    </Drawer.Header>
    
    <div class="flex-1 overflow-auto py-4 px-4 md:px-0">
      {#if selectedDateStats}
        {@const stats = selectedDateStats}
        
        <!-- 分类汇总 -->
        <div class="mb-4 space-y-2">
          <h4 class="text-sm font-medium text-muted-foreground">分类汇总</h4>
          <div class="grid grid-cols-2 gap-2">
            {#each stats!.categories as cat, i}
              <div class="flex items-center justify-between p-2 rounded-lg bg-muted/50">
                <div class="flex items-center gap-2">
                  <div 
                    class="w-2.5 h-2.5 rounded-full" 
                    style="background-color: {getColor(i)}"
                  ></div>
                  <span class="text-sm">{cat.category}</span>
                  <span class="text-xs text-muted-foreground">({cat.count}笔)</span>
                </div>
                <span class="font-mono text-sm font-medium text-red-600 dark:text-red-400">
                  ¥{cat.amount.toFixed(2)}
                </span>
              </div>
            {/each}
          </div>
        </div>
        
        <!-- 详细记录 -->
        <div>
          <h4 class="text-sm font-medium text-muted-foreground mb-2">详细记录</h4>
          <BillRecordsTable 
            bind:records={selectedDateRecords} 
            showCategory={true} 
            showDescription={false}
            pageSize={8}
            {categories}
            onUpdate={handleRecordUpdated}
            onDelete={handleRecordDeleted}
          />
        </div>
      {:else}
        <p class="text-center text-muted-foreground py-8">暂无数据</p>
      {/if}
    </div>
  </Drawer.Content>
</Drawer.Root>
