/**
 * Token Usage Domain Entity
 * 记录每次 Claude API 调用的 token 消耗
 */
export class TokenUsageEntity {
  readonly id: string;
  userId: string | null;
  conversationId: string;
  messageId: string | null;
  model: string;
  inputTokens: number;
  outputTokens: number;
  cacheCreationTokens: number;
  cacheReadTokens: number;
  totalTokens: number;
  estimatedCost: number;
  intentType: string | null;
  toolCalls: number;
  responseLength: number;
  latencyMs: number;
  readonly createdAt: Date;

  private constructor(props: {
    id: string;
    userId: string | null;
    conversationId: string;
    messageId: string | null;
    model: string;
    inputTokens: number;
    outputTokens: number;
    cacheCreationTokens: number;
    cacheReadTokens: number;
    totalTokens: number;
    estimatedCost: number;
    intentType: string | null;
    toolCalls: number;
    responseLength: number;
    latencyMs: number;
    createdAt: Date;
  }) {
    Object.assign(this, props);
  }

  static create(props: {
    id: string;
    userId?: string;
    conversationId: string;
    messageId?: string;
    model: string;
    inputTokens: number;
    outputTokens: number;
    cacheCreationTokens?: number;
    cacheReadTokens?: number;
    intentType?: string;
    toolCalls?: number;
    responseLength?: number;
    latencyMs?: number;
  }): TokenUsageEntity {
    const totalTokens = props.inputTokens + props.outputTokens;
    const estimatedCost = TokenUsageEntity.calculateCost(
      props.model,
      props.inputTokens,
      props.outputTokens,
      props.cacheCreationTokens || 0,
      props.cacheReadTokens || 0,
    );

    return new TokenUsageEntity({
      id: props.id,
      userId: props.userId || null,
      conversationId: props.conversationId,
      messageId: props.messageId || null,
      model: props.model,
      inputTokens: props.inputTokens,
      outputTokens: props.outputTokens,
      cacheCreationTokens: props.cacheCreationTokens || 0,
      cacheReadTokens: props.cacheReadTokens || 0,
      totalTokens,
      estimatedCost,
      intentType: props.intentType || null,
      toolCalls: props.toolCalls || 0,
      responseLength: props.responseLength || 0,
      latencyMs: props.latencyMs || 0,
      createdAt: new Date(),
    });
  }

  static fromPersistence(props: {
    id: string;
    userId: string | null;
    conversationId: string;
    messageId: string | null;
    model: string;
    inputTokens: number;
    outputTokens: number;
    cacheCreationTokens: number;
    cacheReadTokens: number;
    totalTokens: number;
    estimatedCost: number;
    intentType: string | null;
    toolCalls: number;
    responseLength: number;
    latencyMs: number;
    createdAt: Date;
  }): TokenUsageEntity {
    return new TokenUsageEntity(props);
  }

  /**
   * 根据模型和 token 数量计算估算成本
   */
  private static calculateCost(
    model: string,
    inputTokens: number,
    outputTokens: number,
    cacheCreationTokens: number,
    cacheReadTokens: number,
  ): number {
    // Claude 3.5 Sonnet pricing (per million tokens)
    const pricing: Record<string, { input: number; output: number; cacheWrite: number; cacheRead: number }> = {
      'claude-sonnet-4-20250514': { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
      'claude-3-5-sonnet-20241022': { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
      'claude-3-5-haiku-20241022': { input: 0.8, output: 4, cacheWrite: 1, cacheRead: 0.08 },
    };

    const modelPricing = pricing[model] || pricing['claude-sonnet-4-20250514'];

    const inputCost = ((inputTokens - cacheReadTokens) / 1_000_000) * modelPricing.input;
    const outputCost = (outputTokens / 1_000_000) * modelPricing.output;
    const cacheWriteCost = (cacheCreationTokens / 1_000_000) * modelPricing.cacheWrite;
    const cacheReadCost = (cacheReadTokens / 1_000_000) * modelPricing.cacheRead;

    return inputCost + outputCost + cacheWriteCost + cacheReadCost;
  }
}
