/**
 * Initiative Router — create, list, get, update, merge config
 */

import { TRPCError } from '@trpc/server';
import { z } from 'zod';
import type { ProcedureBuilder } from '../trpc.js';
import { requireInitiativeRepository, requireProjectRepository } from './_helpers.js';

export function initiativeProcedures(publicProcedure: ProcedureBuilder) {
  return {
    createInitiative: publicProcedure
      .input(z.object({
        name: z.string().min(1),
        branch: z.string().nullable().optional(),
        projectIds: z.array(z.string().min(1)).min(1).optional(),
        executionMode: z.enum(['yolo', 'review_per_phase']).optional(),
      }))
      .mutation(async ({ ctx, input }) => {
        const repo = requireInitiativeRepository(ctx);

        if (input.projectIds && input.projectIds.length > 0) {
          const projectRepo = requireProjectRepository(ctx);
          for (const pid of input.projectIds) {
            const project = await projectRepo.findById(pid);
            if (!project) {
              throw new TRPCError({
                code: 'NOT_FOUND',
                message: `Project '${pid}' not found`,
              });
            }
          }
        }

        const initiative = await repo.create({
          name: input.name,
          status: 'active',
          ...(input.executionMode && { executionMode: input.executionMode }),
          ...(input.branch && { branch: input.branch }),
        });

        if (input.projectIds && input.projectIds.length > 0) {
          const projectRepo = requireProjectRepository(ctx);
          await projectRepo.setInitiativeProjects(initiative.id, input.projectIds);
        }

        if (ctx.pageRepository) {
          await ctx.pageRepository.create({
            initiativeId: initiative.id,
            parentPageId: null,
            title: input.name,
            content: null,
            sortOrder: 0,
          });
        }

        return initiative;
      }),

    listInitiatives: publicProcedure
      .input(z.object({
        status: z.enum(['active', 'completed', 'archived']).optional(),
      }).optional())
      .query(async ({ ctx, input }) => {
        const repo = requireInitiativeRepository(ctx);
        if (input?.status) {
          return repo.findByStatus(input.status);
        }
        return repo.findAll();
      }),

    getInitiative: publicProcedure
      .input(z.object({ id: z.string().min(1) }))
      .query(async ({ ctx, input }) => {
        const repo = requireInitiativeRepository(ctx);
        const initiative = await repo.findById(input.id);
        if (!initiative) {
          throw new TRPCError({
            code: 'NOT_FOUND',
            message: `Initiative '${input.id}' not found`,
          });
        }

        let projects: Array<{ id: string; name: string; url: string }> = [];
        if (ctx.projectRepository) {
          const fullProjects = await ctx.projectRepository.findProjectsByInitiativeId(input.id);
          projects = fullProjects.map((p) => ({ id: p.id, name: p.name, url: p.url }));
        }

        return { ...initiative, projects };
      }),

    updateInitiative: publicProcedure
      .input(z.object({
        id: z.string().min(1),
        name: z.string().min(1).optional(),
        status: z.enum(['active', 'completed', 'archived']).optional(),
      }))
      .mutation(async ({ ctx, input }) => {
        const repo = requireInitiativeRepository(ctx);
        const { id, ...data } = input;
        return repo.update(id, data);
      }),

    updateInitiativeConfig: publicProcedure
      .input(z.object({
        initiativeId: z.string().min(1),
        mergeRequiresApproval: z.boolean().optional(),
        executionMode: z.enum(['yolo', 'review_per_phase']).optional(),
      }))
      .mutation(async ({ ctx, input }) => {
        const repo = requireInitiativeRepository(ctx);
        const { initiativeId, ...data } = input;

        const existing = await repo.findById(initiativeId);
        if (!existing) {
          throw new TRPCError({
            code: 'NOT_FOUND',
            message: `Initiative '${initiativeId}' not found`,
          });
        }

        return repo.update(initiativeId, data);
      }),
  };
}
