/**
 * ConversationGroupBuilder - Alternative grouping strategy for conversation flow.
 *
 * Groups one user message with all AI responses until the next user message.
 * This is a cleaner alternative to buildChunks() that:
 * - Uses simpler time-based grouping
 * - Separates Task executions from regular tool executions
 * - Links subagents more explicitly via TaskExecution
 */

import {
  type ConversationGroup,
  isParsedUserChunkMessage,
  type ParsedMessage,
  type Process,
  type TaskExecution,
  type ToolCall,
  type ToolExecution,
} from '@main/types';
import { calculateMetrics } from '@main/utils/jsonl';

/**
 * Build conversation groups using simplified grouping strategy.
 * Groups one user message with all AI responses until the next user message.
 */
export function buildGroups(messages: ParsedMessage[], subagents: Process[]): ConversationGroup[] {
  const groups: ConversationGroup[] = [];

  // Step 1: Filter to main thread only (not sidechain)
  const mainMessages = messages.filter((m) => !m.isSidechain);

  // Step 2: Find all REAL user messages (these start groups)
  // Use isParsedUserChunkMessage to filter out noise
  const userMessages = mainMessages.filter(isParsedUserChunkMessage);

  // Step 3: For each user message, collect all AI responses until next user message
  for (let i = 0; i < userMessages.length; i++) {
    const userMsg = userMessages[i];
    const nextUserMsg = userMessages[i + 1];

    // Collect all messages between this user message and the next
    const aiResponses = collectAIResponses(mainMessages, userMsg, nextUserMsg);

    // Separate Task tool results from regular tool executions
    const { taskExecutions, regularToolExecutions } = separateTaskExecutions(
      aiResponses,
      subagents
    );

    // Link subagents to this group via deterministic parentTaskId matching
    const groupSubagents = linkSubagentsToGroup(aiResponses, subagents);

    // Calculate metrics
    const { startTime, endTime, durationMs } = calculateGroupTiming(userMsg, aiResponses);
    const metrics = calculateMetrics([userMsg, ...aiResponses]);

    groups.push({
      id: `group-${i + 1}`,
      type: 'user-ai-exchange',
      userMessage: userMsg,
      aiResponses,
      processes: groupSubagents,
      toolExecutions: regularToolExecutions,
      taskExecutions,
      startTime,
      endTime,
      durationMs,
      metrics,
    });
  }

  return groups;
}

/**
 * Collect AI responses between a user message and the next user message.
 * Simpler than collectResponses - just uses timestamp boundaries.
 */
function collectAIResponses(
  messages: ParsedMessage[],
  userMsg: ParsedMessage,
  nextUserMsg: ParsedMessage | undefined
): ParsedMessage[] {
  const responses: ParsedMessage[] = [];
  const startTime = userMsg.timestamp;
  const endTime = nextUserMsg?.timestamp;

  for (const msg of messages) {
    // Skip if before this user message
    if (msg.timestamp <= startTime) continue;

    // Skip if at or after next user message
    if (endTime && msg.timestamp >= endTime) continue;

    // Include ALL non-user messages (assistant + internal user messages)
    if (msg.type === 'assistant' || (msg.type === 'user' && msg.isMeta === true)) {
      responses.push(msg);
    }
  }

  return responses;
}

/**
 * Separate Task executions from regular tool executions.
 * Task tools spawn subagents, so we track them separately to avoid duplication.
 */
function separateTaskExecutions(
  responses: ParsedMessage[],
  allSubagents: Process[]
): { taskExecutions: TaskExecution[]; regularToolExecutions: ToolExecution[] } {
  const taskExecutions: TaskExecution[] = [];
  const regularToolExecutions: ToolExecution[] = [];

  // Build map of tool_use_id -> subagent for Task calls
  const taskIdToSubagent = new Map<string, Process>();
  for (const subagent of allSubagents) {
    if (subagent.parentTaskId) {
      taskIdToSubagent.set(subagent.parentTaskId, subagent);
    }
  }

  // Collect all tool calls
  const toolCalls = new Map<string, { call: ToolCall; timestamp: Date }>();
  for (const msg of responses) {
    if (msg.type === 'assistant') {
      for (const toolCall of msg.toolCalls) {
        toolCalls.set(toolCall.id, { call: toolCall, timestamp: msg.timestamp });
      }
    }
  }

  // Match with results
  for (const msg of responses) {
    if (msg.type === 'user' && msg.isMeta === true && msg.sourceToolUseID) {
      const callInfo = toolCalls.get(msg.sourceToolUseID);
      if (!callInfo) continue;

      // Check if this is a Task call with a subagent
      const subagent = taskIdToSubagent.get(msg.sourceToolUseID);
      if (callInfo.call.name === 'Task' && subagent) {
        // This is a Task execution
        taskExecutions.push({
          taskCall: callInfo.call,
          taskCallTimestamp: callInfo.timestamp,
          subagent,
          toolResult: msg,
          resultTimestamp: msg.timestamp,
          durationMs: msg.timestamp.getTime() - callInfo.timestamp.getTime(),
        });
      } else {
        // Regular tool execution
        const result = msg.toolResults[0];
        if (result) {
          regularToolExecutions.push({
            toolCall: callInfo.call,
            result,
            startTime: callInfo.timestamp,
            endTime: msg.timestamp,
            durationMs: msg.timestamp.getTime() - callInfo.timestamp.getTime(),
          });
        }
      }
    }
  }

  return { taskExecutions, regularToolExecutions };
}

/**
 * Link subagents to a conversation group via deterministic parentTaskId matching.
 * Only includes subagents whose parentTaskId matches a Task tool_use ID in the AI responses.
 */
function linkSubagentsToGroup(aiResponses: ParsedMessage[], allSubagents: Process[]): Process[] {
  const groupTaskIds = new Set<string>();
  for (const msg of aiResponses) {
    for (const toolCall of msg.toolCalls) {
      if (toolCall.isTask) {
        groupTaskIds.add(toolCall.id);
      }
    }
  }
  return allSubagents
    .filter((s) => s.parentTaskId && groupTaskIds.has(s.parentTaskId))
    .sort((a, b) => a.startTime.getTime() - b.startTime.getTime());
}

/**
 * Calculate group timing from user message and AI responses.
 */
function calculateGroupTiming(
  userMsg: ParsedMessage,
  aiResponses: ParsedMessage[]
): { startTime: Date; endTime: Date; durationMs: number } {
  const startTime = userMsg.timestamp;

  let endTime = startTime;
  for (const resp of aiResponses) {
    if (resp.timestamp > endTime) {
      endTime = resp.timestamp;
    }
  }

  return {
    startTime,
    endTime,
    durationMs: endTime.getTime() - startTime.getTime(),
  };
}
