/**
 * Quality Review Service
 *
 * Decides whether to run a quality review after a task agent completes,
 * and orchestrates spawning the review agent.
 *
 * All dependencies are passed as function parameters (hexagonal DI pattern).
 */

import type { BranchManager } from '../git/branch-manager.js';
import type { AgentRepository } from '../db/repositories/agent-repository.js';
import type { TaskRepository } from '../db/repositories/task-repository.js';
import type { InitiativeRepository } from '../db/repositories/initiative-repository.js';
import type { AgentManager } from '../agent/types.js';
import type { Logger } from 'pino';

// ---------------------------------------------------------------------------
// computeQualifyingFiles
// ---------------------------------------------------------------------------

/**
 * Compute source files in the diff between taskBranch and baseBranch that
 * qualify for a quality review (excludes *.gen.ts and dist/ paths).
 *
 * Returns [] if the diff throws (treated as no qualifying files).
 */
export async function computeQualifyingFiles(
  repoPath: string,
  taskBranch: string,
  baseBranch: string,
  branchManager: BranchManager,
): Promise<string[]> {
  try {
    const entries = await branchManager.diffBranchesStat(repoPath, baseBranch, taskBranch);
    return entries
      .map((e) => e.path)
      .filter((p) => !p.endsWith('.gen.ts'))
      .filter((p) => !p.startsWith('dist/') && !p.includes('/dist/'));
  } catch {
    return [];
  }
}

// ---------------------------------------------------------------------------
// shouldRunQualityReview
// ---------------------------------------------------------------------------

export interface QualityReviewCheckParams {
  agentId: string;
  taskId: string;
  stopReason: string;
  repoPath: string;
  taskBranch: string;
  baseBranch: string;
  agentRepository: AgentRepository;
  taskRepository: TaskRepository;
  initiativeRepository: InitiativeRepository;
  branchManager: BranchManager;
}

/**
 * Determine whether a quality review should be run for the given agent stop event.
 *
 * Returns { run: true, qualifyingFiles } only when all six conditions pass:
 * 1. stopReason === 'task_complete'
 * 2. Agent mode is 'execute'
 * 3. Task status is 'in_progress' (not 'quality_review' — recursion guard)
 * 4. task.initiativeId is non-null
 * 5. initiative.qualityReview === true
 * 6. computeQualifyingFiles() returns a non-empty array
 */
export async function shouldRunQualityReview(
  params: QualityReviewCheckParams,
): Promise<{ run: boolean; qualifyingFiles: string[] }> {
  const { agentId, taskId, stopReason, repoPath, taskBranch, baseBranch, agentRepository, taskRepository, initiativeRepository, branchManager } = params;
  const NO = { run: false, qualifyingFiles: [] };

  // 1. Only fire on task_complete
  if (stopReason !== 'task_complete') return NO;

  // 2. Agent mode must be 'execute'
  const agent = await agentRepository.findById(agentId);
  if (!agent || agent.mode !== 'execute') return NO;

  // 3. Task status must be 'in_progress' (recursion guard: skip if already quality_review)
  const task = await taskRepository.findById(taskId);
  if (!task) return NO;
  if (task.status === 'quality_review') return NO;
  if (task.status !== 'in_progress') return NO;

  // 4. Task must belong to an initiative
  if (!task.initiativeId) return NO;

  // 5. Initiative must have qualityReview enabled
  const initiative = await initiativeRepository.findById(task.initiativeId);
  if (!initiative || !initiative.qualityReview) return NO;

  // 6. Must have qualifying files in the changeset
  const qualifyingFiles = await computeQualifyingFiles(repoPath, taskBranch, baseBranch, branchManager);
  if (qualifyingFiles.length === 0) return NO;

  return { run: true, qualifyingFiles };
}

// ---------------------------------------------------------------------------
// runQualityReview
// ---------------------------------------------------------------------------

export interface QualityReviewRunParams {
  taskId: string;
  taskBranch: string;
  baseBranch: string;
  initiativeId: string;
  qualifyingFiles: string[];
  taskRepository: TaskRepository;
  agentManager: AgentManager;
  log: Logger;
}

/**
 * Spawn a quality review agent on the task branch.
 *
 * 1. Transitions task to 'quality_review'
 * 2. Builds /simplify prompt with qualifying files
 * 3. Spawns execute-mode agent on the same task branch
 * 4. Logs the review agent ID
 * 5. On spawn error: logs and transitions task to 'completed' — never throws
 */
export async function runQualityReview(params: QualityReviewRunParams): Promise<void> {
  const { taskId, taskBranch, baseBranch, initiativeId, qualifyingFiles, taskRepository, agentManager, log } = params;

  await taskRepository.update(taskId, { status: 'quality_review' });

  const fileList = qualifyingFiles.join('\n');
  const prompt = `Run /simplify to review and fix code quality in this branch.\n\n${fileList}`;

  try {
    const reviewAgent = await agentManager.spawn({
      taskId,
      initiativeId,
      prompt,
      mode: 'execute',
      baseBranch,
      branchName: taskBranch,
    });

    log.info({ taskId, reviewAgentId: reviewAgent.id }, 'quality review agent spawned');
  } catch (err) {
    log.error({ taskId, err: err instanceof Error ? err.message : String(err) }, 'quality review agent spawn failed');
    await taskRepository.update(taskId, { status: 'completed' });
  }
}
