import React, { useCallback, useState } from 'react';

import {
  CODE_BG,
  CODE_BORDER,
  COLOR_TEXT_MUTED,
  TOOL_CALL_BG,
  TOOL_CALL_BORDER,
  TOOL_CALL_TEXT,
} from '@renderer/constants/cssVariables';
import { formatTokensCompact } from '@renderer/utils/formatters';
import { format } from 'date-fns';
import { ChevronRight, Layers, MailOpen } from 'lucide-react';

import { BaseItem } from './items/BaseItem';
import { LinkedToolItem } from './items/LinkedToolItem';
import { SlashItem } from './items/SlashItem';
import { SubagentItem } from './items/SubagentItem';
import { TeammateMessageItem } from './items/TeammateMessageItem';
import { TextItem } from './items/TextItem';
import { ThinkingItem } from './items/ThinkingItem';
import { MarkdownViewer } from './viewers/MarkdownViewer';

import type { AIGroupDisplayItem } from '@renderer/types/groups';
import type { TriggerColor } from '@shared/constants/triggerColors';

interface DisplayItemListProps {
  items: AIGroupDisplayItem[];
  onItemClick: (itemId: string) => void;
  expandedItemIds: Set<string>;
  aiGroupId: string;
  /** Render order for display items (visual only). */
  order?: 'chronological' | 'newest-first';
  /** Optional local search query override for markdown highlighting */
  searchQueryOverride?: string;
  /** Tool use ID to highlight for error deep linking */
  highlightToolUseId?: string;
  /** Custom highlight color from trigger */
  highlightColor?: TriggerColor;
  /** Map of tool use ID to trigger color for notification dots */
  notificationColorMap?: Map<string, TriggerColor>;
  /** Optional callback to register tool element refs for scroll targeting */
  registerToolRef?: (toolId: string, el: HTMLDivElement | null) => void;
}

/**
 * Truncates text to a maximum length and adds ellipsis if needed.
 */
function truncateText(text: string, maxLength: number): string {
  if (text.length <= maxLength) {
    return text;
  }
  return text.substring(0, maxLength) + '...';
}

/**
 * Renders a flat list of AIGroupDisplayItem[] into the appropriate components.
 *
 * This component maps each display item to its corresponding component based on type:
 * - thinking -> ThinkingItem
 * - output -> TextItem
 * - tool -> LinkedToolItem
 * - subagent -> SubagentItem
 * - slash -> SlashItem
 *
 * The list is completely flat with no nested toggles or hierarchies.
 */
export const DisplayItemList = ({
  items,
  onItemClick,
  expandedItemIds,
  aiGroupId,
  order = 'chronological',
  searchQueryOverride,
  highlightToolUseId,
  highlightColor,
  notificationColorMap,
  registerToolRef,
}: Readonly<DisplayItemListProps>): React.JSX.Element => {
  // Reply-link highlight: when hovering a reply badge, dim everything except the linked pair
  const [replyLinkToolId, setReplyLinkToolId] = useState<string | null>(null);

  const handleReplyHover = useCallback((toolId: string | null) => {
    setReplyLinkToolId(toolId);
  }, []);

  /** Check if an item is part of the currently highlighted reply link */
  const isItemInReplyLink = (item: AIGroupDisplayItem): boolean => {
    if (!replyLinkToolId) return false;
    if (item.type === 'tool' && item.tool.id === replyLinkToolId) return true;
    if (item.type === 'teammate_message' && item.teammateMessage.replyToToolId === replyLinkToolId)
      return true;
    return false;
  };

  if (!items || items.length === 0) {
    return (
      <div className="px-3 py-2 text-sm italic text-claude-dark-text-secondary">
        No items to display
      </div>
    );
  }

  return (
    <div
      className={
        order === 'newest-first' ? 'flex min-w-0 flex-col-reverse gap-2' : 'min-w-0 space-y-2'
      }
    >
      {items.map((item, index) => {
        let itemKey = '';
        let element: React.ReactNode = null;

        switch (item.type) {
          case 'thinking': {
            itemKey = `thinking-${index}`;
            const thinkingStep = {
              id: itemKey,
              type: 'thinking' as const,
              startTime: item.timestamp,
              endTime: item.timestamp,
              durationMs: 0,
              content: { thinkingText: item.content, tokenCount: item.tokenCount },
              tokens: { input: 0, output: item.tokenCount ?? 0 },
              context: 'main' as const,
            };
            element = (
              <ThinkingItem
                step={thinkingStep}
                preview={truncateText(item.content, 150)}
                onClick={() => onItemClick(itemKey)}
                isExpanded={expandedItemIds.has(itemKey)}
                timestamp={item.timestamp}
                markdownItemId={searchQueryOverride ? `${aiGroupId}:${itemKey}` : undefined}
                searchQueryOverride={searchQueryOverride}
              />
            );
            break;
          }

          case 'output': {
            itemKey = `output-${index}`;
            const textStep = {
              id: itemKey,
              type: 'output' as const,
              startTime: item.timestamp,
              endTime: item.timestamp,
              durationMs: 0,
              content: { outputText: item.content, tokenCount: item.tokenCount },
              tokens: { input: 0, output: item.tokenCount ?? 0 },
              context: 'main' as const,
            };
            element = (
              <TextItem
                step={textStep}
                preview={truncateText(item.content, 150)}
                onClick={() => onItemClick(itemKey)}
                isExpanded={expandedItemIds.has(itemKey)}
                timestamp={item.timestamp}
                markdownItemId={searchQueryOverride ? `${aiGroupId}:${itemKey}` : undefined}
                searchQueryOverride={searchQueryOverride}
              />
            );
            break;
          }

          case 'tool': {
            itemKey = `tool-${item.tool.id}-${index}`;
            element = (
              <LinkedToolItem
                linkedTool={item.tool}
                onClick={() => onItemClick(itemKey)}
                isExpanded={expandedItemIds.has(itemKey)}
                timestamp={item.tool.startTime}
                searchQueryOverride={searchQueryOverride}
                isHighlighted={highlightToolUseId === item.tool.id}
                highlightColor={highlightColor}
                notificationDotColor={notificationColorMap?.get(item.tool.id)}
                registerRef={
                  registerToolRef ? (el) => registerToolRef(item.tool.id, el) : undefined
                }
              />
            );
            break;
          }

          case 'subagent': {
            itemKey = `subagent-${item.subagent.id}-${index}`;
            const subagentStep = {
              id: itemKey,
              type: 'subagent' as const,
              startTime: item.subagent.startTime,
              endTime: item.subagent.endTime,
              durationMs: item.subagent.durationMs,
              content: {
                subagentId: item.subagent.id,
                subagentDescription: item.subagent.description,
              },
              isParallel: item.subagent.isParallel,
              context: 'main' as const,
            };
            element = (
              <SubagentItem
                step={subagentStep}
                subagent={item.subagent}
                onClick={() => onItemClick(itemKey)}
                isExpanded={expandedItemIds.has(itemKey)}
                aiGroupId={aiGroupId}
                highlightToolUseId={highlightToolUseId}
                highlightColor={highlightColor}
                notificationColorMap={notificationColorMap}
                registerToolRef={registerToolRef}
              />
            );
            break;
          }

          case 'slash': {
            itemKey = `slash-${item.slash.name}-${index}`;
            element = (
              <SlashItem
                slash={item.slash}
                onClick={() => onItemClick(itemKey)}
                isExpanded={expandedItemIds.has(itemKey)}
                timestamp={item.slash.timestamp}
              />
            );
            break;
          }

          case 'teammate_message': {
            itemKey = `teammate-${item.teammateMessage.id}-${index}`;
            element = (
              <TeammateMessageItem
                teammateMessage={item.teammateMessage}
                onClick={() => onItemClick(itemKey)}
                isExpanded={expandedItemIds.has(itemKey)}
                onReplyHover={handleReplyHover}
              />
            );
            break;
          }

          case 'subagent_input': {
            itemKey = `input-${index}`;
            const inputContent = item.content;
            const inputTokenCount = item.tokenCount;
            element = (
              <BaseItem
                icon={<MailOpen className="size-4" />}
                label="Input"
                summary={truncateText(inputContent, 80)}
                tokenCount={inputTokenCount}
                timestamp={item.timestamp}
                onClick={() => onItemClick(itemKey)}
                isExpanded={expandedItemIds.has(itemKey)}
              >
                <MarkdownViewer
                  content={inputContent}
                  copyable
                  itemId={searchQueryOverride ? `${aiGroupId}:${itemKey}` : undefined}
                  searchQueryOverride={searchQueryOverride}
                />
              </BaseItem>
            );
            break;
          }

          case 'compact_boundary': {
            itemKey = `compact-${index}`;
            const compactContent = item.content;
            const compactExpanded = expandedItemIds.has(itemKey);
            element = (
              <div>
                <button
                  onClick={() => onItemClick(itemKey)}
                  className="group flex w-full cursor-pointer items-center gap-2 rounded-lg px-3 py-2 transition-all duration-200"
                  style={{
                    backgroundColor: TOOL_CALL_BG,
                    border: `1px solid ${TOOL_CALL_BORDER}`,
                  }}
                  aria-expanded={compactExpanded}
                >
                  <div
                    className="flex shrink-0 items-center gap-1.5"
                    style={{ color: TOOL_CALL_TEXT }}
                  >
                    <ChevronRight
                      size={14}
                      className={`transition-transform duration-200 ${compactExpanded ? 'rotate-90' : ''}`}
                    />
                    <Layers size={14} />
                  </div>
                  <span className="shrink-0 text-xs font-medium" style={{ color: TOOL_CALL_TEXT }}>
                    Compacted
                  </span>
                  {item.tokenDelta && (
                    <span
                      className="min-w-0 truncate text-[11px] tabular-nums"
                      style={{ color: COLOR_TEXT_MUTED }}
                    >
                      {formatTokensCompact(item.tokenDelta.preCompactionTokens)} →{' '}
                      {formatTokensCompact(item.tokenDelta.postCompactionTokens)}
                      <span style={{ color: '#4ade80' }}>
                        {' '}
                        ({formatTokensCompact(Math.abs(item.tokenDelta.delta))} freed)
                      </span>
                    </span>
                  )}
                  <span
                    className="shrink-0 rounded px-1.5 py-0.5 text-[10px]"
                    style={{
                      backgroundColor: 'rgba(99, 102, 241, 0.15)',
                      color: '#818cf8',
                    }}
                  >
                    Phase {item.phaseNumber}
                  </span>
                  <span
                    className="ml-auto shrink-0 text-[11px]"
                    style={{ color: COLOR_TEXT_MUTED }}
                  >
                    {format(new Date(item.timestamp), 'h:mm:ss a')}
                  </span>
                </button>
                {compactExpanded && compactContent && (
                  <div
                    className="mt-1 overflow-hidden rounded-lg"
                    style={{
                      backgroundColor: CODE_BG,
                      border: `1px solid ${CODE_BORDER}`,
                    }}
                  >
                    <div
                      className="max-h-64 overflow-y-auto border-l-2 px-3 py-2"
                      style={{ borderColor: 'var(--chat-ai-border)' }}
                    >
                      <MarkdownViewer content={compactContent} copyable />
                    </div>
                  </div>
                )}
              </div>
            );
            break;
          }

          default:
            return null;
        }

        // Apply reply-link spotlight: dim items not in the highlighted pair
        const isDimmed = replyLinkToolId !== null && !isItemInReplyLink(item);
        return (
          <div
            key={itemKey}
            style={
              replyLinkToolId !== null
                ? { opacity: isDimmed ? 0.2 : 1, transition: 'opacity 150ms ease' }
                : undefined
            }
          >
            {element}
          </div>
        );
      })}
    </div>
  );
};
