import React, { useMemo, useEffect, useRef } from 'react';
import ReactFlow, { 
  ReactFlowProvider,
  useReactFlow,
  Background, 
  Controls, 
  Panel,
  Handle,
  Position,
} from 'reactflow';
import type { Node, Edge, NodeProps } from 'reactflow';
import { toPng } from 'html-to-image';

import 'reactflow/dist/style.css';
import { useStore } from '../../store/useStore';
import type { TestCaseNode, Priority } from '../../store/useStore';

import { Plus, CornerDownRight, ChevronRight, ChevronDown, Bug, Link, Trash2 } from 'lucide-react';
import { useToastStore } from '../layout/Toast';

// Custom Node Component
const MindMapNode = ({ data }: NodeProps) => {
  const node = data.node as TestCaseNode;
  const { updateNode, addNode, addSiblingNode, deleteNode, selectedNodeId, setSelectedNodeId, editingNodeId, setEditingNodeId } = useStore();
  const isSelected = selectedNodeId === node.id;
  const isEditing = editingNodeId === node.id;
  const isSet = !node.caseId;

  // Local state for editing — avoids store re-renders breaking the input
  const [editingText, setEditingText] = React.useState(node.text);
  React.useEffect(() => {
    if (isEditing) setEditingText(node.text);
  }, [isEditing, node.id]);

  const commitEdit = () => {
    updateNode(node.id, { text: editingText });
    setEditingNodeId(null);
  };

  const priorityColors: Record<Priority, string> = {
    P0: '#F53F3F',
    P1: '#FF7D00',
    P2: '#F7BA1E',
    P3: '#165DFF',
  };

  const statusStyles: Record<string, { border: string, bg: string, color: string }> = {
    PASS: { border: '#00B42A', bg: '#E8FFFB', color: '#00B42A' },
    FAIL: { border: '#F53F3F', bg: '#FFECE8', color: '#F53F3F' },
    BLOCK: { border: '#FF7D00', bg: '#FFF7E8', color: '#FF7D00' },
    UNTESTED: { border: '#E5E6EB', bg: 'white', color: '#86909C' }
  };

  const currentStatus = node.executionStatus || 'UNTESTED';
  const statusStyle = statusStyles[currentStatus];

  return (
    <div 
      className={`mind-node status-${currentStatus} ${node.priority ? 'has-priority' : ''} ${isSelected ? 'selected' : ''} ${isSet ? 'is-set' : ''}`}
      style={{ 
        position: 'relative',
        borderColor: isSelected ? 'var(--primary)' : statusStyle.border,
        background: statusStyle.bg
      }}
      onClick={(e) => {
        e.stopPropagation();
        setSelectedNodeId(node.id);
      }}
      onDoubleClick={(e) => {
        e.stopPropagation();
        setEditingNodeId(node.id);
      }}
    >
      <Handle type="target" position={Position.Left} style={{ background: '#165DFF', width: '8px', height: '8px' }} />

      <div className="node-content">
        <div className="node-main">
          {node.priority && (
            <span 
              className="priority-badge" 
              style={{ backgroundColor: priorityColors[node.priority] }}
            >
              {node.priority}
            </span>
          )}
          {isEditing ? (
            <input 
              autoFocus
              className="node-input"
              value={editingText}
              onChange={(e) => setEditingText(e.target.value)}
              onBlur={commitEdit}
              onKeyDown={(e) => {
                if (e.key === 'Enter') { e.preventDefault(); commitEdit(); }
                if (e.key === 'Escape') { setEditingText(node.text); setEditingNodeId(null); }
              }}
              placeholder=""
            />
          ) : (
            <span className="node-text">{node.text || '未命名'}</span>

          )}
        </div>

        {(node.requirementId || node.bugId || (node.tags && node.tags.length > 0)) && (
          <div className="node-meta">
            {node.requirementId && (
              <span className="meta-badge req" title={`需求: ${node.requirementId}`}>
                <Link size={10} /> {node.requirementId}
              </span>
            )}
            {node.bugId && (
              <span className="meta-badge bug" title={`Bug: ${node.bugId}`}>
                <Bug size={10} /> {node.bugId}
              </span>
            )}
            {node.tags && node.tags.map((tag, idx) => (
              <span key={idx} className="meta-badge tag">
                {tag}
              </span>
            ))}
          </div>
        )}

        <div className="node-actions">
          <button onClick={(e) => { e.stopPropagation(); addNode(node.id); }} className="action-btn" title="添加子节点 (Tab)">
            <Plus size={12} />
          </button>
          <button onClick={(e) => { e.stopPropagation(); addSiblingNode(node.id); }} className="action-btn" title="添加同级 (Enter)">
            <CornerDownRight size={12} />
          </button>
          <button onClick={(e) => { e.stopPropagation(); deleteNode(node.id); }} className="action-btn action-btn-danger" title="删除 (Delete)">
            <Trash2 size={12} />
          </button>
        </div>
      </div>

      <Handle type="source" position={Position.Right} style={{ background: '#165DFF', width: '8px', height: '8px' }} />
      
      {node.children && node.children.length > 0 && (
        <button 
          className="collapse-btn" 
          onClick={(e) => {
            e.stopPropagation();
            updateNode(node.id, { isExpanded: node.isExpanded === false ? true : false });
          }}
        >
          {node.isExpanded === false ? <ChevronRight size={10} /> : <ChevronDown size={10} />}
        </button>
      )}

      <style>{`
        .mind-node {
          background: white;
          padding: 8px 12px;
          border-radius: 8px;
          border: 2px solid #E5E6EB;
          box-shadow: 0 2px 4px rgba(0,0,0,0.05);
          min-width: 140px;
          transition: all 0.2s;
          border-left-width: 6px; /* Status emphasis */
        }
        .mind-node.status-PASS { border-left-color: #00B42A; }
        .mind-node.status-FAIL { border-left-color: #F53F3F; }
        .mind-node.status-BLOCK { border-left-color: #FF7D00; }
        .mind-node.status-UNTESTED { border-left-color: #E5E6EB; }
        .mind-node:hover {
          border-color: var(--primary);
          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        }
        .mind-node.selected {
          border-color: var(--primary);
          box-shadow: 0 0 0 3px rgba(0, 102, 255, 0.2);
          background: #F0F7FF;
        }
        .mind-node.is-set {
          border-left: 4px solid var(--primary);
        }
        .node-content {
          display: flex;
          flex-direction: column;
          gap: 4px;
        }
        .node-main {
          display: flex;
          align-items: center;
          gap: 8px;
        }
        .node-meta {
          display: flex;
          gap: 6px;
          margin-top: 2px;
        }
        .meta-badge {
          font-size: 10px;
          display: flex;
          align-items: center;
          gap: 2px;
          padding: 2px 4px;
          border-radius: 4px;
        }
        .meta-badge.req { background: #E8F4FF; color: #165DFF; }
        .meta-badge.bug { background: #FFECE8; color: #F53F3F; }
        .meta-badge.tag { background: #F2F3F5; color: #4E5969; border: 1px solid #E5E6EB; }

        .node-text {
          font-size: 13px;
          font-weight: 500;
          color: #1D2129;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
        .node-input {
          border: none;
          outline: none;
          font-size: 13px;
          font-weight: 500;
          color: #1D2129;
          width: 100%;
          background: transparent;
        }

        .priority-badge {
          font-size: 10px;
          color: white;
          padding: 1px 4px;
          border-radius: 4px;
          font-weight: 700;
        }
        .node-set-label {
          font-size: 10px;
          color: var(--primary);
          background: #E8F4FF;
          border: 1px solid rgba(22, 93, 255, 0.2);
          border-radius: 4px;
          padding: 1px 6px;
          font-weight: 500;
          display: inline-block;
          align-self: flex-start;
          margin-top: 2px;
          letter-spacing: 0.5px;
        }
        .node-actions {
          position: absolute;
          right: -24px;
          top: 50%;
          transform: translateY(-50%);
          opacity: 0;
          transition: opacity 0.2s;
          display: flex;
          flex-direction: column;
          gap: 2px;
        }
        .mind-node:hover .node-actions {
          opacity: 1;
        }
        .action-btn {
          border: none;
          background: white;
          border: 1px solid #E5E6EB;
          width: 20px;
          height: 20px;
          border-radius: 50%;
          display: flex;
          align-items: center;
          justify-content: center;
          cursor: pointer;
          color: var(--primary);
          box-shadow: 0 2px 4px rgba(0,0,0,0.05);
        }
        .action-btn:hover {
          background: #F0F7FF;
        }
        .action-btn-danger:hover {
          background: #FFF1F0 !important;
          color: #F53F3F !important;
          border-color: #F53F3F !important;
        }
        .collapse-btn {
          position: absolute;
          right: -8px;
          top: 50%;
          transform: translateY(-50%);
          width: 16px;
          height: 16px;
          border-radius: 50%;
          border: 1px solid #E5E6EB;
          background: white;
          display: flex;
          align-items: center;
          justify-content: center;
          cursor: pointer;
          z-index: 10;
          color: #86909C;
        }
        .collapse-btn:hover {
          border-color: var(--primary);
          color: var(--primary);
        }
      `}</style>

    </div>
  );
};

const nodeTypes = {
  mindMap: MindMapNode,
};
 
 interface MindMapProps {
   selectedModuleId?: string | null;
   onClearModuleSelection?: () => void;
   executionMode?: boolean;
 }

 const MindMapInner: React.FC<MindMapProps> = ({ selectedModuleId, onClearModuleSelection, executionMode }) => {


   const { spaceData, currentSpaceId, selectedNodeId, editingNodeId, addNode, addSiblingNode, deleteNode, setEditingNodeId, selectedPlanId, testPlans } = useStore();
   const testCases = spaceData[currentSpaceId] || [];
   const { addToast } = useToastStore();
   const { fitView } = useReactFlow();

  const handleExportImage = () => {
    const element = document.querySelector('.react-flow__viewport') as HTMLElement;
    if (!element) return;
    
    addToast('正在生成图片...', 'info');
    toPng(document.querySelector('.react-flow') as HTMLElement, {
      backgroundColor: '#f8fafc',
      filter: (node) => {
        // Exclude controls and panels from the export
        if (node?.classList?.contains('react-flow__controls') || node?.classList?.contains('react-flow__panel')) {
          return false;
        }
        return true;
      }
    }).then((dataUrl) => {
      const link = document.createElement('a');
      link.download = `mindmap-${currentSpaceId}-${Date.now()}.png`;
      link.href = dataUrl;
      link.click();
      addToast('导出成功', 'success');
    }).catch((err) => {
      console.error('Export failed', err);
      addToast('导出失败', 'error');
    });
  };

  const handleAutoLayout = () => {
    fitView({ duration: 800, padding: 0.2 });
    addToast('布局已整理', 'success');
  };

  const activePlanCaseIds = useMemo(() => {
    if (!selectedPlanId) return null;
    const plan = testPlans.find(p => p.id === selectedPlanId);
    return plan ? new Set(plan.caseIds) : null;
  }, [selectedPlanId, testPlans]);

  // Keyboard shortcuts handler
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      const state = useStore.getState();
      const { selectedNodeId, editingNodeId, addNode, addSiblingNode, deleteNode, setEditingNodeId } = state;
      if (editingNodeId) return;
      if (!selectedNodeId) return;
      const target = e.target as HTMLElement;
      if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
        return;
      }

      switch (e.key) {
        case 'Tab':
          e.preventDefault();
          e.stopPropagation();
          addNode(selectedNodeId);
          break;
        case 'Enter':
          e.preventDefault();
          e.stopPropagation();
          addSiblingNode(selectedNodeId);
          break;
        case 'Backspace':
        case 'Delete':
          e.preventDefault();
          e.stopPropagation();
          deleteNode(selectedNodeId);
          break;
        case ' ':
        case 'F2':
          e.preventDefault();
          e.stopPropagation();
          setEditingNodeId(selectedNodeId);
          break;
        case 'Escape':
          e.preventDefault();
          e.stopPropagation();
          setEditingNodeId(null);
          break;
        default:
          break;
      }
    };
    window.addEventListener('keydown', handleKeyDown, true);
    return () => window.removeEventListener('keydown', handleKeyDown, true);
  }, []);

  const { nodes, edges } = useMemo(() => {
    const initialNodes: Node[] = [];
    const initialEdges: Edge[] = [];
    const verticalSpacing = 90;
    const horizontalSpacing = 280;

    const getSubtreeHeight = (node: TestCaseNode): number => {
      if (!node.children || node.children.length === 0 || node.isExpanded === false) {
        return verticalSpacing;
      }
      return node.children.reduce((acc, child) => acc + getSubtreeHeight(child), 0);
    };

    const filterTree = (nodes: TestCaseNode[]): TestCaseNode[] => {
      if (!activePlanCaseIds) return nodes;
      return nodes
        .map(node => {
          const children = node.children ? filterTree(node.children) : [];
          const isInPlan = activePlanCaseIds.has(node.id);
          if (isInPlan || children.length > 0) {
            return { ...node, children };
          }
          return null;
        })
        .filter((n): n is TestCaseNode => n !== null);
    };

    const tree = filterTree(testCases);
     const filteredTestCases = (() => {
      if (executionMode) {
        // If in execution mode but plan not loaded/ready, show nothing instead of everything
        if (!activePlanCaseIds) return [];
        return tree;
      }
      if (!selectedModuleId) return []; // Focus mode: show nothing if not selected
      
      const findModuleNode = (nodes: TestCaseNode[]): TestCaseNode | null => {
        for (const node of nodes) {
          if (node.id === selectedModuleId) return node;
          if (node.children) {
            const found = findModuleNode(node.children);
            if (found) return found;
          }
        }
        return null;
      };
      
      const modNode = findModuleNode(tree);
      return modNode ? [modNode] : [];
    })();

    const traverse = (node: TestCaseNode, x: number, y: number, parentId: string | null = null) => {
      const currentId = node.id;
      
      initialNodes.push({
        id: currentId,
        type: 'mindMap',
        data: { node },
        position: { x, y },
      });

      if (parentId) {
        initialEdges.push({
          id: `edge-${parentId}-${currentId}`,
          source: parentId,
          target: currentId,
          type: 'default',
          style: { stroke: '#86909C', strokeWidth: 2 },
        });
      }

      if (node.children && node.isExpanded !== false) {
        const nodeHeight = getSubtreeHeight(node);
        let startY = y - nodeHeight / 2;
        
        node.children.forEach((child) => {
          const childHeight = getSubtreeHeight(child);
          const childY = startY + childHeight / 2;
          traverse(child, x + horizontalSpacing, childY, currentId);
          startY += childHeight;
        });
      }
    };

    filteredTestCases.forEach((rootNode) => {
      // Always center the single root at 0,0 for clean layout
      traverse(rootNode, 0, 0);
    });

    return { nodes: initialNodes, edges: initialEdges };

  }, [testCases, activePlanCaseIds, selectedModuleId]);

  return (
    <div className="mindmap-container" style={{ width: '100%', height: '100%', minHeight: '500px', position: 'relative' }}>
      <ReactFlow
        nodes={nodes}
        edges={edges}
        nodeTypes={nodeTypes}
        onPaneClick={() => {
          setEditingNodeId(null);
          useStore.getState().setSelectedNodeId(null);
          onClearModuleSelection?.();
        }}

        fitView
        fitViewOptions={{ padding: 0.2 }}
        minZoom={0.1}
        maxZoom={2}
        deleteKeyCode={null}
        selectionKeyCode={null}
        multiSelectionKeyCode={null}
      >
        <Background color="#E5E6EB" gap={20} />
        <Controls />
        <Panel position="top-right">
          <div className="map-toolbar glass">
            <button className="tool-btn" onClick={handleAutoLayout}>整理布局</button>
            <button className="tool-btn" onClick={handleExportImage}>导出图片</button>
          </div>
        </Panel>
        <Panel position="bottom-right">
          <div className="shortcuts-hint">
            {!executionMode ? (
              <>
                <div className="shortcut-row"><kbd>Tab</kbd> 添加子节点</div>
                <div className="shortcut-row"><kbd>Enter</kbd> 添加同级</div>
                <div className="shortcut-row"><kbd>Delete</kbd> 删除节点</div>
                <div className="shortcut-row"><kbd>空格/F2</kbd> 编辑文本</div>
              </>
            ) : (
              <div className="shortcut-row" style={{ color: '#165DFF', fontWeight: 600 }}>执行预览模式</div>
            )}
          </div>
        </Panel>
      </ReactFlow>
      <style>{`
        .map-toolbar {
          padding: 6px;
          border-radius: 12px;
          display: flex;
          gap: 6px;
          border: 1px solid var(--border-color);
          box-shadow: var(--shadow-md);
        }
        .tool-btn {
          background: white;
          border: 1px solid #E5E6EB;
          padding: 6px 14px;
          font-size: 13px;
          font-weight: 500;
          border-radius: 8px;
          cursor: pointer;
          transition: all 0.2s;
        }
        .tool-btn:hover {
          background: #F2F3F5;
          border-color: var(--primary);
          color: var(--primary);
        }
        .tool-btn:active {
          transform: scale(0.95);
        }
        .shortcuts-hint {
          background: rgba(255,255,255,0.92);
          backdrop-filter: blur(8px);
          border: 1px solid #E5E6EB;
          border-radius: 8px;
          padding: 8px 12px;
          display: flex;
          flex-direction: column;
          gap: 4px;
        }
        .shortcut-row {
          font-size: 11px;
          color: #86909C;
          display: flex;
          align-items: center;
          gap: 8px;
        }
        .shortcut-row kbd {
          background: #F2F3F5;
          border: 1px solid #E5E6EB;
          border-radius: 4px;
          padding: 1px 6px;
          font-size: 10px;
          font-family: monospace;
          color: #4E5969;
          min-width: 40px;
          text-align: center;
        }
        .react-flow__edge-path {
          stroke: #86909C !important;
          stroke-width: 2 !important;
        }
      `}</style>
    </div>
  );
};

const MindMapView: React.FC<MindMapProps> = (props) => (
  <ReactFlowProvider>
    <MindMapInner {...props} />
  </ReactFlowProvider>
);



export default MindMapView;
