import { useCallback, useRef, useState, type DragEvent } from 'react';
import {
  ReactFlow,
  Background,
  Controls,
  MiniMap,
  type Connection,
  type Node,
  type Edge,
  BackgroundVariant,
  type OnNodesChange,
  type OnEdgesChange,
  useReactFlow,
  ReactFlowProvider,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import TransactionNodeComponent from './TransactionNode';
import {
  Save, GitBranch, ShieldCheck, FlaskConical, Play,
  AlertTriangle, CheckCircle2, DollarSign, Clock, Globe,
  Undo2, Redo2, Copy, Trash2, Plus, X, SplitSquareHorizontal,
  ZoomIn, ZoomOut, Maximize
} from 'lucide-react';
import type { ComponentItem, TransactionTab, SessionMode } from '../types';

const nodeTypes = { transactionNode: TransactionNodeComponent };

interface CanvasProps {
  nodes: Node[];
  edges: Edge[];
  setNodes: (updater: Node[] | ((prev: Node[]) => Node[])) => void;
  setEdges: (updater: Edge[] | ((prev: Edge[]) => Edge[])) => void;
  onNodesChange: OnNodesChange;
  onEdgesChange: OnEdgesChange;
  onConnect: (params: Connection) => void;
  onSelectionChange: (params: { nodes: Node[] }) => void;
  onDropComponent: (item: ComponentItem, position: { x: number; y: number }) => void;
  onValidate: () => void;
  onSimulate: () => void;
  onExecute: () => void;
  transactionName: string;
  onRenameTransaction: (name: string) => void;
  isSimulating: boolean;
  simulationResults: string | null;
  onDismissSimulation: () => void;
  mode: SessionMode;
  canUndo: boolean;
  canRedo: boolean;
  onUndo: () => void;
  onRedo: () => void;
  selectedNodeIds: Set<string>;
  onDeleteSelected: () => void;
  onDuplicateSelected: () => void;
  transactionTabs: TransactionTab[];
  activeTransactionId: string;
  onSwitchTab: (id: string) => void;
  onAddTab: () => void;
  onCloseTab: (id: string) => void;
  splitView: boolean;
  onToggleSplitView: () => void;
  pushHistory: (nodes: Node[], edges: Edge[]) => void;
}

function CanvasInner({
  nodes, edges,
  onNodesChange, onEdgesChange, onConnect, onSelectionChange, onDropComponent,
  onValidate, onSimulate, onExecute,
  transactionName, onRenameTransaction,
  isSimulating, simulationResults, onDismissSimulation,
  mode, canUndo, canRedo, onUndo, onRedo,
  selectedNodeIds, onDeleteSelected, onDuplicateSelected,
  transactionTabs, activeTransactionId, onSwitchTab, onAddTab, onCloseTab,
  splitView, onToggleSplitView,
}: CanvasProps) {
  const reactFlowWrapper = useRef<HTMLDivElement>(null);
  const [isEditingName, setIsEditingName] = useState(false);
  const [editName, setEditName] = useState(transactionName);
  const [zoomLevel, setZoomLevel] = useState(100);
  const reactFlowInstance = useReactFlow();

  const onDragOver = useCallback((event: DragEvent) => {
    event.preventDefault();
    event.dataTransfer.dropEffect = 'move';
  }, []);

  const onDrop = useCallback(
    (event: DragEvent) => {
      event.preventDefault();
      const data = event.dataTransfer.getData('application/transactflow-component');
      if (!data) return;
      const item: ComponentItem = JSON.parse(data);
      const wrapperBounds = reactFlowWrapper.current?.getBoundingClientRect();
      if (!wrapperBounds) return;
      const position = reactFlowInstance.screenToFlowPosition({
        x: event.clientX,
        y: event.clientY,
      });
      onDropComponent(item, position);
    },
    [onDropComponent, reactFlowInstance]
  );

  const onMoveEnd = useCallback(() => {
    const zoom = reactFlowInstance.getZoom();
    setZoomLevel(Math.round(zoom * 100));
  }, [reactFlowInstance]);

  const handleZoomIn = () => { reactFlowInstance.zoomIn(); setZoomLevel(Math.round(reactFlowInstance.getZoom() * 100)); };
  const handleZoomOut = () => { reactFlowInstance.zoomOut(); setZoomLevel(Math.round(reactFlowInstance.getZoom() * 100)); };
  const handleFitView = () => { reactFlowInstance.fitView(); setTimeout(() => setZoomLevel(Math.round(reactFlowInstance.getZoom() * 100)), 100); };

  const errorCount = nodes.filter(n => (n.data as Record<string, unknown>).status === 'error').length;
  const warningCount = nodes.filter(n => (n.data as Record<string, unknown>).status === 'warning').length;

  const commitName = () => {
    setIsEditingName(false);
    if (editName.trim()) onRenameTransaction(editName.trim());
    else setEditName(transactionName);
  };

  return (
    <div className="canvas-container">
      {/* Transaction tabs */}
      <div className="transaction-tabs">
        {transactionTabs.map(tab => (
          <div
            key={tab.id}
            className={`transaction-tab ${tab.id === activeTransactionId ? 'active' : ''}`}
            onClick={() => onSwitchTab(tab.id)}
          >
            <span>{tab.name}</span>
            {transactionTabs.length > 1 && (
              <button className="tab-close" onClick={e => { e.stopPropagation(); onCloseTab(tab.id); }}>
                <X size={10} />
              </button>
            )}
          </div>
        ))}
        <button className="transaction-tab-add" onClick={onAddTab} title="New Transaction">
          <Plus size={12} />
        </button>
      </div>

      <div className="canvas-header">
        <div className="canvas-header-left">
          {isEditingName ? (
            <input
              className="canvas-tx-name-input"
              value={editName}
              onChange={e => setEditName(e.target.value)}
              onBlur={commitName}
              onKeyDown={e => { if (e.key === 'Enter') commitName(); if (e.key === 'Escape') { setEditName(transactionName); setIsEditingName(false); } }}
              autoFocus
            />
          ) : (
            <span
              className="canvas-tx-name"
              onClick={() => { setIsEditingName(true); setEditName(transactionName); }}
              title="Click to rename"
            >
              {transactionName}
            </span>
          )}
          <span className="canvas-version">v1.0</span>
          <span className="canvas-save-state">
            <Save size={12} /> Saved
          </span>
          <div className="canvas-toolbar-separator" />
          <button className="canvas-toolbar-btn" onClick={onUndo} disabled={!canUndo} title="Undo (Ctrl+Z)">
            <Undo2 size={14} />
          </button>
          <button className="canvas-toolbar-btn" onClick={onRedo} disabled={!canRedo} title="Redo (Ctrl+Y)">
            <Redo2 size={14} />
          </button>
          <div className="canvas-toolbar-separator" />
          <button className="canvas-toolbar-btn" onClick={onDuplicateSelected} disabled={selectedNodeIds.size === 0} title="Duplicate (Ctrl+D)">
            <Copy size={14} />
          </button>
          <button className="canvas-toolbar-btn" onClick={onDeleteSelected} disabled={selectedNodeIds.size === 0} title="Delete (Del)">
            <Trash2 size={14} />
          </button>
          <div className="canvas-toolbar-separator" />
          <button className="canvas-toolbar-btn" onClick={onToggleSplitView} title="Split View">
            <SplitSquareHorizontal size={14} />
          </button>
        </div>
        <div className="canvas-header-center">
          <button className="canvas-env-btn">
            <GitBranch size={13} />
            <span>{mode}</span>
          </button>
        </div>
        <div className="canvas-header-right">
          <button className="canvas-action-btn validate" onClick={onValidate}>
            <ShieldCheck size={14} /> Validate
          </button>
          <button className="canvas-action-btn simulate" onClick={onSimulate} disabled={isSimulating}>
            <FlaskConical size={14} /> {isSimulating ? 'Simulating...' : 'Simulate'}
          </button>
          <button className="canvas-action-btn execute" onClick={onExecute}>
            <Play size={14} /> Execute
          </button>
        </div>
      </div>

      <div className="canvas-body" ref={reactFlowWrapper}>
        <div style={{ display: 'flex', width: '100%', height: '100%' }}>
          <div style={{ flex: 1, position: 'relative' }}>
            <ReactFlow
              nodes={nodes}
              edges={edges}
              onNodesChange={onNodesChange}
              onEdgesChange={onEdgesChange}
              onConnect={onConnect}
              onSelectionChange={onSelectionChange}
              onDragOver={onDragOver}
              onDrop={onDrop}
              onMoveEnd={onMoveEnd}
              nodeTypes={nodeTypes}
              fitView
              snapToGrid
              snapGrid={[16, 16]}
              multiSelectionKeyCode="Shift"
              deleteKeyCode={null}
              defaultEdgeOptions={{
                animated: true,
                style: { stroke: '#3b82f6', strokeWidth: 2 },
              }}
              proOptions={{ hideAttribution: true }}
            >
              <Background variant={BackgroundVariant.Dots} gap={16} size={1} color="#333" />
              <Controls className="canvas-controls" showZoom={false} showFitView={false} showInteractive={false}>
                <button className="react-flow__controls-button" onClick={handleZoomIn} title="Zoom In">
                  <ZoomIn size={14} />
                </button>
                <button className="react-flow__controls-button" onClick={handleZoomOut} title="Zoom Out">
                  <ZoomOut size={14} />
                </button>
                <button className="react-flow__controls-button zoom-display" title="Current Zoom">
                  {zoomLevel}%
                </button>
                <button className="react-flow__controls-button" onClick={handleFitView} title="Fit View">
                  <Maximize size={14} />
                </button>
              </Controls>
              <MiniMap
                className="canvas-minimap"
                nodeColor={(n) => {
                  const d = n.data as Record<string, unknown>;
                  return (d?.color as string) || '#3b82f6';
                }}
                maskColor="rgba(0,0,0,0.7)"
              />
            </ReactFlow>
          </div>

          {splitView && (
            <>
              <div style={{ width: 1, background: '#2a2a32', flexShrink: 0 }} />
              <div style={{ flex: 1, position: 'relative', background: '#0e0e10', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <div style={{ textAlign: 'center', color: '#5c5c68' }}>
                  <SplitSquareHorizontal size={32} style={{ marginBottom: 8, opacity: 0.4 }} />
                  <p style={{ fontSize: 13 }}>Comparison View</p>
                  <p style={{ fontSize: 11, marginTop: 4 }}>Select a saved version or branch to compare</p>
                </div>
              </div>
            </>
          )}
        </div>

        {nodes.length === 0 && !splitView && (
          <div className="canvas-empty">
            <div className="canvas-empty-content">
              <div className="canvas-empty-icon">⚡</div>
              <h3>Start Building</h3>
              <p>Drag components from the left panel onto the canvas to compose your transaction flow</p>
              <p className="canvas-empty-hint">or press <kbd>Ctrl+K</kbd> to search components</p>
            </div>
          </div>
        )}

        {/* Simulation overlay */}
        {isSimulating && (
          <div className="simulation-overlay">
            <div className="simulation-spinner" />
            <span>Running simulation...</span>
          </div>
        )}

        {simulationResults && (
          <div className="simulation-results-overlay">
            <div className="simulation-results-card">
              <div className="simulation-results-header">
                <CheckCircle2 size={16} color="#22c55e" />
                <span>Simulation Results</span>
                <button className="simulation-dismiss" onClick={onDismissSimulation}><X size={14} /></button>
              </div>
              <pre className="simulation-results-body">{simulationResults}</pre>
            </div>
          </div>
        )}
      </div>

      <div className="canvas-inspector">
        <div className="inspector-item">
          <CheckCircle2 size={12} color="#22c55e" />
          <span>{nodes.length} nodes</span>
        </div>
        <div className="inspector-item">
          <span>{edges.length} connections</span>
        </div>
        <div className="inspector-separator" />
        <div className="inspector-item">
          <AlertTriangle size={12} color={errorCount > 0 ? '#ef4444' : '#555'} />
          <span>{errorCount} errors</span>
        </div>
        <div className="inspector-item">
          <AlertTriangle size={12} color={warningCount > 0 ? '#eab308' : '#555'} />
          <span>{warningCount} warnings</span>
        </div>
        <div className="inspector-separator" />
        <div className="inspector-item">
          <DollarSign size={12} />
          <span>Est. fees: {nodes.length > 0 ? '$0.02%' : '—'}</span>
        </div>
        <div className="inspector-item">
          <Clock size={12} />
          <span>Settlement: {nodes.length > 0 ? 'T+1' : '—'}</span>
        </div>
        <div className="inspector-item">
          <Globe size={12} />
          <span>Jurisdictions: {nodes.length > 0 ? 'Multi' : '—'}</span>
        </div>
        {selectedNodeIds.size > 0 && (
          <>
            <div className="inspector-separator" />
            <div className="inspector-item selected-info">
              <span>{selectedNodeIds.size} selected</span>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

export default function Canvas(props: CanvasProps) {
  return (
    <ReactFlowProvider>
      <CanvasInner {...props} />
    </ReactFlowProvider>
  );
}
