/**
 * Router Helpers
 *
 * Shared require*() helpers that validate context dependencies
 * and throw TRPCError when a required dependency is missing.
 */

import { TRPCError } from '@trpc/server';
import type { TRPCContext } from '../context.js';
import type { TaskRepository } from '../../db/repositories/task-repository.js';
import type { MessageRepository } from '../../db/repositories/message-repository.js';
import type { InitiativeRepository } from '../../db/repositories/initiative-repository.js';
import type { PhaseRepository } from '../../db/repositories/phase-repository.js';
import type { PageRepository } from '../../db/repositories/page-repository.js';
import type { ProjectRepository } from '../../db/repositories/project-repository.js';
import type { AccountRepository } from '../../db/repositories/account-repository.js';
import type { ChangeSetRepository } from '../../db/repositories/change-set-repository.js';
import type { LogChunkRepository } from '../../db/repositories/log-chunk-repository.js';
import type { ConversationRepository } from '../../db/repositories/conversation-repository.js';
import type { ChatSessionRepository } from '../../db/repositories/chat-session-repository.js';
import type { ReviewCommentRepository } from '../../db/repositories/review-comment-repository.js';
import type { ErrandRepository } from '../../db/repositories/errand-repository.js';
import type { DispatchManager, PhaseDispatchManager } from '../../dispatch/types.js';
import type { CoordinationManager } from '../../coordination/types.js';
import type { BranchManager } from '../../git/branch-manager.js';
import type { ExecutionOrchestrator } from '../../execution/orchestrator.js';
import type { PreviewManager } from '../../preview/index.js';
import type { ProjectSyncManager } from '../../git/remote-sync.js';

export function requireAgentManager(ctx: TRPCContext) {
  if (!ctx.agentManager) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Agent manager not available',
    });
  }
  return ctx.agentManager;
}

export function requireTaskRepository(ctx: TRPCContext): TaskRepository {
  if (!ctx.taskRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Task repository not available',
    });
  }
  return ctx.taskRepository;
}

export function requireMessageRepository(ctx: TRPCContext): MessageRepository {
  if (!ctx.messageRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Message repository not available',
    });
  }
  return ctx.messageRepository;
}

export function requireDispatchManager(ctx: TRPCContext): DispatchManager {
  if (!ctx.dispatchManager) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Dispatch manager not available',
    });
  }
  return ctx.dispatchManager;
}

export function requireCoordinationManager(ctx: TRPCContext): CoordinationManager {
  if (!ctx.coordinationManager) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Coordination manager not available',
    });
  }
  return ctx.coordinationManager;
}

export function requireInitiativeRepository(ctx: TRPCContext): InitiativeRepository {
  if (!ctx.initiativeRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Initiative repository not available',
    });
  }
  return ctx.initiativeRepository;
}

export function requirePhaseRepository(ctx: TRPCContext): PhaseRepository {
  if (!ctx.phaseRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Phase repository not available',
    });
  }
  return ctx.phaseRepository;
}

export function requirePhaseDispatchManager(ctx: TRPCContext): PhaseDispatchManager {
  if (!ctx.phaseDispatchManager) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Phase dispatch manager not available',
    });
  }
  return ctx.phaseDispatchManager;
}

export function requirePageRepository(ctx: TRPCContext): PageRepository {
  if (!ctx.pageRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Page repository not available',
    });
  }
  return ctx.pageRepository;
}

export function requireProjectRepository(ctx: TRPCContext): ProjectRepository {
  if (!ctx.projectRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Project repository not available',
    });
  }
  return ctx.projectRepository;
}

export function requireAccountRepository(ctx: TRPCContext): AccountRepository {
  if (!ctx.accountRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Account repository not available',
    });
  }
  return ctx.accountRepository;
}

export function requireChangeSetRepository(ctx: TRPCContext): ChangeSetRepository {
  if (!ctx.changeSetRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Change set repository not available',
    });
  }
  return ctx.changeSetRepository;
}

export function requireLogChunkRepository(ctx: TRPCContext): LogChunkRepository {
  if (!ctx.logChunkRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Log chunk repository not available',
    });
  }
  return ctx.logChunkRepository;
}

export function requireBranchManager(ctx: TRPCContext): BranchManager {
  if (!ctx.branchManager) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Branch manager not available',
    });
  }
  return ctx.branchManager;
}

export function requireExecutionOrchestrator(ctx: TRPCContext): ExecutionOrchestrator {
  if (!ctx.executionOrchestrator) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Execution orchestrator not available',
    });
  }
  return ctx.executionOrchestrator;
}

export function requirePreviewManager(ctx: TRPCContext): PreviewManager {
  if (!ctx.previewManager) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Preview manager not available',
    });
  }
  return ctx.previewManager;
}

export function requireConversationRepository(ctx: TRPCContext): ConversationRepository {
  if (!ctx.conversationRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Conversation repository not available',
    });
  }
  return ctx.conversationRepository;
}

export function requireChatSessionRepository(ctx: TRPCContext): ChatSessionRepository {
  if (!ctx.chatSessionRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Chat session repository not available',
    });
  }
  return ctx.chatSessionRepository;
}

export function requireReviewCommentRepository(ctx: TRPCContext): ReviewCommentRepository {
  if (!ctx.reviewCommentRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Review comment repository not available',
    });
  }
  return ctx.reviewCommentRepository;
}

export function requireProjectSyncManager(ctx: TRPCContext): ProjectSyncManager {
  if (!ctx.projectSyncManager) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Project sync manager not available',
    });
  }
  return ctx.projectSyncManager;
}

export function requireErrandRepository(ctx: TRPCContext): ErrandRepository {
  if (!ctx.errandRepository) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'Errand repository not available',
    });
  }
  return ctx.errandRepository;
}
