import { useCallback, useMemo, useState, useEffect } from 'react'
import {
  ReactFlow,
  Background,
  Controls,
  MiniMap,
  BackgroundVariant,
  useReactFlow,
  useNodesState,
  useEdgesState,
  ReactFlowProvider,
  PanOnScrollMode,
  type NodeMouseHandler,
} from '@xyflow/react'
import '@xyflow/react/dist/style.css'

import { FlowCanvasNode, NODE_TYPE_CONFIG } from './FlowCanvasNode'
import { FlowCanvasAnswerNode } from './FlowCanvasAnswerNode'
import { useTreeLayout } from './useTreeLayout'
import { cn } from '@/lib/utils'
import { Map as MapIcon, MapPinOff } from 'lucide-react'
import type { FlowCanvasNodeData } from './FlowCanvasNode'
import type { FlowCanvasAnswerNodeData } from './FlowCanvasAnswerNode'

const nodeTypes = {
  flowNode: FlowCanvasNode,
  answerStub: FlowCanvasAnswerNode,
}

interface FlowCanvasProps {
  selectedNodeId: string | null
  onNodeSelect: (nodeId: string | null) => void
  onSelectAnswerType: (nodeId: string, type: 'decision' | 'action' | 'solution') => void
}

function FlowCanvasInner({ selectedNodeId, onNodeSelect, onSelectAnswerType }: FlowCanvasProps) {
  const { fitView, setCenter } = useReactFlow()
  const { nodes: layoutNodes, edges: layoutEdges, collapsedNodeIds, toggleCollapse, onNodesMeasured } = useTreeLayout()
  const [minimapVisible, setMinimapVisible] = useState(true)

  // Inject callbacks into node data (because useTreeLayout creates placeholder functions)
  const nodesWithCallbacks = useMemo(() => {
    return layoutNodes.map(n => {
      if (n.type === 'flowNode') {
        const data = n.data as unknown as FlowCanvasNodeData
        return {
          ...n,
          selected: n.id === selectedNodeId,
          data: { ...data, onToggleCollapse: toggleCollapse },
        }
      }
      if (n.type === 'answerStub') {
        const data = n.data as unknown as FlowCanvasAnswerNodeData
        return {
          ...n,
          selected: n.id === selectedNodeId,
          data: { ...data, onSelectType: onSelectAnswerType },
        }
      }
      return n
    })
  }, [layoutNodes, selectedNodeId, toggleCollapse, onSelectAnswerType])

  const [nodes, setNodes, onNodesChange] = useNodesState(nodesWithCallbacks)
  const [edges, setEdges, onEdgesChange] = useEdgesState(layoutEdges)

  // Sync layout changes into React Flow state
  useEffect(() => {
    setNodes(nodesWithCallbacks)
    setEdges(layoutEdges)
  }, [nodesWithCallbacks, layoutEdges, setNodes, setEdges])

  // Fit view after layout changes
  useEffect(() => {
    // Small delay to let React Flow process the node updates
    const timer = setTimeout(() => {
      fitView({ padding: 0.1, duration: 200 })
    }, 50)
    return () => clearTimeout(timer)
  }, [layoutNodes.length, collapsedNodeIds.size]) // eslint-disable-line react-hooks/exhaustive-deps

  // Auto-center on selected node when panel opens
  useEffect(() => {
    if (!selectedNodeId) return
    const node = nodes.find(n => n.id === selectedNodeId)
    if (node) {
      const x = node.position.x + 140 // center of 280px node
      const y = node.position.y + 50
      setCenter(x, y, { duration: 300, zoom: 1 })
    }
  }, [selectedNodeId]) // eslint-disable-line react-hooks/exhaustive-deps

  // Height measurement correction
  useEffect(() => {
    if (nodes.length > 0 && nodes.some(n => n.measured?.height)) {
      onNodesMeasured(nodes)
    }
  }, [nodes]) // eslint-disable-line react-hooks/exhaustive-deps

  const handleNodeClick: NodeMouseHandler = useCallback((_event, node) => {
    onNodeSelect(node.id)
  }, [onNodeSelect])

  const handlePaneClick = useCallback(() => {
    onNodeSelect(null)
  }, [onNodeSelect])

  // Custom minimap node color based on actual tree node type
  const minimapNodeColor = useCallback((rfNode: { data?: unknown }) => {
    const data = rfNode.data as (FlowCanvasNodeData & FlowCanvasAnswerNodeData) | undefined
    if (!data || !('node' in data)) return '#6b7280'
    const treeNode = data.node
    if (treeNode.type === 'answer') return '#6b7280'
    const config = NODE_TYPE_CONFIG[treeNode.type as keyof typeof NODE_TYPE_CONFIG]
    return config?.minimapColor ?? '#6b7280'
  }, [])

  return (
    <div className="relative h-full w-full">
      <ReactFlow
        nodes={nodes}
        edges={edges}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
        nodeTypes={nodeTypes}
        onNodeClick={handleNodeClick}
        onPaneClick={handlePaneClick}
        fitView
        minZoom={0.25}
        maxZoom={2}
        zoomOnScroll={false}
        zoomOnPinch={true}
        panOnScroll={true}
        panOnScrollMode={PanOnScrollMode.Vertical}
        selectionOnDrag={false}
        nodesDraggable={false}
        nodesConnectable={false}
        proOptions={{ hideAttribution: true }}
        className="dark bg-accent/30"
      >
        <Background variant={BackgroundVariant.Dots} gap={20} size={1.5} color="hsl(var(--muted-foreground) / 0.25)" />
        <Controls showInteractive={false} className="!bg-card !border-border !shadow-lg" />
        {minimapVisible && (
          <MiniMap
            pannable
            zoomable
            nodeColor={minimapNodeColor}
            className="!bg-card !border-border"
            nodeStrokeWidth={2}
          />
        )}
      </ReactFlow>

      {/* Minimap toggle button */}
      <button
        onClick={() => setMinimapVisible(v => !v)}
        className={cn(
          'absolute bottom-2 right-2 z-10 rounded-lg border border-border bg-card p-2 text-muted-foreground shadow-lg hover:bg-accent hover:text-foreground transition-colors',
          minimapVisible && 'bottom-[170px]'
        )}
        title={minimapVisible ? 'Hide minimap' : 'Show minimap'}
      >
        {minimapVisible ? <MapPinOff className="h-4 w-4" /> : <MapIcon className="h-4 w-4" />}
      </button>
    </div>
  )
}

// Wrap in ReactFlowProvider (required by useReactFlow hook)
export function FlowCanvas(props: FlowCanvasProps) {
  return (
    <ReactFlowProvider>
      <FlowCanvasInner {...props} />
    </ReactFlowProvider>
  )
}
