// ABOUTME: Groups multiple tool calls into a collapsible summary with plain language description.
// ABOUTME: Reduces clutter by showing "searched 5 files, ran 3 commands" instead of 20+ individual cards.

import type { Component } from "solid-js";
import { createEffect, For, Show } from "solid-js";
import type { ToolCallEvent } from "@/services/providers";
import {
  getToolCallGroupState,
  markToolCallTailed,
  setToolCallGroupExpanded,
  setToolCallGroupTailing,
  wasToolCallTailed,
} from "@/stores/tool-call-groups.store";
import { ToolCallCard } from "./ToolCallCard";

interface ToolCallGroupProps {
  toolCalls: ToolCallEvent[];
  /**
   * Stable identity for this group across regroup remounts (#1748). Provided
   * by ChatContent and derived from the first tool call's id.
   */
  groupId: string;
  isComplete?: boolean;
}

function isRunning(tool: ToolCallEvent): boolean {
  const status = tool.status.toLowerCase();
  return status.includes("running") || status.includes("progress");
}

/** Categorize tool calls into plain language summary */
function categorizeToolCalls(toolCalls: ToolCallEvent[]) {
  const categories = {
    filesSearched: 0,
    filesEdited: 0,
    filesWritten: 0,
    commandsRun: 0,
    tasksCreated: 0,
    other: 0,
  };

  for (const tool of toolCalls) {
    const kind = tool.kind.toLowerCase();
    const title = tool.title.toLowerCase();

    if (
      kind === "read" ||
      kind.includes("file") ||
      kind === "glob" ||
      kind === "grep"
    ) {
      categories.filesSearched++;
    } else if (kind === "edit") {
      categories.filesEdited++;
    } else if (kind === "write" || kind === "notebookedit") {
      categories.filesWritten++;
    } else if (
      kind.includes("bash") ||
      kind.includes("command") ||
      kind === "execute"
    ) {
      categories.commandsRun++;
    } else if (title.includes("todo") || kind === "todowrite") {
      categories.tasksCreated++;
    } else {
      categories.other++;
    }
  }

  return categories;
}

/** Build plain language summary from categories */
function buildSummary(
  categories: ReturnType<typeof categorizeToolCalls>,
): string {
  const parts: string[] = [];

  if (categories.filesSearched > 0) {
    parts.push(
      `searched ${categories.filesSearched} file${categories.filesSearched > 1 ? "s" : ""}`,
    );
  }
  if (categories.filesEdited > 0) {
    parts.push(
      `edited ${categories.filesEdited} file${categories.filesEdited > 1 ? "s" : ""}`,
    );
  }
  if (categories.filesWritten > 0) {
    parts.push(
      `created ${categories.filesWritten} file${categories.filesWritten > 1 ? "s" : ""}`,
    );
  }
  if (categories.commandsRun > 0) {
    parts.push(
      `ran ${categories.commandsRun} command${categories.commandsRun > 1 ? "s" : ""}`,
    );
  }
  if (categories.tasksCreated > 0) {
    parts.push("updated task list");
  }
  if (categories.other > 0 && parts.length === 0) {
    parts.push(
      `${categories.other} operation${categories.other > 1 ? "s" : ""}`,
    );
  }

  if (parts.length === 0) return "No operations";
  if (parts.length === 1) return parts[0];
  if (parts.length === 2) return `${parts[0]} and ${parts[1]}`;

  // Join with commas and "and" for the last item
  const lastPart = parts.pop();
  return `${parts.join(", ")}, and ${lastPart}`;
}

export const ToolCallGroup: Component<ToolCallGroupProps> = (props) => {
  // State lives in the store, keyed by groupId, so it survives regroup remounts.
  const groupState = () => getToolCallGroupState(props.groupId);
  const isExpanded = () => groupState().expanded;
  const isTailing = () => groupState().tailing;
  const toggleExpanded = () =>
    setToolCallGroupExpanded(props.groupId, !isExpanded());
  const toggleTailing = (e: MouseEvent) => {
    e.stopPropagation(); // don't also toggle the chevron
    setToolCallGroupTailing(props.groupId, !isTailing());
  };

  const categories = () => categorizeToolCalls(props.toolCalls);
  const summary = () => buildSummary(categories());
  const hasRunning = () => props.toolCalls.some(isRunning);

  // Sticky-expand (#2100): record each tool call that Tail force-expands
  // while it is running, so the card stays open through completion instead
  // of snapping shut the instant the result lands.
  createEffect(() => {
    if (!isTailing()) return;
    for (const tc of props.toolCalls) {
      if (isRunning(tc)) {
        markToolCallTailed(props.groupId, tc.toolCallId);
      }
    }
  });

  const shouldForceOpen = (tc: ToolCallEvent): boolean => {
    if (!isTailing()) return false;
    return isRunning(tc) || wasToolCallTailed(props.groupId, tc.toolCallId);
  };

  return (
    <div class="my-2 mx-5 bg-surface-0 border border-surface-3 rounded-lg overflow-hidden">
      {/* Collapsible Header */}
      <button
        type="button"
        class="w-full flex items-center gap-3 px-3 py-2.5 text-left hover:bg-surface-2 transition-colors"
        onClick={toggleExpanded}
      >
        {/* Status Icon */}
        <Show
          when={hasRunning()}
          fallback={
            <svg
              class="w-4 h-4 shrink-0 text-green-500"
              fill="currentColor"
              viewBox="0 0 20 20"
              role="img"
              aria-label="Complete"
            >
              <path
                fill-rule="evenodd"
                d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
                clip-rule="evenodd"
              />
            </svg>
          }
        >
          <svg
            class="w-4 h-4 shrink-0 text-yellow-500 animate-spin"
            fill="none"
            viewBox="0 0 24 24"
            role="img"
            aria-label="Working"
          >
            <circle
              class="opacity-25"
              cx="12"
              cy="12"
              r="10"
              stroke="currentColor"
              stroke-width="4"
            />
            <path
              class="opacity-75"
              fill="currentColor"
              d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
            />
          </svg>
        </Show>

        {/* Summary Text */}
        <span class="flex-1 text-sm text-foreground">
          <Show when={hasRunning()} fallback={`Done (${summary()})`}>
            Working on your request... ({summary()})
          </Show>
        </span>

        {/* Tool Count Badge */}
        <span class="shrink-0 px-2 py-0.5 rounded text-xs bg-surface-3 text-muted-foreground">
          {props.toolCalls.length} tool{props.toolCalls.length > 1 ? "s" : ""}
        </span>

        {/* Tail Toggle — only meaningful while a tool is running */}
        <Show when={hasRunning()}>
          <button
            type="button"
            onClick={toggleTailing}
            aria-pressed={isTailing() ? "true" : "false"}
            title={
              isTailing()
                ? "Stop tailing running tool output"
                : "Tail running tool output"
            }
            class={`shrink-0 flex items-center gap-1 px-2 py-0.5 rounded text-xs border transition-colors ${
              isTailing()
                ? "bg-primary/15 border-primary/40 text-primary"
                : "bg-surface-2 border-surface-3 text-muted-foreground hover:text-foreground hover:border-primary/40"
            }`}
          >
            <svg
              class="w-3 h-3"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
              role="img"
              aria-label="Tail"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M19 14l-7 7m0 0l-7-7m7 7V3"
              />
            </svg>
            <span>Tail</span>
          </button>
        </Show>

        {/* Expand Icon */}
        <svg
          class={`w-4 h-4 shrink-0 text-muted-foreground transition-transform ${isExpanded() ? "rotate-180" : ""}`}
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
          role="img"
          aria-label={isExpanded() ? "Collapse" : "Expand"}
        >
          <path
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="2"
            d="M19 9l-7 7-7-7"
          />
        </svg>
      </button>

      {/* Expanded Tool Call Cards */}
      <Show when={isExpanded()}>
        <div class="border-t border-surface-2 px-3 py-2 space-y-2">
          <For each={props.toolCalls}>
            {(toolCall) => (
              <ToolCallCard
                toolCall={toolCall}
                forceExpanded={shouldForceOpen(toolCall)}
                tail={isTailing() && isRunning(toolCall)}
              />
            )}
          </For>
        </div>
      </Show>
    </div>
  );
};
