/**
 * 性能预算与测量（plan.md「性能预算」）。
 *
 * 提供：
 * - measure()：异步函数执行计时，超预算时告警
 * - PerfBudget：预算配置（解析/入库/渲染等关键路径的毫秒上限）
 * - getPerfReport()：获取所有测量记录（供 CI 门禁或日志中心展示）
 *
 * 参考 BeeCount 的性能埋点 + AutoAccounting 的 ocrDoing 守卫计时。
 */

import { logger } from './logger';

/** 关键路径性能预算（毫秒）。 */
export interface PerfBudget {
  /** 账本解析（main.bean + mobile.bean 合计）。 */
  ledgerParse: number;
  /** 单笔交易写入（含锁+序列化+文件写入）。 */
  transactionWrite: number;
  /** OCR 单张图片识别。 */
  ocrProcess: number;
  /** 报表统计计算。 */
  reportStats: number;
  /** 页面首帧渲染。 */
  firstRender: number;
}

/** 默认预算（plan.md 建议值）。 */
export const DEFAULT_BUDGET: PerfBudget = {
  ledgerParse: 500,
  transactionWrite: 50,
  ocrProcess: 3000,
  reportStats: 200,
  firstRender: 300,
};

interface PerfRecord {
  tag: string;
  duration: number;
  budget: number;
  overBudget: boolean;
  timestamp: string;
}

/** 全局性能记录缓冲（最多 200 条）。 */
const records: PerfRecord[] = [];
const MAX_RECORDS = 200;

/**
 * 测量异步函数执行时间，超预算时记 WARN 日志。
 *
 * @param tag 测量标识（如 'ledgerParse'）
 * @param budget 预算（ms）
 * @param fn 要测量的异步函数
 * @returns fn 的返回值
 *
 * @example
 * const ledger = await measure('ledgerParse', 500, () => parseLedger(content));
 */
export async function measure<T>(
  tag: string,
  budget: number,
  fn: () => Promise<T>,
): Promise<T> {
  const start = Date.now();
  try {
    return await fn();
  } finally {
    const duration = Date.now() - start;
    const overBudget = duration > budget;
    const record: PerfRecord = {
      tag,
      duration,
      budget,
      overBudget,
      timestamp: new Date().toISOString(),
    };
    records.push(record);
    if (records.length > MAX_RECORDS) records.shift();

    if (overBudget) {
      logger.warn('perf', `${tag} 超预算: ${duration}ms > ${budget}ms`);
    } else {
      logger.debug('perf', `${tag}: ${duration}ms / ${budget}ms`);
    }
  }
}

/** 测量同步函数执行时间（非异步版本）。 */
export function measureSync<T>(tag: string, budget: number, fn: () => T): T {
  const start = Date.now();
  try {
    return fn();
  } finally {
    const duration = Date.now() - start;
    const overBudget = duration > budget;
    records.push({ tag, duration, budget, overBudget, timestamp: new Date().toISOString() });
    if (records.length > MAX_RECORDS) records.shift();
    if (overBudget) {
      logger.warn('perf', `${tag} 超预算: ${duration}ms > ${budget}ms`);
    }
  }
}

/** 获取所有性能记录（副本）。 */
export function getPerfRecords(): PerfRecord[] {
  return [...records];
}

/** 获取超预算的记录（用于 CI 门禁）。 */
export function getOverBudgetRecords(): PerfRecord[] {
  return records.filter(r => r.overBudget);
}

/** 清空性能记录。 */
export function clearPerfRecords(): void {
  records.length = 0;
}

/**
 * 生成性能报告摘要（供日志中心 / CI 输出）。
 */
export function getPerfReport(): {
  totalMeasurements: number;
  overBudgetCount: number;
  worstOffender?: { tag: string; duration: number; budget: number };
} {
  const overBudget = getOverBudgetRecords();
  const worst = overBudget.length > 0
    ? overBudget.reduce((max, r) => r.duration > max.duration ? r : max)
    : undefined;
  return {
    totalMeasurements: records.length,
    overBudgetCount: overBudget.length,
    worstOffender: worst ? { tag: worst.tag, duration: worst.duration, budget: worst.budget } : undefined,
  };
}
