/**
 * 智能提交消息生成模块
 * 参考 Aider 的 AI 提交消息生成
 */

import * as path from 'path';
import type { CheckpointTrigger, FileChange } from './types.js';

/**
 * 工具调用信息
 */
interface ToolCallInfo {
  tool: string;
  params: Record<string, unknown>;
}

/**
 * 提交消息生成器
 * 生成人类可读的检查点提交消息
 */
export class CommitMessageGenerator {
  /**
   * 生成提交消息
   */
  generateMessage(
    trigger: CheckpointTrigger,
    toolCall?: ToolCallInfo,
    filesChanged?: FileChange[]
  ): string {
    const prefix = this.getTriggerPrefix(trigger);
    const description = this.getDescription(trigger, toolCall, filesChanged);
    const body = this.generateBody(trigger, toolCall, filesChanged);

    if (body) {
      return `${prefix}: ${description}\n\n${body}`;
    }

    return `${prefix}: ${description}`;
  }

  /**
   * 获取触发类型的前缀
   */
  private getTriggerPrefix(trigger: CheckpointTrigger): string {
    const prefixes: Record<CheckpointTrigger, string> = {
      auto: 'auto',
      manual: 'checkpoint',
      'tool:write_file': 'write',
      'tool:edit_file': 'edit',
      'tool:delete_file': 'delete',
      'tool:move_file': 'move',
      'tool:copy_file': 'copy',
      'tool:bash': 'bash',
      task_start: 'session-start',
      task_complete: 'session-end',
      pre_rollback: 'pre-rollback',
      session_start: 'session-start',
      session_end: 'session-end',
    };

    return prefixes[trigger] || 'checkpoint';
  }

  /**
   * 生成描述
   */
  private getDescription(
    trigger: CheckpointTrigger,
    toolCall?: ToolCallInfo,
    filesChanged?: FileChange[]
  ): string {
    // 从工具调用参数获取文件路径
    if (toolCall) {
      const filePath =
        (toolCall.params.file_path as string) ||
        (toolCall.params.path as string);

      if (filePath) {
        return this.formatFilePath(filePath);
      }

      // bash 命令
      if (toolCall.tool === 'bash') {
        const command = String(toolCall.params.command || '');
        return this.formatCommand(command);
      }

      // 移动/复制操作
      if (toolCall.params.source && toolCall.params.destination) {
        const source = this.formatFilePath(String(toolCall.params.source));
        const dest = this.formatFilePath(String(toolCall.params.destination));
        return `${source} -> ${dest}`;
      }
    }

    // 从文件变更列表获取描述
    if (filesChanged && filesChanged.length > 0) {
      if (filesChanged.length === 1) {
        return this.formatFilePath(filesChanged[0].path);
      }
      return `${filesChanged.length} files`;
    }

    // 根据触发类型生成描述
    switch (trigger) {
      case 'task_start':
      case 'session_start':
        return 'begin session';
      case 'task_complete':
      case 'session_end':
        return 'end session';
      case 'pre_rollback':
        return 'state before rollback';
      case 'manual':
        return 'manual checkpoint';
      default:
        return 'state snapshot';
    }
  }

  /**
   * 生成消息正文
   */
  private generateBody(
    trigger: CheckpointTrigger,
    toolCall?: ToolCallInfo,
    filesChanged?: FileChange[]
  ): string {
    const lines: string[] = [];

    // 时间戳
    lines.push(`Time: ${new Date().toISOString()}`);

    // 触发类型
    lines.push(`Trigger: ${trigger}`);

    // 工具信息
    if (toolCall) {
      lines.push(`Tool: ${toolCall.tool}`);
    }

    // 文件变更统计
    if (filesChanged && filesChanged.length > 0) {
      const stats = this.calculateStats(filesChanged);
      lines.push(`Files: ${filesChanged.length}`);
      if (stats.insertions > 0 || stats.deletions > 0) {
        lines.push(`Changes: +${stats.insertions} -${stats.deletions}`);
      }
    }

    return lines.join('\n');
  }

  /**
   * 格式化文件路径（只保留文件名和父目录）
   */
  private formatFilePath(filePath: string): string {
    const parts = filePath.split(path.sep);

    if (parts.length <= 2) {
      return filePath;
    }

    // 返回 父目录/文件名 格式
    return parts.slice(-2).join('/');
  }

  /**
   * 格式化命令（截断过长的命令）
   */
  private formatCommand(command: string): string {
    const maxLength = 50;
    const trimmed = command.trim();

    if (trimmed.length <= maxLength) {
      return `"${trimmed}"`;
    }

    return `"${trimmed.slice(0, maxLength - 3)}..."`;
  }

  /**
   * 计算文件变更统计
   */
  private calculateStats(filesChanged: FileChange[]): {
    insertions: number;
    deletions: number;
    added: number;
    modified: number;
    deleted: number;
    renamed: number;
  } {
    let insertions = 0;
    let deletions = 0;
    let added = 0;
    let modified = 0;
    let deleted = 0;
    let renamed = 0;

    for (const file of filesChanged) {
      insertions += file.insertions || 0;
      deletions += file.deletions || 0;

      switch (file.type) {
        case 'added':
          added++;
          break;
        case 'modified':
          modified++;
          break;
        case 'deleted':
          deleted++;
          break;
        case 'renamed':
          renamed++;
          break;
      }
    }

    return { insertions, deletions, added, modified, deleted, renamed };
  }

  /**
   * 生成简短的提交消息（单行）
   */
  generateShortMessage(
    trigger: CheckpointTrigger,
    toolCall?: ToolCallInfo
  ): string {
    const prefix = this.getTriggerPrefix(trigger);
    const description = this.getDescription(trigger, toolCall);
    return `${prefix}: ${description}`;
  }

  /**
   * 从提交消息解析元数据
   */
  parseMessage(message: string): {
    prefix: string;
    description: string;
    metadata: Record<string, string>;
  } {
    const lines = message.split('\n');
    const firstLine = lines[0] || '';

    // 解析第一行: prefix: description
    const [prefix, ...descParts] = firstLine.split(':');
    const description = descParts.join(':').trim();

    // 解析元数据
    const metadata: Record<string, string> = {};
    for (let i = 2; i < lines.length; i++) {
      const line = lines[i];
      const colonIndex = line.indexOf(':');
      if (colonIndex > 0) {
        const key = line.slice(0, colonIndex).trim();
        const value = line.slice(colonIndex + 1).trim();
        metadata[key] = value;
      }
    }

    return {
      prefix: prefix.trim(),
      description,
      metadata,
    };
  }
}

/**
 * 创建提交消息生成器实例
 */
export function createCommitMessageGenerator(): CommitMessageGenerator {
  return new CommitMessageGenerator();
}
