/**
 * Checkpoints API Routes
 *
 * 提供 Checkpoint 管理的 REST API
 */

import { Hono } from 'hono';
import { getConfig } from './config.js';

// Core Checkpoint 模块类型
interface CheckpointModule {
  getCheckpointManager: () => CheckpointManager;
  initCheckpointManager: (
    workDir: string,
    config?: Partial<CheckpointConfig>
  ) => Promise<CheckpointManager>;
  RestoreMode: typeof RestoreMode;
}

interface CheckpointManager {
  initialize(): Promise<void>;
  isEnabled(): boolean;
  getConfig(): CheckpointConfig;
  listCheckpoints(): Promise<CheckpointMetadata[]>;
  getCheckpoint(idOrHash: string): Promise<CheckpointMetadata | null>;
  getLatestCheckpoint(): Promise<CheckpointMetadata | null>;
  createCheckpoint(options: {
    name?: string;
    description?: string;
    trigger?: CheckpointTrigger;
  }): Promise<CheckpointMetadata>;
  deleteCheckpoint(id: string): Promise<boolean>;
  getDiff(checkpointId: string): Promise<DiffInfo>;
  getFileDiff(checkpointId: string, filePath: string): Promise<FileDiff>;
  rollback(options: RollbackOptions): Promise<RollbackResult>;
  checkSafety(checkpointId: string): Promise<SafetyCheckResult>;
  unrevert(): Promise<UnrevertResult>;
  canUnrevert(): boolean;
  getLastRollback(): RollbackRecord | null;
  cleanup(): Promise<number>;
  getStats(): Promise<CheckpointStats>;
  getSessionCheckpoints(sessionId: string): Promise<CheckpointMetadata[]>;
  getMessageCheckpoints(messageId: string): Promise<CheckpointMetadata[]>;
}

interface CheckpointConfig {
  enabled: boolean;
  autoCheckpoint: {
    beforeWrite: boolean;
    beforeEdit: boolean;
    beforeDelete: boolean;
    beforeMove: boolean;
    beforeBash: boolean;
  };
  maxCheckpoints: number;
  maxAge: number;
  storageDir: string;
}

type CheckpointTrigger =
  | 'auto'
  | 'manual'
  | 'tool:write_file'
  | 'tool:edit_file'
  | 'tool:delete_file'
  | 'tool:move_file'
  | 'tool:copy_file'
  | 'tool:bash'
  | 'task_start'
  | 'task_complete'
  | 'pre_rollback'
  | 'session_start'
  | 'session_end';

interface CheckpointMetadata {
  id: string;
  name?: string;
  description?: string;
  timestamp: number;
  trigger: CheckpointTrigger;
  toolCall?: {
    tool: string;
    params: Record<string, unknown>;
  };
  commitHash: string;
  filesChanged: number;
  messageId?: string;
  sessionId?: string;
  turnIndex?: number;
}

type FileChangeType = 'added' | 'modified' | 'deleted' | 'renamed';

interface FileChange {
  path: string;
  type: FileChangeType;
  oldPath?: string;
  insertions?: number;
  deletions?: number;
}

interface DiffInfo {
  from: string;
  to: string;
  files: FileChange[];
  totalInsertions: number;
  totalDeletions: number;
}

interface FileDiff {
  path: string;
  type: FileChangeType;
  oldContent?: string;
  newContent?: string;
  patch?: string;
}

enum RestoreMode {
  AI_CHANGES_ONLY = 'ai_changes_only',
  WORKSPACE_ONLY = 'workspace_only',
  FULL = 'full',
}

interface RollbackOptions {
  target: string;
  files?: string[];
  dryRun?: boolean;
  mode?: RestoreMode;
  skipSafetyCheck?: boolean;
}

interface RollbackResult {
  success: boolean;
  restoredFiles: string[];
  errors: Array<{ file: string; error: string }>;
  previousCommit?: string;
}

interface SafetyCheckResult {
  safe: boolean;
  warnings: string[];
  errors: string[];
}

interface RollbackRecord {
  id: string;
  timestamp: number;
  targetCheckpoint: string;
  previousCommit: string;
  restoredFiles: string[];
  canUnrevert: boolean;
}

interface UnrevertResult {
  success: boolean;
  restoredCommit: string;
  filesRestored: number;
  error?: string;
}

interface CheckpointStats {
  count: number;
  oldestTimestamp: number | null;
  newestTimestamp: number | null;
}

export const checkpointsRouter = new Hono();

// Core 模块缓存
let checkpointModule: CheckpointModule | null = null;
let managerInitialized = false;

/**
 * 初始化 Checkpoint 模块
 */
async function initCheckpointModule(): Promise<CheckpointModule | null> {
  if (checkpointModule && managerInitialized) return checkpointModule;

  try {
    const corePath = '@ai-assistant/core';
    const core = (await import(corePath)) as Record<string, unknown>;

    if (
      typeof core.getCheckpointManager !== 'function' ||
      typeof core.initCheckpointManager !== 'function'
    ) {
      console.warn('[Checkpoints] Core module missing Checkpoint exports');
      return null;
    }

    checkpointModule = {
      getCheckpointManager: core.getCheckpointManager as () => CheckpointManager,
      initCheckpointManager: core.initCheckpointManager as (
        workDir: string,
        config?: Partial<CheckpointConfig>
      ) => Promise<CheckpointManager>,
      RestoreMode: core.RestoreMode as typeof RestoreMode,
    };

    // 初始化 Checkpoint Manager
    const config = getConfig();
    await checkpointModule.initCheckpointManager(config.workdir);
    managerInitialized = true;

    console.log('[Checkpoints] Checkpoint module initialized');
    return checkpointModule;
  } catch (error) {
    console.warn('[Checkpoints] Failed to load Checkpoint module:', error);
    return null;
  }
}

/**
 * GET /checkpoints - 获取所有检查点列表
 */
checkpointsRouter.get('/', async (c) => {
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const checkpoints = await manager.listCheckpoints();

    return c.json({
      success: true,
      data: checkpoints.map((cp) => ({
        id: cp.id,
        name: cp.name,
        description: cp.description,
        timestamp: cp.timestamp,
        trigger: cp.trigger,
        filesChanged: cp.filesChanged,
        commitHash: cp.commitHash,
        messageId: cp.messageId,
        sessionId: cp.sessionId,
      })),
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to list checkpoints',
      },
      500
    );
  }
});

/**
 * GET /checkpoints/stats - 获取检查点统计信息
 */
checkpointsRouter.get('/stats', async (c) => {
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const stats = await manager.getStats();

    return c.json({
      success: true,
      data: stats,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to get stats',
      },
      500
    );
  }
});

/**
 * GET /checkpoints/latest - 获取最新检查点
 */
checkpointsRouter.get('/latest', async (c) => {
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const checkpoint = await manager.getLatestCheckpoint();

    return c.json({
      success: true,
      data: checkpoint,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to get latest checkpoint',
      },
      500
    );
  }
});

/**
 * GET /checkpoints/unrevert/status - 检查是否可撤销回滚
 */
checkpointsRouter.get('/unrevert/status', async (c) => {
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const canUnrevert = manager.canUnrevert();
    const lastRollback = manager.getLastRollback();

    return c.json({
      success: true,
      data: {
        canUnrevert,
        lastRollback: lastRollback
          ? {
              id: lastRollback.id,
              timestamp: lastRollback.timestamp,
              targetCheckpoint: lastRollback.targetCheckpoint,
              restoredFiles: lastRollback.restoredFiles,
            }
          : null,
      },
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to get unrevert status',
      },
      500
    );
  }
});

/**
 * GET /checkpoints/:id - 获取单个检查点详情
 */
checkpointsRouter.get('/:id', async (c) => {
  const id = c.req.param('id');
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const checkpoint = await manager.getCheckpoint(id);

    if (!checkpoint) {
      return c.json(
        {
          success: false,
          error: `Checkpoint not found: ${id}`,
        },
        404
      );
    }

    return c.json({
      success: true,
      data: checkpoint,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to get checkpoint',
      },
      500
    );
  }
});

/**
 * POST /checkpoints - 创建手动检查点
 */
checkpointsRouter.post('/', async (c) => {
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const body = await c.req.json<{ name?: string; description?: string }>();
    const manager = module.getCheckpointManager();

    const checkpoint = await manager.createCheckpoint({
      name: body.name,
      description: body.description,
      trigger: 'manual',
    });

    return c.json({
      success: true,
      data: checkpoint,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to create checkpoint',
      },
      500
    );
  }
});

/**
 * DELETE /checkpoints/:id - 删除检查点
 */
checkpointsRouter.delete('/:id', async (c) => {
  const id = c.req.param('id');
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const deleted = await manager.deleteCheckpoint(id);

    if (!deleted) {
      return c.json(
        {
          success: false,
          error: `Checkpoint not found: ${id}`,
        },
        404
      );
    }

    return c.json({
      success: true,
      data: { deleted: true },
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to delete checkpoint',
      },
      500
    );
  }
});

/**
 * GET /checkpoints/:id/diff - 获取检查点与当前工作区的差异
 */
checkpointsRouter.get('/:id/diff', async (c) => {
  const id = c.req.param('id');
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const diff = await manager.getDiff(id);

    return c.json({
      success: true,
      data: diff,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to get diff',
      },
      500
    );
  }
});

/**
 * GET /checkpoints/:id/file-diff - 获取单个文件的详细差异
 */
checkpointsRouter.get('/:id/file-diff', async (c) => {
  const id = c.req.param('id');
  const filePath = c.req.query('path');
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  if (!filePath) {
    return c.json(
      {
        success: false,
        error: 'File path is required',
      },
      400
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const fileDiff = await manager.getFileDiff(id, filePath);

    return c.json({
      success: true,
      data: fileDiff,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to get file diff',
      },
      500
    );
  }
});

/**
 * POST /checkpoints/:id/restore - 回滚到检查点
 */
checkpointsRouter.post('/:id/restore', async (c) => {
  const id = c.req.param('id');
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const body = await c.req.json<{
      mode?: 'ai_changes_only' | 'workspace_only' | 'full';
      files?: string[];
      skipSafetyCheck?: boolean;
    }>();

    const manager = module.getCheckpointManager();

    // 转换 mode 字符串为枚举值
    let mode: RestoreMode | undefined;
    if (body.mode) {
      switch (body.mode) {
        case 'ai_changes_only':
          mode = module.RestoreMode.AI_CHANGES_ONLY;
          break;
        case 'workspace_only':
          mode = module.RestoreMode.WORKSPACE_ONLY;
          break;
        case 'full':
          mode = module.RestoreMode.FULL;
          break;
      }
    }

    const result = await manager.rollback({
      target: id,
      mode,
      files: body.files,
      skipSafetyCheck: body.skipSafetyCheck,
    });

    return c.json({
      success: true,
      data: result,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to restore checkpoint',
      },
      500
    );
  }
});

/**
 * GET /checkpoints/:id/restore/preview - 预览回滚（dry run）
 */
checkpointsRouter.get('/:id/restore/preview', async (c) => {
  const id = c.req.param('id');
  const modeParam = c.req.query('mode');
  const filesParam = c.req.query('files');
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();

    // 转换 mode 字符串为枚举值
    let mode: RestoreMode | undefined;
    if (modeParam) {
      switch (modeParam) {
        case 'ai_changes_only':
          mode = module.RestoreMode.AI_CHANGES_ONLY;
          break;
        case 'workspace_only':
          mode = module.RestoreMode.WORKSPACE_ONLY;
          break;
        case 'full':
          mode = module.RestoreMode.FULL;
          break;
      }
    }

    const files = filesParam ? filesParam.split(',') : undefined;

    const result = await manager.rollback({
      target: id,
      mode,
      files,
      dryRun: true,
    });

    return c.json({
      success: true,
      data: result,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to preview restore',
      },
      500
    );
  }
});

/**
 * POST /checkpoints/unrevert - 撤销最近一次回滚
 */
checkpointsRouter.post('/unrevert', async (c) => {
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const result = await manager.unrevert();

    if (!result.success) {
      return c.json(
        {
          success: false,
          error: result.error || 'Failed to unrevert',
        },
        400
      );
    }

    return c.json({
      success: true,
      data: result,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to unrevert',
      },
      500
    );
  }
});

/**
 * GET /checkpoints/:id/safety-check - 执行安全检查
 */
checkpointsRouter.get('/:id/safety-check', async (c) => {
  const id = c.req.param('id');
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const result = await manager.checkSafety(id);

    return c.json({
      success: true,
      data: result,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to check safety',
      },
      500
    );
  }
});

/**
 * POST /checkpoints/cleanup - 清理过期检查点
 */
checkpointsRouter.post('/cleanup', async (c) => {
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const deleted = await manager.cleanup();

    return c.json({
      success: true,
      data: { deleted },
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to cleanup',
      },
      500
    );
  }
});

/**
 * GET /checkpoints/sessions/:sessionId - 获取会话的所有检查点
 */
checkpointsRouter.get('/sessions/:sessionId', async (c) => {
  const sessionId = c.req.param('sessionId');
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const checkpoints = await manager.getSessionCheckpoints(sessionId);

    return c.json({
      success: true,
      data: checkpoints,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to get session checkpoints',
      },
      500
    );
  }
});

/**
 * GET /checkpoints/messages/:messageId - 获取消息关联的检查点
 */
checkpointsRouter.get('/messages/:messageId', async (c) => {
  const messageId = c.req.param('messageId');
  const module = await initCheckpointModule();

  if (!module) {
    return c.json(
      {
        success: false,
        error: 'Checkpoint module not available',
      },
      503
    );
  }

  try {
    const manager = module.getCheckpointManager();
    const checkpoints = await manager.getMessageCheckpoints(messageId);

    return c.json({
      success: true,
      data: checkpoints,
    });
  } catch (error) {
    return c.json(
      {
        success: false,
        error: error instanceof Error ? error.message : 'Failed to get message checkpoints',
      },
      500
    );
  }
});
