/**
 * Headquarters Router
 *
 * Provides the composite dashboard query for the Headquarters page,
 * aggregating all action items that require user intervention.
 */

import type { ProcedureBuilder } from '../trpc.js';
import type { Phase } from '../../db/schema.js';
import {
  requireAgentManager,
  requireInitiativeRepository,
  requirePhaseRepository,
} from './_helpers.js';

export function headquartersProcedures(publicProcedure: ProcedureBuilder) {
  return {
    getHeadquartersDashboard: publicProcedure.query(async ({ ctx }) => {
      const initiativeRepo = requireInitiativeRepository(ctx);
      const phaseRepo = requirePhaseRepository(ctx);
      const agentManager = requireAgentManager(ctx);

      const [allInitiatives, allAgents] = await Promise.all([
        initiativeRepo.findAll(),
        agentManager.list(),
      ]);

      // Relevant initiatives: status in ['active', 'pending_review']
      const relevantInitiatives = allInitiatives.filter(
        (i) => i.status === 'active' || i.status === 'pending_review',
      );

      // Non-dismissed agents only
      const activeAgents = allAgents.filter((a) => !a.userDismissedAt);

      // Fast lookup map: initiative id → initiative
      const initiativeMap = new Map(relevantInitiatives.map((i) => [i.id, i]));

      // Batch-fetch all phases for relevant initiatives in parallel
      const phasesByInitiative = new Map<string, Phase[]>();
      await Promise.all(
        relevantInitiatives.map(async (init) => {
          const phases = await phaseRepo.findByInitiativeId(init.id);
          phasesByInitiative.set(init.id, phases);
        }),
      );

      // -----------------------------------------------------------------------
      // Section 1: waitingForInput
      // -----------------------------------------------------------------------
      const waitingAgents = activeAgents.filter((a) => a.status === 'waiting_for_input');
      const pendingQuestionsResults = await Promise.all(
        waitingAgents.map((a) => agentManager.getPendingQuestions(a.id)),
      );

      const waitingForInput = waitingAgents
        .map((agent, i) => {
          const initiative = agent.initiativeId ? initiativeMap.get(agent.initiativeId) : undefined;
          return {
            agentId: agent.id,
            agentName: agent.name,
            initiativeId: agent.initiativeId,
            initiativeName: initiative?.name ?? null,
            questionText: pendingQuestionsResults[i]?.questions[0]?.question ?? '',
            waitingSince: agent.updatedAt.toISOString(),
          };
        })
        .sort((a, b) => a.waitingSince.localeCompare(b.waitingSince));

      // -----------------------------------------------------------------------
      // Section 2a: pendingReviewInitiatives
      // -----------------------------------------------------------------------
      const pendingReviewInitiatives = relevantInitiatives
        .filter((i) => i.status === 'pending_review')
        .map((i) => ({
          initiativeId: i.id,
          initiativeName: i.name,
          since: i.updatedAt.toISOString(),
        }))
        .sort((a, b) => a.since.localeCompare(b.since));

      // -----------------------------------------------------------------------
      // Section 2b: pendingReviewPhases
      // -----------------------------------------------------------------------
      const pendingReviewPhases: Array<{
        initiativeId: string;
        initiativeName: string;
        phaseId: string;
        phaseName: string;
        since: string;
      }> = [];

      for (const [initiativeId, phases] of phasesByInitiative) {
        const initiative = initiativeMap.get(initiativeId)!;
        for (const phase of phases) {
          if (phase.status === 'pending_review') {
            pendingReviewPhases.push({
              initiativeId,
              initiativeName: initiative.name,
              phaseId: phase.id,
              phaseName: phase.name,
              since: phase.updatedAt.toISOString(),
            });
          }
        }
      }
      pendingReviewPhases.sort((a, b) => a.since.localeCompare(b.since));

      // -----------------------------------------------------------------------
      // Section 3: planningInitiatives
      // -----------------------------------------------------------------------
      const planningInitiatives: Array<{
        initiativeId: string;
        initiativeName: string;
        pendingPhaseCount: number;
        since: string;
      }> = [];

      for (const initiative of relevantInitiatives) {
        if (initiative.status !== 'active') continue;
        const phases = phasesByInitiative.get(initiative.id) ?? [];
        if (phases.length === 0) continue;

        const allPending = phases.every((p) => p.status === 'pending');
        if (!allPending) continue;

        const hasActiveAgent = activeAgents.some(
          (a) =>
            a.initiativeId === initiative.id &&
            (a.status === 'running' || a.status === 'waiting_for_input'),
        );
        if (hasActiveAgent) continue;

        const sortedByCreatedAt = [...phases].sort(
          (a, b) => a.createdAt.getTime() - b.createdAt.getTime(),
        );

        planningInitiatives.push({
          initiativeId: initiative.id,
          initiativeName: initiative.name,
          pendingPhaseCount: phases.length,
          since: sortedByCreatedAt[0].createdAt.toISOString(),
        });
      }
      planningInitiatives.sort((a, b) => a.since.localeCompare(b.since));

      // -----------------------------------------------------------------------
      // Section 4: resolvingConflicts
      // -----------------------------------------------------------------------
      const resolvingConflicts: Array<{
        initiativeId: string;
        initiativeName: string;
        agentId: string;
        agentName: string;
        agentStatus: string;
        since: string;
      }> = [];

      for (const agent of activeAgents) {
        if (
          agent.name?.startsWith('conflict-') &&
          (agent.status === 'running' || agent.status === 'waiting_for_input') &&
          agent.initiativeId
        ) {
          const initiative = initiativeMap.get(agent.initiativeId);
          if (initiative) {
            resolvingConflicts.push({
              initiativeId: initiative.id,
              initiativeName: initiative.name,
              agentId: agent.id,
              agentName: agent.name,
              agentStatus: agent.status,
              since: agent.updatedAt.toISOString(),
            });
          }
        }
      }
      resolvingConflicts.sort((a, b) => a.since.localeCompare(b.since));

      // -----------------------------------------------------------------------
      // Section 5: blockedPhases
      // -----------------------------------------------------------------------
      const blockedPhases: Array<{
        initiativeId: string;
        initiativeName: string;
        phaseId: string;
        phaseName: string;
        lastMessage: string | null;
        since: string;
      }> = [];

      for (const initiative of relevantInitiatives) {
        if (initiative.status !== 'active') continue;
        const phases = phasesByInitiative.get(initiative.id) ?? [];

        for (const phase of phases) {
          if (phase.status !== 'blocked') continue;

          let lastMessage: string | null = null;
          try {
            if (ctx.taskRepository && ctx.messageRepository) {
              const taskRepo = ctx.taskRepository;
              const messageRepo = ctx.messageRepository;
              const tasks = await taskRepo.findByPhaseId(phase.id);
              const phaseAgentIds = allAgents
                .filter((a) => tasks.some((t) => t.id === a.taskId))
                .map((a) => a.id);

              if (phaseAgentIds.length > 0) {
                const messageLists = await Promise.all(
                  phaseAgentIds.map((id) => messageRepo.findBySender('agent', id)),
                );
                const allMessages = messageLists
                  .flat()
                  .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());

                if (allMessages.length > 0) {
                  lastMessage = allMessages[0].content.slice(0, 160);
                }
              }
            }
          } catch {
            // Non-critical: message retrieval failure does not crash the dashboard
          }

          blockedPhases.push({
            initiativeId: initiative.id,
            initiativeName: initiative.name,
            phaseId: phase.id,
            phaseName: phase.name,
            lastMessage,
            since: phase.updatedAt.toISOString(),
          });
        }
      }
      blockedPhases.sort((a, b) => a.since.localeCompare(b.since));

      return {
        waitingForInput,
        pendingReviewInitiatives,
        pendingReviewPhases,
        planningInitiatives,
        resolvingConflicts,
        blockedPhases,
      };
    }),
  };
}
