/**
 * Phase Dispatch Router — queue, dispatch, state, child tasks
 */

import { TRPCError } from '@trpc/server';
import { z } from 'zod';
import type { Task } from '../../db/schema.js';
import type { ProcedureBuilder } from '../trpc.js';
import { requirePhaseDispatchManager, requirePhaseRepository, requireTaskRepository } from './_helpers.js';

export function phaseDispatchProcedures(publicProcedure: ProcedureBuilder) {
  return {
    queuePhase: publicProcedure
      .input(z.object({ phaseId: z.string().min(1) }))
      .mutation(async ({ ctx, input }) => {
        const phaseDispatchManager = requirePhaseDispatchManager(ctx);
        await phaseDispatchManager.queuePhase(input.phaseId);
        return { success: true };
      }),

    queueAllPhases: publicProcedure
      .input(z.object({ initiativeId: z.string().min(1) }))
      .mutation(async ({ ctx, input }) => {
        const phaseDispatchManager = requirePhaseDispatchManager(ctx);
        const phaseRepo = requirePhaseRepository(ctx);
        const phases = await phaseRepo.findByInitiativeId(input.initiativeId);
        let queued = 0;
        for (const phase of phases) {
          if (phase.status === 'approved') {
            await phaseDispatchManager.queuePhase(phase.id);
            queued++;
          }
        }
        return { success: true, queued };
      }),

    dispatchNextPhase: publicProcedure
      .mutation(async ({ ctx }) => {
        const phaseDispatchManager = requirePhaseDispatchManager(ctx);
        return phaseDispatchManager.dispatchNextPhase();
      }),

    getPhaseQueueState: publicProcedure
      .query(async ({ ctx }) => {
        const phaseDispatchManager = requirePhaseDispatchManager(ctx);
        return phaseDispatchManager.getPhaseQueueState();
      }),

    createChildTasks: publicProcedure
      .input(z.object({
        parentTaskId: z.string().min(1),
        tasks: z.array(z.object({
          number: z.number().int().positive(),
          name: z.string().min(1),
          description: z.string(),
          type: z.enum(['auto']).default('auto'),
          dependencies: z.array(z.number().int().positive()).optional(),
        })),
      }))
      .mutation(async ({ ctx, input }) => {
        const taskRepo = requireTaskRepository(ctx);

        const parentTask = await taskRepo.findById(input.parentTaskId);
        if (!parentTask) {
          throw new TRPCError({
            code: 'NOT_FOUND',
            message: `Parent task '${input.parentTaskId}' not found`,
          });
        }
        if (parentTask.category !== 'detail') {
          throw new TRPCError({
            code: 'BAD_REQUEST',
            message: `Parent task must have category 'detail', got '${parentTask.category}'`,
          });
        }

        const numberToId = new Map<number, string>();
        const created: Task[] = [];

        for (const taskInput of input.tasks) {
          const task = await taskRepo.create({
            parentTaskId: input.parentTaskId,
            phaseId: parentTask.phaseId,
            initiativeId: parentTask.initiativeId,
            name: taskInput.name,
            description: taskInput.description,
            type: taskInput.type,
            order: taskInput.number,
            status: 'pending',
          });
          numberToId.set(taskInput.number, task.id);
          created.push(task);
        }

        for (const taskInput of input.tasks) {
          if (taskInput.dependencies && taskInput.dependencies.length > 0) {
            const taskId = numberToId.get(taskInput.number)!;
            for (const depNumber of taskInput.dependencies) {
              const dependsOnTaskId = numberToId.get(depNumber);
              if (dependsOnTaskId) {
                await taskRepo.createDependency(taskId, dependsOnTaskId);
              }
            }
          }
        }

        return created;
      }),
  };
}
