/**
 * 分享海报生成（plan.md「5.10 分享海报生成」）。
 *
 * 参考 BeeCount 的 share_poster_service.dart：
 * - 渲染海报视图 → 截图 → 保存相册 / 分享
 * - 海报类型：年度/月度/账本摘要
 *
 * 截图与保存通过注入抽象（生产用 react-native-view-shot + expo-media-library，
 * 测试用 mock），海报数据计算为纯函数。
 */

import { generateAnnualReport, type AnnualReport } from '../domain/stats/annualReport';
import { addDecimals, negateDecimal } from '../domain/core/decimal';
import type { Transaction } from '../domain/core/types';

export type PosterType = 'year' | 'month' | 'ledger';

export interface PosterConfig {
  type: PosterType;
  title: string;
  period?: string;        // 如 "2026年7月" 或 "2026"
  transactions: Transaction[];
  /** 年份（year 类型用）。 */
  year?: number;
  /** 月份（month 类型用，1-12）。 */
  month?: number;
}

export interface PosterStats {
  totalIncome: string;
  totalExpense: string;
  transactionCount: number;
  topCategory?: { category: string; amount: string };
  averageDaily?: string;
  /** 年度报告（year 类型）。 */
  annualReport?: AnnualReport;
}

/** 截图器抽象（生产用 react-native-view-shot）。 */
export interface ViewShotter {
  /** 截取指定 ref 的视图，返回图片 URI。 */
  capture(refId: string, options?: { format?: 'png' | 'jpg'; quality?: number }): Promise<string>;
  /** 保存到相册。 */
  saveToAlbum(uri: string, album?: string): Promise<void>;
  /** 调用系统分享。 */
  share(uri: string, title?: string): Promise<void>;
}

/** 计算海报统计数据（纯函数）。 */
export function calculatePosterStats(config: PosterConfig): PosterStats {
  let tx = config.transactions;

  // 按类型过滤
  if (config.type === 'year' && config.year) {
    tx = tx.filter(t => t.date.startsWith(String(config.year)));
    const annualReport = generateAnnualReport(tx, config.year);
    return {
      totalIncome: annualReport.totalIncome,
      totalExpense: annualReport.totalExpense,
      transactionCount: annualReport.transactionCount,
      topCategory: annualReport.topCategories[0]
        ? { category: annualReport.topCategories[0].category, amount: annualReport.topCategories[0].amount }
        : undefined,
      averageDaily: annualReport.averageDailyExpense,
      annualReport,
    };
  }

  if (config.type === 'month' && config.year && config.month) {
    const monthStr = `${config.year}-${String(config.month).padStart(2, '0')}`;
    tx = tx.filter(t => t.date.startsWith(monthStr));
  }

  // 通用统计
  let income = '0', expense = '0';
  const byCategory = new Map<string, string>();
  for (const t of tx) {
    for (const p of t.postings) {
      if (!p.amount) continue;
      if (p.account.startsWith('Income')) {
        income = addDecimals([income, negateDecimal(p.amount)]);
      }
      if (p.account.startsWith('Expenses')) {
        expense = addDecimals([expense, p.amount]);
        byCategory.set(p.account, addDecimals([byCategory.get(p.account) ?? '0', p.amount]));
      }
    }
  }

  const topEntry = [...byCategory.entries()].sort((a, b) => parseFloat(b[1]) - parseFloat(a[1]))[0];

  return {
    totalIncome: income,
    totalExpense: expense,
    transactionCount: tx.length,
    topCategory: topEntry ? { category: topEntry[0], amount: topEntry[1] } : undefined,
  };
}

/**
 * 海报生成协调器。
 */
export class SharePosterService {
  constructor(private readonly shotter: ViewShotter) {}

  /** 生成海报：计算数据 → 截图 → 保存相册。 */
  async generateAndSave(config: PosterConfig, refId: string): Promise<string> {
    calculatePosterStats(config);
    const uri = await this.shotter.capture(refId, { format: 'png', quality: 1.0 });
    await this.shotter.saveToAlbum(uri, 'Bean Mobile');
    return uri;
  }

  /** 生成海报并分享。 */
  async generateAndShare(config: PosterConfig, refId: string): Promise<string> {
    const uri = await this.shotter.capture(refId, { format: 'png', quality: 1.0 });
    await this.shotter.share(uri, config.title);
    return uri;
  }

  /** 仅计算海报数据（不截图，用于预览）。 */
  previewStats(config: PosterConfig): PosterStats {
    return calculatePosterStats(config);
  }
}

/** 模拟截图器（测试用）。 */
export class MockViewShotter implements ViewShotter {
  public captured: { refId: string; format?: string }[] = [];
  public savedToAlbum: string[] = [];
  public shared: string[] = [];

  async capture(refId: string, options?: { format?: 'png' | 'jpg'; quality?: number }): Promise<string> {
    this.captured.push({ refId, format: options?.format });
    return `mock://${refId}.${options?.format ?? 'png'}`;
  }
  async saveToAlbum(uri: string): Promise<void> {
    this.savedToAlbum.push(uri);
  }
  async share(uri: string): Promise<void> {
    this.shared.push(uri);
  }
}
