/**
 * ConflictResolutionService
 *
 * Service responsible for handling merge conflicts by:
 * - Creating conflict resolution tasks
 * - Updating original task status
 * - Notifying agents via messages
 * - Emitting appropriate events
 *
 * This service is used by the CoordinationManager when merge conflicts occur.
 */

import type { EventBus, TaskQueuedEvent } from '../events/index.js';
import type { TaskRepository } from '../db/repositories/task-repository.js';
import type { AgentRepository } from '../db/repositories/agent-repository.js';
import type { MessageRepository } from '../db/repositories/message-repository.js';

// =============================================================================
// ConflictResolutionService Interface (Port)
// =============================================================================

/**
 * Service interface for handling merge conflicts.
 * This is the PORT - implementations are ADAPTERS.
 */
/**
 * Branch context for merge conflicts from the branch hierarchy.
 */
export interface MergeContext {
  sourceBranch: string;
  targetBranch: string;
}

export interface ConflictResolutionService {
  /**
   * Handle a merge conflict by creating resolution task and notifying agent.
   *
   * @param taskId - ID of the task that conflicted
   * @param conflicts - List of conflicting file paths
   * @param mergeContext - Optional branch context for branch hierarchy merges
   */
  handleConflict(taskId: string, conflicts: string[], mergeContext?: MergeContext): Promise<void>;
}

// =============================================================================
// DefaultConflictResolutionService Implementation (Adapter)
// =============================================================================

/**
 * Default implementation of ConflictResolutionService.
 *
 * Creates conflict resolution tasks, updates task statuses, sends messages
 * to agents, and emits events when merge conflicts occur.
 */
export class DefaultConflictResolutionService implements ConflictResolutionService {
  constructor(
    private taskRepository: TaskRepository,
    private agentRepository: AgentRepository,
    private messageRepository?: MessageRepository,
    private eventBus?: EventBus
  ) {}

  /**
   * Handle a merge conflict.
   * Creates a conflict-resolution task and notifies the agent via message.
   */
  async handleConflict(taskId: string, conflicts: string[], mergeContext?: MergeContext): Promise<void> {
    // Get original task for context
    const originalTask = await this.taskRepository.findById(taskId);
    if (!originalTask) {
      throw new Error(`Original task not found: ${taskId}`);
    }

    // Get agent that was working on the task
    const agent = await this.agentRepository.findByTaskId(taskId);
    if (!agent) {
      throw new Error(`No agent found for task: ${taskId}`);
    }

    // Build conflict description
    const descriptionLines = [
      'Merge conflicts detected. Resolve conflicts in the following files:',
      '',
      ...conflicts.map((f) => `- ${f}`),
      '',
      `Original task: ${originalTask.name}`,
      '',
    ];

    if (mergeContext) {
      descriptionLines.push(
        `Resolve merge conflicts between branch "${mergeContext.sourceBranch}" and "${mergeContext.targetBranch}".`,
        `Run: git merge ${mergeContext.sourceBranch} --no-edit`,
        'Resolve all conflicts, then: git add . && git commit',
      );
    } else {
      descriptionLines.push(
        'Instructions: Resolve merge conflicts in the listed files, then mark task complete.',
      );
    }

    const conflictDescription = descriptionLines.join('\n');

    // Create new conflict-resolution task
    const conflictTask = await this.taskRepository.create({
      parentTaskId: originalTask.parentTaskId,
      phaseId: originalTask.phaseId,
      initiativeId: originalTask.initiativeId,
      name: `Resolve conflicts: ${originalTask.name}`,
      description: conflictDescription,
      category: mergeContext ? 'merge' : 'execute',
      type: 'auto',
      priority: 'high',
      status: 'pending',
      order: originalTask.order + 1,
    });

    // Update original task status to blocked
    await this.taskRepository.update(taskId, { status: 'blocked' });

    // Create message to agent if messageRepository is configured
    if (this.messageRepository) {
      const messageContent = [
        `Merge conflict detected for task: ${originalTask.name}`,
        '',
        'Conflicting files:',
        ...conflicts.map((f) => `- ${f}`),
        '',
        `A new task has been created to resolve these conflicts: ${conflictTask.name}`,
        '',
        'Please resolve the merge conflicts in the listed files and mark the resolution task as complete.',
      ].join('\n');

      await this.messageRepository.create({
        senderType: 'user', // System-generated messages appear as from user
        senderId: null,
        recipientType: 'agent',
        recipientId: agent.id,
        type: 'info',
        content: messageContent,
        requiresResponse: false,
      });
    }

    // Emit TaskQueuedEvent for the new conflict-resolution task
    if (this.eventBus) {
      const event: TaskQueuedEvent = {
        type: 'task:queued',
        timestamp: new Date(),
        payload: {
          taskId: conflictTask.id,
          priority: 'high',
          dependsOn: [],
        },
      };
      this.eventBus.emit(event);
    }
  }
}