import { useState, useMemo } from 'react'
import { HelpCircle, Zap, CheckCircle, ChevronDown, ChevronRight, Copy, Check, Play, Users } from 'lucide-react'
import type { TreeStructure, NodeType } from '@/types'
import { cn } from '@/lib/utils'
import type { SharedLinksMap } from './TreePreviewPanel'

type FindNodeFn = (nodeId: string) => TreeStructure | null

/**
 * Recursively check if a node's subtree contains any solution nodes
 * Also follows next_node_id references using the findNode function
 * @param visited - Set to track visited nodes and prevent infinite loops
 */
function hasSolutionInSubtree(
  node: TreeStructure,
  findNode: FindNodeFn,
  visited: Set<string> = new Set()
): boolean {
  // Prevent infinite loops from circular references
  if (visited.has(node.id)) return false
  visited.add(node.id)

  // This node is a solution
  if (node.type === 'solution') {
    return true
  }

  // Check children array
  if (node.children && node.children.length > 0) {
    if (node.children.some(child => hasSolutionInSubtree(child, findNode, visited))) {
      return true
    }
  }

  // Check next_node_id reference (for action nodes)
  if (node.next_node_id) {
    const nextNode = findNode(node.next_node_id)
    if (nextNode && hasSolutionInSubtree(nextNode, findNode, visited)) {
      return true
    }
  }

  return false
}

interface TreePreviewNodeProps {
  node: TreeStructure
  selectedNodeId: string | null
  onSelect: (nodeId: string) => void
  depth: number
  /** Optional label showing which option led to this node */
  fromOption?: string
  /** Callback when hovering over a node reference */
  onHoverNodeId?: (nodeId: string | null) => void
  /** Currently hovered node ID */
  hoveredNodeId?: string | null
  /** Function to look up any node by ID (for following next_node_id references) */
  findNode: FindNodeFn
  /** Map of targetNodeId -> sources that link to it (for showing shared connections) */
  sharedLinksMap: SharedLinksMap
}

export function TreePreviewNode({
  node,
  selectedNodeId,
  onSelect,
  depth,
  fromOption,
  onHoverNodeId,
  hoveredNodeId,
  findNode,
  sharedLinksMap
}: TreePreviewNodeProps) {
  const [isCollapsed, setIsCollapsed] = useState(false)
  const [copiedId, setCopiedId] = useState(false)
  const isSelected = selectedNodeId === node.id
  const isHovered = hoveredNodeId === node.id
  const isRootNode = node.id === 'root'

  // Check if this node (or its children/next_node_id) leads to a solution
  const leadsTosolution = useMemo(() => {
    // Don't show indicator on solution nodes themselves
    if (node.type === 'solution') return false
    return hasSolutionInSubtree(node, findNode)
  }, [node, findNode])

  const nodeTypeColors: Record<NodeType, string> = {
    decision: 'border-blue-500/50 bg-blue-500/10',
    action: 'border-yellow-500/50 bg-yellow-500/10',
    solution: 'border-green-500/50 bg-green-500/10',
    answer: 'border-dashed border-border bg-muted/50'
  }

  const nodeTypeSelectedColors: Record<NodeType, string> = {
    decision: 'border-blue-500 bg-blue-500/20 ring-2 ring-blue-500/50 shadow-lg shadow-blue-500/20',
    action: 'border-yellow-500 bg-yellow-500/20 ring-2 ring-yellow-500/50 shadow-lg shadow-yellow-500/20',
    solution: 'border-green-500 bg-green-500/20 ring-2 ring-green-500/50 shadow-lg shadow-green-500/20',
    answer: 'border-border bg-muted/50'
  }

  const nodeTypeHoveredColors: Record<NodeType, string> = {
    decision: 'border-blue-400 bg-blue-500/15 ring-1 ring-blue-400/50',
    action: 'border-yellow-400 bg-yellow-500/15 ring-1 ring-yellow-400/50',
    solution: 'border-green-400 bg-green-500/15 ring-1 ring-green-400/50',
    answer: 'border-border bg-muted/50'
  }

  const nodeTypeIcons: Record<NodeType, React.ReactNode> = {
    decision: <HelpCircle className="h-4 w-4 text-blue-500" />,
    action: <Zap className="h-4 w-4 text-yellow-500" />,
    solution: <CheckCircle className="h-4 w-4 text-green-500" />,
    answer: <HelpCircle className="h-4 w-4 opacity-40" />
  }

  const getNodeLabel = () => {
    if (node.type === 'decision') return node.question || 'Untitled Question'
    return node.title || `Untitled ${node.type}`
  }

  const hasChildren = node.children && node.children.length > 0

  const handleCopyId = (e: React.MouseEvent) => {
    e.stopPropagation()
    navigator.clipboard.writeText(node.id)
    setCopiedId(true)
    setTimeout(() => setCopiedId(false), 2000)
  }

  const toggleCollapse = (e: React.MouseEvent) => {
    e.stopPropagation()
    setIsCollapsed(!isCollapsed)
  }

  // Find which option label leads to each child node
  const getOptionLabelForChild = (childId: string): string | undefined => {
    if (node.type === 'decision' && node.options) {
      const option = node.options.find(opt => opt.next_node_id === childId)
      return option?.label
    }
    return undefined
  }

  // Check if a specific option/next_node_id leads to a solution
  const nodeLeadsToSolution = (nextNodeId: string | undefined): boolean => {
    if (!nextNodeId) return false
    // First try to find in children
    const childNode = node.children?.find(child => child.id === nextNodeId)
    if (childNode) {
      return hasSolutionInSubtree(childNode, findNode)
    }
    // Otherwise look up using findNode (for shared/external node references)
    const targetNode = findNode(nextNodeId)
    if (!targetNode) return false
    return hasSolutionInSubtree(targetNode, findNode)
  }

  return (
    <div className="relative">
      {/* From option label */}
      {fromOption && (
        <div className="mb-1 text-xs font-medium text-muted-foreground">
          <span className="rounded bg-accent px-1.5 py-0.5">{fromOption}</span>
        </div>
      )}

      {/* Node card */}
      <div
        onClick={() => onSelect(node.id)}
        className={cn(
          'relative cursor-pointer rounded-lg border-2 p-3 transition-all',
          isRootNode
            ? isSelected
              ? 'border-blue-500 bg-blue-500/20 ring-2 ring-blue-500/50 shadow-lg shadow-blue-500/20'
              : isHovered
              ? 'border-blue-400 bg-blue-500/15 ring-1 ring-blue-400/50'
              : 'border-blue-500/50 bg-blue-500/10'
            : isSelected
            ? nodeTypeSelectedColors[node.type]
            : isHovered
            ? nodeTypeHoveredColors[node.type]
            : nodeTypeColors[node.type],
          'hover:shadow-md',
          isRootNode ? 'min-w-[260px] max-w-[360px]' : 'min-w-[220px] max-w-[320px]'
        )}
      >
        {/* Solution path indicator - shows when this branch leads to a solution */}
        {leadsTosolution && (
          <div
            className="absolute -top-1.5 -right-1.5 flex items-center justify-center rounded-full bg-green-500/90 p-0.5 shadow-sm"
            title="This branch leads to a solution"
          >
            <CheckCircle className="h-3 w-3 text-foreground" />
          </div>
        )}
        {/* Root node START header */}
        {isRootNode && (
          <div className="flex items-center gap-2 mb-2 pb-2 border-b border-blue-500/30">
            <div className="rounded-full bg-blue-500/30 p-1.5">
              <Play className="h-4 w-4 text-blue-500" />
            </div>
            <span className="text-xs font-bold uppercase tracking-wide text-blue-400">
              Starting Question
            </span>
          </div>
        )}

        <div className="flex items-start gap-2">
          {/* Collapse toggle for nodes with children */}
          {hasChildren ? (
            <button
              type="button"
              onClick={toggleCollapse}
              className="mt-0.5 rounded p-0.5 hover:bg-accent"
            >
              {isCollapsed ? (
                <ChevronRight className="h-4 w-4 text-muted-foreground" />
              ) : (
                <ChevronDown className="h-4 w-4 text-muted-foreground" />
              )}
            </button>
          ) : (
            <div className="w-5" /> // Spacer for alignment
          )}

          {!isRootNode && nodeTypeIcons[node.type]}
          {isRootNode && <HelpCircle className="h-4 w-4 text-blue-500" />}

          <div className="flex-1 min-w-0">
            <p className="text-sm font-medium text-foreground leading-tight">
              {getNodeLabel()}
            </p>

            {/* Node ID with copy button */}
            <div className="flex items-center gap-1 mt-1">
              <span
                className="text-xs text-muted-foreground cursor-help"
                title={`Full ID: ${node.id}`}
              >
                {node.id === 'root' ? 'root' : node.id.slice(0, 8) + '...'}
              </span>
              <button
                type="button"
                onClick={handleCopyId}
                className="rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-foreground"
                title="Copy full ID"
              >
                {copiedId ? (
                  <Check className="h-3 w-3 text-green-500" />
                ) : (
                  <Copy className="h-3 w-3" />
                )}
              </button>
            </div>
          </div>
        </div>

        {/* Show options for decision nodes */}
        {node.type === 'decision' && node.options && node.options.length > 0 && (
          <div className="mt-2 space-y-1 border-t border-border pt-2">
            <p className="text-[10px] uppercase tracking-wide text-muted-foreground">Options:</p>
            {node.options.map((opt, i) => {
              const leadsToSolution = nodeLeadsToSolution(opt.next_node_id)
              return (
                <div
                  key={opt.id}
                  className={cn(
                    'flex items-center gap-1 text-xs rounded px-1 py-0.5 -mx-1',
                    opt.next_node_id && 'hover:bg-accent cursor-pointer'
                  )}
                  onMouseEnter={() => opt.next_node_id && onHoverNodeId?.(opt.next_node_id)}
                  onMouseLeave={() => onHoverNodeId?.(null)}
                >
                  <span className="inline-flex h-4 w-4 items-center justify-center rounded bg-accent text-[10px] font-medium text-muted-foreground">
                    {i + 1}
                  </span>
                  <span className="truncate text-muted-foreground">{opt.label || 'Untitled'}</span>
                  <span className="ml-auto flex items-center gap-1">
                    {leadsToSolution && (
                      <span title="Leads to solution">
                        <CheckCircle className="h-3 w-3 text-green-500" />
                      </span>
                    )}
                    {opt.next_node_id ? (
                      <span className="text-blue-500">→</span>
                    ) : (
                      <span className="text-muted-foreground text-[10px]">(no link)</span>
                    )}
                  </span>
                </div>
              )
            })}
          </div>
        )}

        {/* Show next_node_id for action nodes */}
        {node.type === 'action' && node.next_node_id && (() => {
          const nextNode = findNode(node.next_node_id!)
          const nextNodeLeadsToSolution = nodeLeadsToSolution(node.next_node_id)
          const nextNodeLabel = nextNode
            ? (nextNode.type === 'decision' ? nextNode.question : nextNode.title) || 'Untitled'
            : node.next_node_id!.slice(0, 8) + '...'

          // Check if this target is shared by multiple sources
          const sourcesLinkingToTarget = sharedLinksMap.get(node.next_node_id!) || []
          const otherSources = sourcesLinkingToTarget.filter(s => s.id !== node.id)
          const isSharedTarget = otherSources.length > 0

          // Build tooltip for shared connection
          const sharedTooltip = isSharedTarget
            ? `Shared endpoint - also connected from: ${otherSources.map(s => s.label).join(', ')}`
            : undefined

          return (
            <div
              className="mt-2 text-xs border-t border-border pt-2 hover:bg-accent/50 cursor-pointer rounded px-1 -mx-1"
              onMouseEnter={() => onHoverNodeId?.(node.next_node_id!)}
              onMouseLeave={() => onHoverNodeId?.(null)}
            >
              <div className="flex items-center gap-1.5">
                <span className="text-muted-foreground">Next:</span>
                {isSharedTarget && (
                  <span title={sharedTooltip} className="flex items-center">
                    <Users className="h-3 w-3 text-purple-500" />
                  </span>
                )}
                <span className={cn(
                  'truncate',
                  nextNode?.type === 'solution' ? 'text-green-500 font-medium' : 'text-muted-foreground'
                )}>
                  {nextNodeLabel.slice(0, 30)}{nextNodeLabel.length > 30 ? '...' : ''}
                </span>
                <span className="ml-auto flex items-center gap-1">
                  {(nextNodeLeadsToSolution || nextNode?.type === 'solution') && (
                    <span title={nextNode?.type === 'solution' ? 'Solution' : 'Leads to solution'}>
                      <CheckCircle className="h-3 w-3 text-green-500" />
                    </span>
                  )}
                  <span className="text-yellow-500">→</span>
                </span>
              </div>
              {/* Show shared sources count */}
              {isSharedTarget && (
                <div className="mt-1 text-[10px] text-purple-500/80 pl-4">
                  Shared by {sourcesLinkingToTarget.length} nodes
                </div>
              )}
            </div>
          )
        })()}
      </div>

      {/* Children - show as branches */}
      {hasChildren && !isCollapsed && (
        <div className="relative mt-3 ml-6 pl-6 border-l-2 border-border">
          <div className="space-y-4">
            {node.children!.map((child) => {
              const optionLabel = getOptionLabelForChild(child.id)

              return (
                <div key={child.id} className="relative">
                  {/* Horizontal connector line */}
                  <div className="absolute -left-6 top-6 h-0.5 w-6 bg-border" />

                  <TreePreviewNode
                    node={child}
                    selectedNodeId={selectedNodeId}
                    onSelect={onSelect}
                    depth={depth + 1}
                    fromOption={optionLabel}
                    onHoverNodeId={onHoverNodeId}
                    hoveredNodeId={hoveredNodeId}
                    findNode={findNode}
                    sharedLinksMap={sharedLinksMap}
                  />
                </div>
              )
            })}
          </div>
        </div>
      )}

      {/* Show collapsed indicator */}
      {hasChildren && isCollapsed && (
        <div className="mt-2 ml-6 text-xs text-muted-foreground">
          <span className="rounded bg-accent px-2 py-1">
            {node.children!.length} child node{node.children!.length !== 1 ? 's' : ''} hidden
          </span>
        </div>
      )}
    </div>
  )
}

export default TreePreviewNode
