import { useMemo } from 'react';
import type { DiagramSection } from './types';
import type { NodeConfig } from './types';
import type { NodeExecutionState, IterationInfo } from '../ExecutionDiagram/types';
import type { DiagramNode as DiagramNodeType } from '../../api/queries/diagrams';
import { DiagramEdge } from './DiagramEdge';
import { DiagramNode } from './DiagramNode';
import { CompoundNode } from './CompoundNode';
import { isCompoundType } from './node-colors';

const CONTENT_PADDING_Y = 20;
const CONTENT_PADDING_LEFT = 12;

interface ErrorSectionProps {
  section: DiagramSection;
  totalWidth: number;
  selectedNodeId?: string;
  hoveredNodeId: string | null;
  nodeConfigs?: Map<string, NodeConfig>;
  /** Execution overlay for edge traversal coloring */
  executionOverlay?: Map<string, NodeExecutionState>;
  /** Whether an execution overlay is active (enables dimming of skipped nodes) */
  overlayActive?: boolean;
  /** Per-compound iteration state */
  iterationState?: Map<string, IterationInfo>;
  /** Called when user changes iteration on a compound stepper */
  onIterationChange?: (compoundNodeId: string, iterationIndex: number) => void;
  onNodeClick: (nodeId: string) => void;
  onNodeDoubleClick?: (nodeId: string) => void;
  onNodeEnter: (nodeId: string) => void;
  onNodeLeave: () => void;
}

const VARIANT_COLORS: Record<string, string> = {
  error: 'var(--error)',
  completion: 'var(--running)',
};

export function ErrorSection({
  section, totalWidth, selectedNodeId, hoveredNodeId, nodeConfigs, executionOverlay,
  overlayActive, iterationState, onIterationChange,
  onNodeClick, onNodeDoubleClick, onNodeEnter, onNodeLeave,
}: ErrorSectionProps) {
  const color = VARIANT_COLORS[section.variant ?? 'error'] ?? VARIANT_COLORS.error;

  // Check if any node in this section was executed (has overlay entry)
  const wasTriggered = useMemo(() => {
    if (!executionOverlay || executionOverlay.size === 0) return false;
    function checkNodes(nodes: DiagramNodeType[]): boolean {
      for (const n of nodes) {
        if (n.id && executionOverlay!.has(n.id)) return true;
        if (n.children && checkNodes(n.children)) return true;
      }
      return false;
    }
    return checkNodes(section.nodes);
  }, [executionOverlay, section.nodes]);

  const boxHeight = useMemo(() => {
    let maxY = 0;
    for (const n of section.nodes) {
      const bottom = (n.y ?? 0) + (n.height ?? 40);
      if (bottom > maxY) maxY = bottom;
      if (n.children) {
        for (const c of n.children) {
          const cb = (c.y ?? 0) + (c.height ?? 40);
          if (cb > maxY) maxY = cb;
        }
      }
    }
    // Content height + top padding + bottom padding (to vertically center)
    return maxY + CONTENT_PADDING_Y * 2;
  }, [section.nodes]);

  return (
    <g transform={`translate(0, ${section.offsetY})`}>
      {/* Section label */}
      <text x={8} y={-6} fill={color} fontSize={11} fontWeight={600}>
        {section.label}
      </text>

      {/* Divider line — solid when triggered */}
      <line
        x1={0}
        y1={0}
        x2={totalWidth}
        y2={0}
        stroke={color}
        strokeWidth={wasTriggered ? 1.5 : 1}
        strokeDasharray={wasTriggered ? undefined : '6 3'}
        opacity={wasTriggered ? 0.8 : 0.5}
      />

      {/* Background — stronger when this handler was triggered during execution */}
      <rect
        x={0}
        y={4}
        width={totalWidth}
        height={boxHeight}
        fill={color}
        opacity={wasTriggered ? 0.08 : 0.03}
        rx={4}
      />
      {wasTriggered && (
        <rect
          x={0}
          y={4}
          width={totalWidth}
          height={boxHeight}
          fill="none"
          stroke={color}
          strokeWidth={1.5}
          rx={4}
          opacity={0.5}
        />
      )}

      {/* Content group with margin from top-left */}
      <g transform={`translate(${CONTENT_PADDING_LEFT}, ${CONTENT_PADDING_Y})`}>
        {/* Edges */}
        <g className="edges">
          {section.edges.map((edge, i) => {
            const isTraversed = executionOverlay
              ? (executionOverlay.has(edge.sourceId) && executionOverlay.has(edge.targetId))
              : undefined;
            return (
              <DiagramEdge key={`${edge.sourceId}-${edge.targetId}-${i}`} edge={edge} traversed={isTraversed} />
            );
          })}
        </g>

        {/* Nodes */}
        <g className="nodes">
          {section.nodes.map(node => {
            if (isCompoundType(node.type) && node.children && node.children.length > 0) {
              return (
                <CompoundNode
                  key={node.id}
                  node={node}
                  edges={section.edges}
                  selectedNodeId={selectedNodeId}
                  hoveredNodeId={hoveredNodeId}
                  nodeConfigs={nodeConfigs}
                  executionOverlay={executionOverlay}
                  overlayActive={overlayActive}
                  iterationState={iterationState}
                  onIterationChange={onIterationChange}
                  onNodeClick={onNodeClick}
                  onNodeDoubleClick={onNodeDoubleClick}
                  onNodeEnter={onNodeEnter}
                  onNodeLeave={onNodeLeave}
                />
              );
            }
            return (
              <DiagramNode
                key={node.id}
                node={node}
                isHovered={hoveredNodeId === node.id}
                isSelected={selectedNodeId === node.id}
                config={node.id ? nodeConfigs?.get(node.id) : undefined}
                executionState={executionOverlay?.get(node.id ?? '')}
                overlayActive={overlayActive}
                onClick={() => node.id && onNodeClick(node.id)}
                onDoubleClick={() => node.id && onNodeDoubleClick?.(node.id)}
                onMouseEnter={() => node.id && onNodeEnter(node.id)}
                onMouseLeave={onNodeLeave}
              />
            );
          })}
        </g>
      </g>
    </g>
  );
}
