import { useState, useRef } from 'react'
import {
  Plus,
  Pencil,
  Trash2,
  Copy,
  GripVertical,
  HelpCircle,
  Zap,
  CheckCircle,
  ChevronDown,
  ChevronRight,
  Play,
  AlertCircle,
  AlertTriangle
} from 'lucide-react'
import { useTreeEditorStore, findNodeInTree } from '@/store/treeEditorStore'
import { NodeEditorModal } from './NodeEditorModal'
import type { TreeStructure, NodeType } from '@/types'
import { cn } from '@/lib/utils'

interface NodeListItemProps {
  node: TreeStructure
  depth: number
  parentId: string | null
  index: number
  isLast: boolean
  /** Which option label led to this node (from parent decision) */
  fromOption?: string
  onEdit: (node: TreeStructure) => void
  onDelete: (nodeId: string) => void
  onDuplicate: (nodeId: string) => void
  onAddChild: (parentId: string) => void
  onDragStart: (e: React.DragEvent, nodeId: string, parentId: string | null, index: number) => void
  onDragOver: (e: React.DragEvent, parentId: string | null, index: number) => void
  onDrop: (e: React.DragEvent, parentId: string | null, index: number) => void
  onDragEnd: () => void
  onDragLeave: (e: React.DragEvent) => void
  dragOverTarget: { parentId: string | null; index: number; isValid: boolean } | null
  /** Array of booleans indicating which ancestor levels should show continuing lines */
  ancestorLines?: boolean[]
}

function NodeListItem({
  node,
  depth,
  parentId,
  index,
  isLast,
  fromOption,
  onEdit,
  onDelete,
  onDuplicate,
  onAddChild,
  onDragStart,
  onDragOver,
  onDrop,
  onDragEnd,
  onDragLeave,
  dragOverTarget,
  ancestorLines = []
}: NodeListItemProps) {
  const { selectedNodeId, selectNode, validationErrors } = useTreeEditorStore()
  const [isCollapsed, setIsCollapsed] = useState(false)
  const gripInitiated = useRef(false)
  const isSelected = selectedNodeId === node.id
  const isRootNode = node.id === 'root'
  const nodeErrors = validationErrors.filter(e => e.nodeId === node.id && e.severity === 'error')
  const nodeWarnings = validationErrors.filter(e => e.nodeId === node.id && e.severity === 'warning')
  const hasError = nodeErrors.length > 0
  const hasWarning = nodeWarnings.length > 0
  const hasChildren = node.children && node.children.length > 0

  // Get error/warning messages for tooltip
  const getValidationTooltip = () => {
    const messages: string[] = []
    if (hasError) {
      messages.push(...nodeErrors.map(e => `❌ ${e.message}`))
    }
    if (hasWarning) {
      messages.push(...nodeWarnings.map(e => `⚠️ ${e.message}`))
    }
    return messages.join('\n')
  }

  const isDragTarget =
    dragOverTarget?.parentId === parentId &&
    dragOverTarget?.index === index
  const isDragValid = isDragTarget && dragOverTarget?.isValid

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

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

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

  // 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
  }

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

  // Build tree line prefix for proper hierarchy visualization
  const renderTreeLines = () => {
    if (depth === 0) return null

    return (
      <div className="flex items-center">
        {/* Render continuing lines from ancestors */}
        {ancestorLines.map((showLine, i) => (
          <span
            key={i}
            className={cn(
              'inline-block w-5 text-center text-muted-foreground/50',
              showLine ? 'border-l border-muted-foreground/30' : ''
            )}
          >
            &nbsp;
          </span>
        ))}
        {/* Render current level connector */}
        <span className="inline-block w-5 text-center text-muted-foreground/50 font-mono text-xs">
          {isLast ? '└' : '├'}
        </span>
        <span className="inline-block w-3 text-muted-foreground/50 font-mono text-xs">──</span>
      </div>
    )
  }

  return (
    <>
      {/* Drop indicator above */}
      {isDragTarget && (
        <div
          className={cn(
            'h-1 rounded-full mx-2 transition-colors',
            isDragValid
              ? 'bg-primary'
              : 'bg-destructive animate-pulse shadow-[0_0_8px_rgba(239,68,68,0.6)]'
          )}
          style={{ marginLeft: `${depth * 20 + 8}px` }}
        />
      )}

      <div
        draggable={node.id !== 'root'}
        onDragStart={(e) => {
          if (!gripInitiated.current) {
            e.preventDefault()
            return
          }
          onDragStart(e, node.id, parentId, index)
        }}
        onDragEnd={() => {
          gripInitiated.current = false
          onDragEnd()
        }}
        onDragOver={(e) => onDragOver(e, parentId, index)}
        onDragLeave={onDragLeave}
        onDrop={(e) => onDrop(e, parentId, index)}
        onClick={() => selectNode(node.id)}
        className={cn(
          'group flex items-center gap-1 rounded-md px-2 py-1.5 text-sm transition-colors cursor-pointer',
          isRootNode
            ? isSelected
              ? 'bg-blue-500/20 ring-2 ring-blue-500 shadow-sm'
              : 'bg-blue-500/10 border border-blue-500/30 hover:bg-blue-500/15'
            : isSelected
            ? 'bg-primary/10 ring-1 ring-primary'
            : 'hover:bg-accent',
          hasError && 'ring-1 ring-destructive',
          hasWarning && !hasError && 'ring-1 ring-yellow-500'
        )}
      >
        {/* Tree lines */}
        {renderTreeLines()}

        {/* Collapse toggle for nodes with children */}
        {hasChildren ? (
          <button
            type="button"
            onClick={toggleCollapse}
            className="rounded p-0.5 hover:bg-muted"
          >
            {isCollapsed ? (
              <ChevronRight className="h-3.5 w-3.5 text-muted-foreground" />
            ) : (
              <ChevronDown className="h-3.5 w-3.5 text-muted-foreground" />
            )}
          </button>
        ) : (
          <div className="w-4" />
        )}

        {/* Drag handle */}
        {node.id !== 'root' && (
          <GripVertical
            className="h-4 w-4 cursor-grab text-muted-foreground opacity-0 group-hover:opacity-100"
            onMouseDown={() => { gripInitiated.current = true }}
            onMouseUp={() => { gripInitiated.current = false }}
          />
        )}
        {node.id === 'root' && <div className="w-4" />}

        {/* Node type icon - special treatment for root */}
        {isRootNode ? (
          <span className="flex items-center gap-1 rounded px-1.5 py-0.5 text-xs bg-blue-500/30 text-blue-400 font-semibold">
            <Play className="h-4 w-4" />
            <span className="hidden sm:inline">START</span>
          </span>
        ) : (
          <span className={cn('flex items-center gap-1 rounded px-1.5 py-0.5 text-xs', nodeTypeColors[node.type])}>
            {nodeTypeIcons[node.type]}
            <span className="hidden sm:inline">{node.type}</span>
          </span>
        )}

        {/* From option label */}
        {fromOption && (
          <span className="rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground">
            {fromOption}
          </span>
        )}

        {/* Node label */}
        <span className="flex-1 truncate text-foreground">
          {getNodeLabel()}
        </span>

        {/* Error/Warning badge */}
        {(hasError || hasWarning) && (
          <span
            title={getValidationTooltip()}
            className={cn(
              'flex items-center gap-1 rounded px-1.5 py-0.5 text-xs',
              hasError
                ? 'bg-destructive/20 text-destructive'
                : 'bg-yellow-500/20 text-yellow-500'
            )}
          >
            {hasError ? (
              <AlertCircle className="h-3 w-3" />
            ) : (
              <AlertTriangle className="h-3 w-3" />
            )}
            <span className="hidden sm:inline">
              {hasError ? `${nodeErrors.length} error${nodeErrors.length !== 1 ? 's' : ''}` : `${nodeWarnings.length} warning${nodeWarnings.length !== 1 ? 's' : ''}`}
            </span>
          </span>
        )}

        {/* Node ID */}
        <span
          className="hidden text-xs text-muted-foreground sm:inline cursor-help"
          title={`Full ID: ${node.id}`}
        >
          {node.id === 'root' ? 'root' : node.id.slice(0, 8) + '...'}
        </span>

        {/* Actions */}
        <div className="flex items-center gap-1 opacity-0 group-hover:opacity-100">
          {node.type === 'decision' && (
            <button
              type="button"
              onClick={(e) => {
                e.stopPropagation()
                onAddChild(node.id)
              }}
              title="Add child node"
              aria-label="Add child node"
              className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-accent-foreground"
            >
              <Plus className="h-3 w-3" />
            </button>
          )}
          <button
            type="button"
            onClick={(e) => {
              e.stopPropagation()
              onEdit(node)
            }}
            title="Edit node"
            aria-label="Edit node"
            className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-accent-foreground"
          >
            <Pencil className="h-3 w-3" />
          </button>
          {node.id !== 'root' && (
            <>
              <button
                type="button"
                onClick={(e) => {
                  e.stopPropagation()
                  onDuplicate(node.id)
                }}
                title="Duplicate node"
                aria-label="Duplicate node"
                className="rounded p-1 text-muted-foreground hover:bg-accent hover:text-accent-foreground"
              >
                <Copy className="h-3 w-3" />
              </button>
              <button
                type="button"
                onClick={(e) => {
                  e.stopPropagation()
                  onDelete(node.id)
                }}
                title="Delete node"
                aria-label="Delete node"
                className="rounded p-1 text-muted-foreground hover:bg-destructive/20 hover:text-destructive"
              >
                <Trash2 className="h-3 w-3" />
              </button>
            </>
          )}
        </div>
      </div>

      {/* Collapsed indicator */}
      {hasChildren && isCollapsed && (
        <div
          className="text-xs text-muted-foreground py-1"
          style={{ marginLeft: `${(depth + 1) * 20 + 32}px` }}
        >
          <span className="rounded bg-muted px-2 py-0.5">
            {node.children!.length} hidden
          </span>
        </div>
      )}

      {/* Render children */}
      {!isCollapsed && node.children?.map((child, childIndex) => {
        const optionLabel = getOptionLabelForChild(child.id)
        const isLastChild = childIndex === node.children!.length - 1
        // Build ancestor lines array for children
        const childAncestorLines = depth > 0 ? [...ancestorLines, !isLast] : []

        return (
          <NodeListItem
            key={child.id}
            node={child}
            depth={depth + 1}
            parentId={node.id}
            index={childIndex}
            isLast={isLastChild}
            fromOption={optionLabel}
            onEdit={onEdit}
            onDelete={onDelete}
            onDuplicate={onDuplicate}
            onAddChild={onAddChild}
            onDragStart={onDragStart}
            onDragOver={onDragOver}
            onDrop={onDrop}
            onDragEnd={onDragEnd}
            onDragLeave={onDragLeave}
            dragOverTarget={dragOverTarget}
            ancestorLines={childAncestorLines}
          />
        )
      })}

      {/* Trailing drop zone — allows dropping after the last child */}
      {!isCollapsed && hasChildren && (() => {
        const trailingIndex = node.children!.length
        const isTrailingTarget =
          dragOverTarget?.parentId === node.id &&
          dragOverTarget?.index === trailingIndex
        const isTrailingValid = isTrailingTarget && dragOverTarget?.isValid
        return (
          <div
            className={cn(
              'h-2 rounded-full mx-2 transition-colors',
              isTrailingTarget
                ? isTrailingValid
                  ? 'bg-primary'
                  : 'bg-destructive animate-pulse shadow-[0_0_8px_rgba(239,68,68,0.6)]'
                : 'bg-transparent'
            )}
            style={{ marginLeft: `${(depth + 1) * 20 + 8}px` }}
            onDragOver={(e) => onDragOver(e, node.id, trailingIndex)}
            onDragLeave={onDragLeave}
            onDrop={(e) => onDrop(e, node.id, trailingIndex)}
          />
        )
      })()}
    </>
  )
}

export function NodeList() {
  const { treeStructure, addNode, deleteNode, duplicateNode, reorderNodes, moveNode, findNode } = useTreeEditorStore()
  const [editingNodeId, setEditingNodeId] = useState<string | null>(null)
  const [isEditingNewNode, setIsEditingNewNode] = useState(false)
  const [addingToParent, setAddingToParent] = useState<string | null>(null)

  // Get the current node from store (will update when store changes)
  const editingNode = editingNodeId ? findNode(editingNodeId) : null
  const [dragState, setDragState] = useState<{
    nodeId: string
    parentId: string | null
    index: number
  } | null>(null)
  const [dragOverTarget, setDragOverTarget] = useState<{
    parentId: string | null
    index: number
    isValid: boolean
  } | null>(null)

  const handleAddNode = (type: NodeType) => {
    const newId = addNode(addingToParent, type)
    setAddingToParent(null)
    // Open editor for the new node and mark it as new
    setEditingNodeId(newId)
    setIsEditingNewNode(true)
  }

  const handleEditExistingNode = (node: TreeStructure) => {
    setEditingNodeId(node.id)
    setIsEditingNewNode(false)
  }

  const handleCloseEditor = () => {
    setEditingNodeId(null)
    setIsEditingNewNode(false)
  }

  const handleDragStart = (
    e: React.DragEvent,
    nodeId: string,
    parentId: string | null,
    index: number
  ) => {
    e.dataTransfer.effectAllowed = 'move'
    setDragState({ nodeId, parentId, index })
  }

  // Check if a node can be dropped at a target location
  const canDropAt = (draggedNodeId: string, targetParentId: string | null): boolean => {
    if (!treeStructure) return false

    // Can't drop at root level (no parent)
    if (targetParentId === null) return false

    // Can't drop onto itself
    if (draggedNodeId === targetParentId) return false

    // Can't drop onto a descendant of the dragged node
    const draggedNode = findNodeInTree(draggedNodeId, treeStructure)
    if (!draggedNode) return false
    if (findNodeInTree(targetParentId, draggedNode)) return false

    // Target parent must be able to have children (solution nodes are terminal)
    const targetParent = findNodeInTree(targetParentId, treeStructure)
    if (!targetParent) return false
    if (targetParent.type === 'solution') return false

    return true
  }

  const handleDragOver = (
    e: React.DragEvent,
    parentId: string | null,
    index: number
  ) => {
    e.preventDefault()
    if (!dragState) return

    // Don't show indicator when hovering over self
    if (dragState.nodeId === parentId) return

    const isValid = canDropAt(dragState.nodeId, parentId)
    setDragOverTarget({ parentId, index, isValid })
  }

  const handleDragLeave = (e: React.DragEvent) => {
    // Only clear if leaving to an element outside the current target
    const relatedTarget = e.relatedTarget as HTMLElement | null
    if (!relatedTarget || !e.currentTarget.contains(relatedTarget)) {
      setDragOverTarget(null)
    }
  }

  const handleDrop = (
    e: React.DragEvent,
    targetParentId: string | null,
    targetIndex: number
  ) => {
    e.preventDefault()
    if (!dragState) return

    const { parentId: sourceParentId, index: sourceIndex, nodeId } = dragState

    // Only execute valid drops
    if (targetParentId && canDropAt(nodeId, targetParentId)) {
      if (sourceParentId === targetParentId) {
        // Same parent — use reorderNodes with index adjustment
        const adjustedIndex = sourceIndex < targetIndex ? targetIndex - 1 : targetIndex
        if (sourceIndex !== adjustedIndex) {
          reorderNodes(sourceParentId, sourceIndex, adjustedIndex)
        }
      } else {
        // Cross-parent — use moveNode
        moveNode(nodeId, targetParentId, targetIndex)
      }
    }

    setDragState(null)
    setDragOverTarget(null)
  }

  const handleDragEnd = () => {
    setDragState(null)
    setDragOverTarget(null)
  }

  if (!treeStructure) {
    return (
      <div className="rounded-lg border border-border bg-card p-4 text-center text-sm text-muted-foreground">
        No tree structure. Add a root node to get started.
      </div>
    )
  }

  return (
    <div className="rounded-lg border border-border bg-card">
      <div className="flex items-center justify-between border-b border-border p-3">
        <h2 className="text-sm font-semibold text-card-foreground">Nodes</h2>
        <button
          type="button"
          onClick={() => setAddingToParent(treeStructure.id)}
          className={cn(
            'flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium',
            'bg-primary text-primary-foreground hover:bg-primary/90'
          )}
        >
          <Plus className="h-3 w-3" />
          Add Node
        </button>
      </div>

      <div className="max-h-[500px] space-y-0.5 overflow-y-auto p-2">
        <NodeListItem
          node={treeStructure}
          depth={0}
          parentId={null}
          index={0}
          isLast={true}
          onEdit={handleEditExistingNode}
          onDelete={deleteNode}
          onDuplicate={duplicateNode}
          onAddChild={setAddingToParent}
          onDragStart={handleDragStart}
          onDragOver={handleDragOver}
          onDrop={handleDrop}
          onDragEnd={handleDragEnd}
          onDragLeave={handleDragLeave}
          dragOverTarget={dragOverTarget}
        />
      </div>

      {/* Add Node Type Selector */}
      {addingToParent && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm">
          <div className="w-full max-w-xs rounded-lg border border-border bg-card p-4 shadow-lg">
            <h3 className="mb-3 text-sm font-semibold">Select Node Type</h3>
            <div className="space-y-2">
              <button
                type="button"
                onClick={() => handleAddNode('decision')}
                className={cn(
                  'flex w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm',
                  'border border-blue-500/30 bg-blue-500/10 hover:bg-blue-500/20'
                )}
              >
                <HelpCircle className="h-4 w-4 text-blue-500" />
                <div>
                  <div className="font-medium">Decision</div>
                  <div className="text-xs text-muted-foreground">Question with options</div>
                </div>
              </button>
              <button
                type="button"
                onClick={() => handleAddNode('action')}
                className={cn(
                  'flex w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm',
                  'border border-yellow-500/30 bg-yellow-500/10 hover:bg-yellow-500/20'
                )}
              >
                <Zap className="h-4 w-4 text-yellow-500" />
                <div>
                  <div className="font-medium">Action</div>
                  <div className="text-xs text-muted-foreground">Task to perform</div>
                </div>
              </button>
              <button
                type="button"
                onClick={() => handleAddNode('solution')}
                className={cn(
                  'flex w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm',
                  'border border-green-500/30 bg-green-500/10 hover:bg-green-500/20'
                )}
              >
                <CheckCircle className="h-4 w-4 text-green-500" />
                <div>
                  <div className="font-medium">Solution</div>
                  <div className="text-xs text-muted-foreground">Resolution endpoint</div>
                </div>
              </button>
            </div>
            <button
              type="button"
              onClick={() => setAddingToParent(null)}
              className="mt-3 w-full rounded-md border border-input px-3 py-2 text-sm hover:bg-accent"
            >
              Cancel
            </button>
          </div>
        </div>
      )}

      {/* Node Editor Modal */}
      {editingNode && (
        <NodeEditorModal
          node={editingNode}
          onClose={handleCloseEditor}
          isNewNode={isEditingNewNode}
        />
      )}
    </div>
  )
}

export default NodeList
