import { useState, memo, useMemo } from "react";
import type { JSX } from "react";
import type { CapturedLog } from "../../proxy/schemas";
import {
  ConversationHeader,
  getGroupApiFormat,
  hasMixedApiFormat,
  type ConversationGroupData,
} from "./ConversationHeader";
import { TurnGroup } from "./TurnGroup";
import type { CacheTrendEntry } from "./cacheTrend";
import { buildTurnGroups, shouldRenderConversationContent } from "./viewerState";

export type ConversationGroupProps = {
  group: ConversationGroupData;
  viewMode?: "simple" | "full";
  /** Live strip-Claude-Code-billing-header flag from the viewer container. */
  strip: boolean;
  /** Slow-response threshold in seconds. `0` disables the warning indicator. */
  slowResponseThresholdSeconds: number;
  /**
   * Pre-computed per-log cache token trend map (keyed by `log.id`) shared
   * across the whole viewer. Each `LogEntry` looks up its own entry.
   */
  cacheTrends?: Map<number, CacheTrendEntry>;
  /** Callback to open CompareDrawer with a log and its immediate predecessor. */
  onCompareWithPrevious: (log: CapturedLog) => void;
  comparisonPredecessors: Map<number, CapturedLog>;
  /** When true, skip the group header and render content directly. */
  standalone?: boolean;
  /** Clear all logs that belong to this group. */
  onClearGroup: (ids: number[]) => void;
};

function computeStats(logs: CapturedLog[]): {
  totalInputTokens: number;
  totalOutputTokens: number;
} {
  let totalInput = 0;
  let totalOutput = 0;
  for (const log of logs) {
    if (log.inputTokens !== null) totalInput += log.inputTokens;
    if (log.outputTokens !== null) totalOutput += log.outputTokens;
  }
  return { totalInputTokens: totalInput, totalOutputTokens: totalOutput };
}

export const ConversationGroup = memo(function ({
  group,
  viewMode = "simple",
  strip,
  slowResponseThresholdSeconds,
  cacheTrends,
  onCompareWithPrevious,
  comparisonPredecessors,
  onClearGroup,
  standalone = false,
}: ConversationGroupProps): JSX.Element {
  const [expanded, setExpanded] = useState(false);
  const stats = useMemo(() => computeStats(group.logs), [group.logs]);
  const startTime = group.logs[0]?.timestamp ?? new Date().toISOString();
  const endTime = group.logs[group.logs.length - 1]?.timestamp ?? new Date().toISOString();
  const mixed = hasMixedApiFormat(group.logs);
  const isLoading = group.logs.some((log) => log.responseStatus === null);

  // Pre-compute stop reasons for each log — used by turnIndices
  const turnGroups = useMemo(() => buildTurnGroups(group.logs), [group.logs]);
  return (
    <div className="mb-2">
      {!standalone && (
        <ConversationHeader
          conversationId={group.conversationId}
          startTime={startTime}
          endTime={endTime}
          totalCalls={group.logs.length}
          totalInputTokens={stats.totalInputTokens}
          totalOutputTokens={stats.totalOutputTokens}
          apiFormat={getGroupApiFormat(group.logs)}
          expanded={expanded}
          onToggle={() => setExpanded(!expanded)}
          hideApiFormat={mixed}
          isLoading={isLoading}
          userAgent={group.logs[0]?.userAgent ?? null}
          onClear={() => onClearGroup(group.logs.map((l) => l.id))}
        />
      )}

      {shouldRenderConversationContent(standalone, expanded) && (
        <div>
          {turnGroups.map((tg) => (
            <TurnGroup
              key={tg.turnIndex}
              entries={tg.entries}
              viewMode={viewMode}
              strip={strip}
              slowResponseThresholdSeconds={slowResponseThresholdSeconds}
              cacheTrends={cacheTrends}
              onCompareWithPrevious={onCompareWithPrevious}
              comparisonPredecessors={comparisonPredecessors}
              turnIndex={tg.turnIndex}
            />
          ))}
        </div>
      )}
    </div>
  );
});
