import React, { useEffect, useRef, useState } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

interface Point {
  x: number;
  y: number;
  z: number;
  value: number | string; // 表达强度或细胞类型
}

interface PointCloudProps {
  data: Point[];
  isCategorical?: boolean; // 是否为分类数据（细胞类型）
  autoRotate?: boolean; // 是否自动旋转
}

const PointCloud: React.FC<PointCloudProps> = ({ data, isCategorical = false, autoRotate = false }) => {
  const containerRef = useRef<HTMLDivElement | null>(null);
  const rendererRef = useRef<THREE.WebGLRenderer | null>(null);
  const sceneRef = useRef<THREE.Scene | null>(null);
  const geometryRef = useRef<THREE.BufferGeometry | null>(null);
  const materialRef = useRef<THREE.PointsMaterial | null>(null);
  const animationIdRef = useRef<number | null>(null);
  const controlsRef = useRef<any>(null);
  const [isSpinning, setIsSpinning] = useState(autoRotate);
  const isSpinningRef = useRef(autoRotate);
  const checkboxId = useRef(`spin-checkbox-${Math.random().toString(36).substring(2, 11)}`).current;

  // 为细胞类型生成颜色映射
  const generateCellTypeColors = (cellTypes: string[]) => {
    const colorMap = new Map<string, THREE.Color>();
    const colors = [
      '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7',
      '#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9',
      '#F8C471', '#82E0AA', '#F1948A', '#85CDCE', '#D7BDE2',
      '#A9DFBF', '#F9E79F', '#D5A6BD', '#AED6F1', '#E8DAEF'
    ];

    cellTypes.forEach((type, index) => {
      const colorHex = colors[index % colors.length];
      colorMap.set(type, new THREE.Color(colorHex));
    });

    return colorMap;
  };

  useEffect(() => {
    if (!containerRef.current || data.length === 0) return;

    // 确保ref与当前状态同步
    isSpinningRef.current = isSpinning;

    // 清理之前的资源
    if (animationIdRef.current !== null) {
      cancelAnimationFrame(animationIdRef.current);
      animationIdRef.current = null;
    }

    if (rendererRef.current) {
      rendererRef.current.dispose();
      rendererRef.current = null;
    }

    if (geometryRef.current) {
      geometryRef.current.dispose();
      geometryRef.current = null;
    }

    if (materialRef.current) {
      materialRef.current.dispose();
      materialRef.current = null;
    }

    // 清除旧渲染内容
    while (containerRef.current.firstChild) {
      containerRef.current.removeChild(containerRef.current.firstChild);
    }

    const width = containerRef.current.clientWidth;
    const height = containerRef.current.clientHeight;

    // 初始化场景、相机、渲染器
    const scene = new THREE.Scene();
    sceneRef.current = scene; // 存储scene引用
    const camera = new THREE.PerspectiveCamera(600, width / height, 0.1, 1000);
    camera.position.set(0, 0, -500); // 从左下后方观察，使Z轴指向右上方
    camera.lookAt(0, -100, 0); // 确保相机朝向原点

    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(width, height);
    renderer.setClearColor(0xFFFFFF, 1); // 设置背景为透明
    rendererRef.current = renderer;
    containerRef.current.appendChild(renderer.domElement);

    // 控件
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controlsRef.current = controls;

    // 坐标轴辅助
    const axesHelper = new THREE.AxesHelper(10);
    scene.add(axesHelper);

    // 点云数据
    const geometry = new THREE.BufferGeometry();
    geometryRef.current = geometry;
    const positions: number[] = [];
    const colors: number[] = [];
    const sizes: number[] = [];

    let colorMap: Map<string, THREE.Color> | null = null;
    let cellTypes: string[] = [];
    let maxValue = 0;

    if (isCategorical) {
      // 分类数据处理
      cellTypes = Array.from(new Set(data.map(p => p.value as string))).sort();
      colorMap = generateCellTypeColors(cellTypes);
    } else {
      // 数值数据处理
      maxValue = Math.max(...data.map((p) => p.value as number));
    }

    const color = new THREE.Color();

    data.forEach((point) => {
      positions.push(point.x, point.y, point.z);

      if (isCategorical && colorMap) {
        // 分类数据：按细胞类型着色
        const cellColor = colorMap.get(point.value as string) || new THREE.Color('#CCCCCC');
        colors.push(cellColor.r, cellColor.g, cellColor.b);
        sizes.push(0.8); // 统一大小
      } else {
        // 数值数据：按表达强度着色
        const value = point.value as number;
        color.setHSL(0.6 * (1 - value / maxValue), 1.0, 0.5);
        colors.push(color.r, color.g, color.b);
        sizes.push(0.3 + 1.5 * value / maxValue);
      }
    });

    geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));
    geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
    geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));

    const material = new THREE.PointsMaterial({
      vertexColors: true,
      size: 5,
      sizeAttenuation: true,
      transparent: true,
      alphaTest: 0.5,
      depthWrite: false,
      blending: THREE.NormalBlending,
      map: (() => {
        const canvas = document.createElement('canvas');
        canvas.width = 64;
        canvas.height = 64;
        const ctx = canvas.getContext('2d')!;
        ctx.clearRect(0, 0, 64, 64);
        // 绘制带有alpha渐变的圆形
        const gradient = ctx.createRadialGradient(32, 32, 0, 32, 32, 30);
        gradient.addColorStop(0, 'rgba(255,255,255,1)');
        gradient.addColorStop(0.98, 'rgba(255,255,255,1)');
        gradient.addColorStop(1, 'rgba(255,255,255,0)');
        ctx.beginPath();
        ctx.arc(32, 32, 30, 0, 2 * Math.PI);
        ctx.closePath();
        ctx.fillStyle = gradient;
        ctx.fill();
        return new THREE.CanvasTexture(canvas);
      })()
    });
    materialRef.current = material;
    const points = new THREE.Points(geometry, material);
    scene.add(points);

    // 点击点检测（raycaster）
    const raycaster = new THREE.Raycaster();
    const mouse = new THREE.Vector2();

    const onClick = (event: MouseEvent) => {
      const rect = renderer.domElement.getBoundingClientRect();
      mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
      mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

      raycaster.setFromCamera(mouse, camera);
      const intersects = raycaster.intersectObject(points);

      if (intersects.length > 0) {
        const i = intersects[0].index ?? 0;
        const p = data[i];
        // console.log(`Clicked: x=${p.x}, y=${p.y}, z=${p.z}, value=${p.value}`);

        // if (isCategorical) {
        //   alert(`Cell @ (${p.x.toFixed(1)}, ${p.y.toFixed(1)}, ${p.z.toFixed(1)})\nCell Type: ${p.value}`);
        // } else {
        //   alert(`Cell @ (${p.x.toFixed(1)}, ${p.y.toFixed(1)}, ${p.z.toFixed(1)})\nExpression: ${(p.value as number).toFixed(3)}`);
        // }
      }
    };

    renderer.domElement.addEventListener("click", onClick);

    // 渲染循环
    const animate = () => {
      animationIdRef.current = requestAnimationFrame(animate);

      // 自动旋转逻辑 - 使用 ref 来避免重新创建场景
      if (isSpinningRef.current && autoRotate) {
        scene.rotation.y += 0.002; // 围绕Z轴更慢速旋转
      }

      controls.update();
      renderer.render(scene, camera);
    };
    animate();

    // 只在非分类数据时在3D图形内显示图例
    if (!isCategorical) {
      const legend = document.createElement("div");
      legend.className = "point-cloud-legend";

      // 数值数据图例
      legend.innerHTML = `
        <div class="legend-gradient"></div>
        <div>↑ High</div>
        <div>↓ Low</div>`;

      containerRef.current.appendChild(legend);
    }

    // 清理
    return () => {
      // 停止动画循环
      if (animationIdRef.current !== null) {
        cancelAnimationFrame(animationIdRef.current);
        animationIdRef.current = null;
      }

      // 移除事件监听器
      if (rendererRef.current && rendererRef.current.domElement) {
        rendererRef.current.domElement.removeEventListener("click", onClick);
      }

      // 清理控制器
      if (controlsRef.current) {
        controlsRef.current.dispose();
        controlsRef.current = null;
      }

      // 释放Three.js资源
      if (rendererRef.current) {
        rendererRef.current.dispose();
        rendererRef.current = null;
      }

      if (geometryRef.current) {
        geometryRef.current.dispose();
        geometryRef.current = null;
      }

      if (materialRef.current) {
        materialRef.current.dispose();
        materialRef.current = null;
      }
    };
  }, [data, isCategorical, autoRotate]);

  // 监听autoRotate prop变化，重置旋转状态
  useEffect(() => {
    setIsSpinning(autoRotate);
    isSpinningRef.current = autoRotate;
  }, [autoRotate]);

  // 监听isSpinning状态变化，只更新ref，不重新创建场景
  useEffect(() => {
    isSpinningRef.current = isSpinning;
  }, [isSpinning]);

  // 组件卸载时的最终清理
  useEffect(() => {
    return () => {
      if (animationIdRef.current !== null) {
        cancelAnimationFrame(animationIdRef.current);
      }
      if (controlsRef.current) {
        controlsRef.current.dispose();
      }
      if (rendererRef.current) {
        rendererRef.current.dispose();
      }
      if (geometryRef.current) {
        geometryRef.current.dispose();
      }
      if (materialRef.current) {
        materialRef.current.dispose();
      }
    };
  }, []);

  // 生成图例内容
  const renderLegend = () => {
    if (isCategorical) {
      // 分类数据图例
      const cellTypes = Array.from(new Set(data.map(p => p.value as string))).sort();
      const colorMap = generateCellTypeColors(cellTypes);

      return (
        <div>
          <div style={{ fontWeight: '600', marginBottom: '10px', fontSize: '14px' }}>细胞类型</div>
          <div>
            {cellTypes.map(type => {
              const cellColor = colorMap.get(type);
              if (cellColor) {
                const hexColor = `#${cellColor.getHexString()}`;
                return (
                  <div key={type} style={{ display: 'flex', alignItems: 'center', marginBottom: '5px' }}>
                    <div
                      style={{
                        width: '12px',
                        height: '12px',
                        borderRadius: '50%',
                        backgroundColor: hexColor,
                        marginRight: '8px'
                      }}
                    />
                    <span style={{ fontSize: '12px' }}>{type}</span>
                  </div>
                );
              }
              return null;
            })}
          </div>
        </div>
      );
    } else {
      // 数值数据图例
      return (
        <div>
          <div style={{ fontWeight: '600', marginBottom: '10px', fontSize: '14px' }}>表达强度</div>
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
            <div style={{
              background: 'linear-gradient(to top, hsla(180, 100%, 50%, 1.00), hsla(72, 100%, 50%, 1.00), hsla(0, 100%, 50%, 0.99))',
              width: '20px',
              height: '80px',
              marginBottom: '5px'
            }} />
            <div style={{ fontSize: '11px', color: '#666' }}>
              <div>高</div>
              <div>低</div>
            </div>
          </div>
        </div>
      );
    }
  };

  // 根据isCategorical返回不同的布局
  if (isCategorical) {
    return (
      <div className="point-cloud-visualization-container" style={{
        display: 'flex',
        width: '100%',
        gap: '0',
        height: '100%'
      }}>
        {/* 左侧：3D图形 */}
        <div style={{
          flex: '1',
          position: 'relative',
          height: '100%',
          minHeight: '400px'
        }}>
          <div ref={containerRef} className="point-cloud-container" style={{ width: '100%', height: '100%' }} />
        </div>

        {/* 右侧：图例 */}
        <div style={{
          width: '200px',
          padding: '15px',
          backgroundColor: 'white',
          border: '1px solid #e2e8f0',
          height: 'fit-content',
          maxHeight: '100%',
          overflowY: 'auto',
          flexShrink: 0
        }}>
          {renderLegend()}
        </div>
      </div>
    );
  } else {
    // 原始单列布局
    return (
      <div style={{ position: 'relative', width: '100%', height: '100%' }}>
        <div ref={containerRef} className="point-cloud-container" />
        {autoRotate === true && (
          <div className="spin-control" style={{
            position: 'absolute',
            top: '15px',
            left: '15px',
            background: 'rgba(0, 0, 0, 0.8)',
            color: 'white',
            padding: '10px 15px',
            borderRadius: '8px',
            border: '2px solid #fff',
            fontSize: '14px',
            fontWeight: '500',
            zIndex: 1000,
            display: 'flex',
            alignItems: 'center',
            gap: '8px',
            boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
            pointerEvents: 'auto'
          }}>
            <input
              type="checkbox"
              id={checkboxId}
              checked={isSpinning}
              onChange={(e) => setIsSpinning(e.target.checked)}
              style={{
                cursor: 'pointer',
                width: '16px',
                height: '16px',
                accentColor: '#4ECDC4'
              }}
            />
            <label
              htmlFor={checkboxId}
              style={{
                cursor: 'pointer',
                userSelect: 'none',
                color: 'white',
                fontSize: '14px',
                fontWeight: '500'
              }}
            >
              Auto Spin
            </label>
          </div>
        )}
      </div>
    );
  }
};

export default PointCloud;
