/**
 * CleanupStrategy — Centralized cleanup logic based on debug mode and agent state.
 *
 * Determines when and how to clean up agent workdirs and resources.
 * Supports archive mode for debugging vs. immediate cleanup for production.
 */

import { createModuleLogger } from '../../logger/index.js';
import type { CleanupManager } from '../cleanup-manager.js';

const log = createModuleLogger('cleanup-strategy');

export type CleanupAction = 'remove' | 'archive' | 'preserve';

export interface AgentInfo {
  id: string;
  name: string;
  status: string;
  initiativeId?: string | null;
  worktreeId: string;
}

export interface CleanupStrategy {
  shouldCleanup(agent: AgentInfo, isDebugMode: boolean): Promise<CleanupAction>;
  executeCleanup(agent: AgentInfo, action: CleanupAction): Promise<void>;
}

export class DefaultCleanupStrategy implements CleanupStrategy {
  constructor(private cleanupManager: CleanupManager) {}

  /**
   * Determine what cleanup action should be taken for an agent.
   * Considers agent status and debug mode setting.
   */
  async shouldCleanup(agent: AgentInfo, isDebugMode: boolean): Promise<CleanupAction> {
    log.debug({
      agentId: agent.id,
      name: agent.name,
      status: agent.status,
      isDebugMode
    }, 'evaluating cleanup action for agent');

    // Never cleanup agents waiting for user input
    if (agent.status === 'waiting_for_input') {
      log.debug({ agentId: agent.id, status: agent.status }, 'preserving agent waiting for input');
      return 'preserve';
    }

    // Never cleanup running agents
    if (agent.status === 'running') {
      log.debug({ agentId: agent.id, status: agent.status }, 'preserving running agent');
      return 'preserve';
    }

    // For completed/idle/crashed agents, decide based on debug mode
    if (agent.status === 'idle' || agent.status === 'completed' || agent.status === 'crashed') {
      if (isDebugMode) {
        log.debug({ agentId: agent.id, status: agent.status }, 'archiving agent in debug mode');
        return 'archive';
      } else {
        log.debug({ agentId: agent.id, status: agent.status }, 'removing agent in production mode');
        return 'remove';
      }
    }

    // For stopped agents, clean up immediately regardless of debug mode
    if (agent.status === 'stopped') {
      log.debug({ agentId: agent.id, status: agent.status }, 'removing stopped agent');
      return 'remove';
    }

    // Default to preserve for any unrecognized status
    log.debug({ agentId: agent.id, status: agent.status }, 'preserving agent with unrecognized status');
    return 'preserve';
  }

  /**
   * Execute the determined cleanup action.
   */
  async executeCleanup(agent: AgentInfo, action: CleanupAction): Promise<void> {
    log.debug({
      agentId: agent.id,
      name: agent.name,
      action
    }, 'executing cleanup action');

    switch (action) {
      case 'remove':
        await this.cleanupManager.removeAgentWorktrees(agent.name, agent.initiativeId ?? null);
        await this.cleanupManager.removeAgentBranches(agent.name, agent.initiativeId ?? null);
        await this.cleanupManager.removeAgentLogs(agent.id);
        log.info({ agentId: agent.id, name: agent.name }, 'agent workdir and resources removed');
        break;

      case 'archive':
        await this.cleanupManager.archiveForDebug(agent.worktreeId, agent.id);
        log.info({ agentId: agent.id, name: agent.name }, 'agent workdir archived for debugging');
        break;

      case 'preserve':
        log.debug({ agentId: agent.id, name: agent.name }, 'agent workdir preserved');
        break;

      default:
        log.warn({ agentId: agent.id, action }, 'unknown cleanup action, preserving by default');
    }
  }
}