/**
 * 日历网格计算（plan.md「5.3 日历视图」的纯函数部分）。
 * 从 CalendarView 抽出，使可单测（不依赖 react-native）。
 */

import type { Transaction } from '../core/types';

export interface DayCell {
  day: number;
  date: string;           // YYYY-MM-DD
  isCurrentMonth: boolean;
  hasIncome: boolean;
  hasExpense: boolean;
  count: number;
}

/** 获取某月日历网格（含上下月填充，7 列）。 */
export function getMonthGrid(year: number, month: number, transactions: Transaction[]): DayCell[][] {
  const firstDay = new Date(year, month - 1, 1);
  const lastDay = new Date(year, month, 0);
  const daysInMonth = lastDay.getDate();
  const startWeekday = firstDay.getDay();  // 0=周日

  // 按日期索引交易
  const txByDate = new Map<string, Transaction[]>();
  for (const t of transactions) {
    const date = t.date.slice(0, 10);
    if (!txByDate.has(date)) txByDate.set(date, []);
    txByDate.get(date)!.push(t);
  }

  const cells: DayCell[] = [];
  // 上月填充
  const prevMonthDays = new Date(year, month - 1, 0).getDate();
  for (let i = startWeekday - 1; i >= 0; i--) {
    const day = prevMonthDays - i;
    const prevMonth = month === 1 ? 12 : month - 1;
    const prevYear = month === 1 ? year - 1 : year;
    cells.push(buildCell(prevYear, prevMonth, day, txByDate, false));
  }
  // 当月
  for (let day = 1; day <= daysInMonth; day++) {
    cells.push(buildCell(year, month, day, txByDate, true));
  }
  // 下月填充
  const totalCells = Math.ceil(cells.length / 7) * 7;
  let nextDay = 1;
  const nextMonth = month === 12 ? 1 : month + 1;
  const nextYear = month === 12 ? year + 1 : year;
  while (cells.length < totalCells) {
    cells.push(buildCell(nextYear, nextMonth, nextDay, txByDate, false));
    nextDay++;
  }

  // 切分为周
  const weeks: DayCell[][] = [];
  for (let i = 0; i < cells.length; i += 7) {
    weeks.push(cells.slice(i, i + 7));
  }
  return weeks;
}

function buildCell(
  year: number, month: number, day: number,
  txByDate: Map<string, Transaction[]>,
  isCurrentMonth: boolean,
): DayCell {
  const date = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
  const tx = txByDate.get(date) ?? [];
  return {
    day,
    date,
    isCurrentMonth,
    hasIncome: tx.some(t => t.postings.some(p => p.account.startsWith('Income'))),
    hasExpense: tx.some(t => t.postings.some(p => p.account.startsWith('Expenses'))),
    count: tx.length,
  };
}
