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

interface Point {
  x: number;
  y: number;
  z: number;
  value: number | string;
}

const EmbryoGeneration: React.FC = () => {
  const [cs7Data, setCs7Data] = useState<Point[]>([]);
  const [cs8Data, setCs8Data] = useState<Point[]>([]);
  const [cs75Data, setCs75Data] = useState<Point[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [animationProgress, setAnimationProgress] = useState(0);
  const [isAnimating, setIsAnimating] = useState(false);
  const [animationSpeed, setAnimationSpeed] = useState(2);

  // 加载数据
  useEffect(() => {
    const loadData = async () => {
      setLoading(true);
      setError("");
      try {
        const [cs7Res, cs8Res, cs75Res] = await Promise.all([
          axios.get("http://localhost:5000/api/cell", { params: { stage: "CS7" } }),
          axios.get("http://localhost:5000/api/cell", { params: { stage: "CS8" } }),
          axios.get("http://localhost:5000/api/cell", { params: { stage: "CS7.5" } })
        ]);
        setCs7Data(cs7Res.data.cells);
        setCs8Data(cs8Res.data.cells);
        setCs75Data(cs75Res.data.cells);
      } catch (err: any) {
        if (err.response && err.response.data?.error) {
          setError(err.response.data.error);
        } else {
          setError("Failed to fetch embryo data.");
        }
      } finally {
        setLoading(false);
      }
    };
    loadData();
  }, []);

  // 动画逻辑
  useEffect(() => {
    if (!isAnimating || cs7Data.length === 0 || cs8Data.length === 0 || cs75Data.length === 0) {
      return;
    }
    const duration = 5000 / animationSpeed;
    const startTime = Date.now();
    const animate = () => {
      const elapsed = Date.now() - startTime;
      const progress = Math.min(elapsed / duration, 1);
      setAnimationProgress(progress);
      if (progress < 1) {
        requestAnimationFrame(animate);
      } else {
        setIsAnimating(false);
        setAnimationProgress(1);
      }
    };
    animate();
  }, [isAnimating, cs7Data.length, cs8Data.length, cs75Data.length, animationSpeed]);

  const startAnimation = () => {
    setIsAnimating(true);
    setAnimationProgress(0);
  };
  const resetAnimation = () => {
    setIsAnimating(false);
    setAnimationProgress(0);
  };

  return (
    <div className="page-container">
      <div className="page-header">
        <h1>Embryo Generation</h1>
        <p className="page-description">
          观察胚胎发育过程中的细胞迁移和融合。CS7、CS8、CS7.5点云在同一3D视图中展示，动画模拟细胞从两侧汇聚到中间。
        </p>
      </div>
      <div className="page-content">
        <div className="control-panel" style={{
          display: "flex",
          alignItems: "center",
          gap: "2rem",
          marginBottom: "2rem",
          padding: "1rem",
          backgroundColor: "var(--bg-secondary)",
          borderRadius: "8px",
          flexWrap: "wrap"
        }}>
          <button
            onClick={startAnimation}
            disabled={isAnimating || loading}
            style={{
              padding: "0.75rem 1.5rem",
              backgroundColor: "var(--primary-color)",
              color: "white",
              border: "none",
              borderRadius: "6px",
              cursor: isAnimating || loading ? "not-allowed" : "pointer",
              opacity: isAnimating || loading ? 0.6 : 1
            }}
          >
            {isAnimating ? "动画中..." : "开始动画"}
          </button>
          <button
            onClick={resetAnimation}
            disabled={loading}
            style={{
              padding: "0.75rem 1.5rem",
              backgroundColor: "var(--secondary-color)",
              color: "white",
              border: "none",
              borderRadius: "6px",
              cursor: loading ? "not-allowed" : "pointer",
              opacity: loading ? 0.6 : 1
            }}
          >
            重置
          </button>
          <label style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
            动画速度:
            <input
              type="range"
              min="0.5"
              max="3"
              step="0.1"
              value={animationSpeed}
              onChange={(e) => setAnimationSpeed(parseFloat(e.target.value))}
              style={{ width: "100px" }}
            />
            <span>{animationSpeed}x</span>
          </label>
          <div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
            进度: {Math.round(animationProgress * 100)}%
            <div style={{
              width: "100px",
              height: "8px",
              backgroundColor: "var(--bg-tertiary)",
              borderRadius: "4px",
              overflow: "hidden"
            }}>
              <div style={{
                width: `${animationProgress * 100}%`,
                height: "100%",
                backgroundColor: "var(--primary-color)",
                transition: "width 0.1s ease"
              }} />
            </div>
          </div>
        </div>
        {error && <div className="error-message" style={{ marginBottom: "2rem" }}>{error}</div>}
        <UnifiedEmbryoAnimation
          cs7Data={cs7Data}
          cs8Data={cs8Data}
          cs75Data={cs75Data}
          animationProgress={animationProgress}
        />
        <div className="section">
          <h2>使用说明</h2>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))", gap: "2rem", marginTop: "1.5rem" }}>
            <div>
              <h3>🎬 动画控制</h3>
              <p>点击"开始动画"按钮观看CS7.5阶段的细胞生成过程。可以调节动画速度，使用重置按钮重新开始。</p>
            </div>
            <div>
              <h3>🖱️ 交互操作</h3>
              <p>在3D视图中使用鼠标拖拽旋转视角，滚轮缩放，点击数据点查看详细信息。</p>
            </div>
            <div>
              <h3>🎨 颜色编码</h3>
              <p>相同颜色代表相同细胞类型，便于观察细胞在发育过程中的变化。</p>
            </div>
            <div>
              <h3>📊 发育过程</h3>
              <p>观察从CS7和CS8到CS7.5的胚胎发育过程，了解细胞的空间分布变化和类型分化。</p>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

interface UnifiedEmbryoAnimationProps {
  cs7Data: Point[];
  cs8Data: Point[];
  cs75Data: Point[];
  animationProgress: number;
}

const UnifiedEmbryoAnimation: React.FC<UnifiedEmbryoAnimationProps> = ({ cs7Data, cs8Data, cs75Data, animationProgress }) => {
  const containerRef = useRef<HTMLDivElement | null>(null);
  const rendererRef = useRef<THREE.WebGLRenderer | null>(null);
  const sceneRef = useRef<THREE.Scene | null>(null);
  const controlsRef = useRef<any>(null);
  const animationIdRef = useRef<number | null>(null);

  // 颜色映射
  const getColorMap = (allData: Point[]) => {
    const cellTypes = Array.from(new Set(allData.map(p => p.value as string))).sort();
    const colors = [
      '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7',
      '#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9',
      '#F8C471', '#82E0AA', '#F1948A', '#85CDCE', '#D7BDE2',
      '#A9DFBF', '#F9E79F', '#D5A6BD', '#AED6F1', '#E8DAEF'
    ];
    const colorMap = new Map<string, THREE.Color>();
    cellTypes.forEach((type, idx) => {
      colorMap.set(type, new THREE.Color(colors[idx % colors.length]));
    });
    return colorMap;
  };

  useEffect(() => {
    if (!containerRef.current) return;
    // 清理
    if (animationIdRef.current !== null) {
      cancelAnimationFrame(animationIdRef.current);
      animationIdRef.current = null;
    }
    if (rendererRef.current) {
      rendererRef.current.dispose();
      rendererRef.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;
    const camera = new THREE.PerspectiveCamera(30, width / height, 0.1, 1000);
    camera.position.set(0, 0, 30);
    camera.lookAt(0, 0, 0);
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(width, height);
    rendererRef.current = renderer;
    containerRef.current.appendChild(renderer.domElement);
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controlsRef.current = controls;
    // 不添加坐标轴

    // 颜色映射
    const allData = [...cs7Data, ...cs8Data, ...cs75Data];
    const colorMap = getColorMap(allData);

    // 计算所有点的包围盒，自动居中和缩放
    let allPositions: number[] = [];
    cs7Data.forEach(p => { allPositions.push(p.x - 40, p.y, p.z); });
    cs8Data.forEach(p => { allPositions.push(p.x + 40, p.y, p.z); });
    cs75Data.forEach((p, i) => {
      const fromX = i % 2 === 0 ? p.x - 40 : p.x + 40;
      allPositions.push(fromX, p.y, p.z);
      allPositions.push(p.x, p.y, p.z);
    });
    if (allPositions.length > 0) {
      const posArr = new Float32Array(allPositions);
      const box = new THREE.Box3().setFromArray(posArr);
      const center = new THREE.Vector3();
      box.getCenter(center);
      const size = new THREE.Vector3();
      box.getSize(size);
      // 让最大边长适配canvas
      const maxDim = Math.max(size.x, size.y, size.z);
      const fitScale = 32 / maxDim; // 32为经验缩放系数
      scene.position.set(-center.x, -center.y, -center.z);
      scene.scale.set(fitScale, fitScale, fitScale);
    }

    // CS7点云（左，静态）
    if (cs7Data.length > 0) {
      const geometry = new THREE.BufferGeometry();
      const positions: number[] = [];
      const colors: number[] = [];
      cs7Data.forEach((p) => {
        positions.push(p.x - 40, p.y, p.z);
        const c = colorMap.get(p.value as string) || new THREE.Color('#CCCCCC');
        colors.push(c.r, c.g, c.b);
      });
      geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));
      geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
      const material = new THREE.PointsMaterial({
        vertexColors: true,
        size: 0.7,
        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);
        })()
      });
      const points = new THREE.Points(geometry, material);
      scene.add(points);
    }
    // CS8点云（右，静态）
    if (cs8Data.length > 0) {
      const geometry = new THREE.BufferGeometry();
      const positions: number[] = [];
      const colors: number[] = [];
      cs8Data.forEach((p) => {
        positions.push(p.x + 40, p.y, p.z);
        const c = colorMap.get(p.value as string) || new THREE.Color('#CCCCCC');
        colors.push(c.r, c.g, c.b);
      });
      geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));
      geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
      const material = new THREE.PointsMaterial({
        vertexColors: true,
        size: 0.7,
        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);
        })()
      });
      const points = new THREE.Points(geometry, material);
      scene.add(points);
    }
    // CS7.5点云（动画）
    if (cs75Data.length > 0) {
      const geometry = new THREE.BufferGeometry();
      const positions: number[] = [];
      const colors: number[] = [];
      const n = cs75Data.length;
      const moveDuration = 0.4; // 每个点的动画持续时间（占总进度的比例）
      const delayPerPoint = 0.6 / n; // 剩余0.6进度用于错峰
      for (let i = 0; i < n; i++) {
        const to = cs75Data[i];
        const fromX = i % 2 === 0 ? to.x - 40 : to.x + 40;
        const fromY = to.y;
        const fromZ = to.z;
        const delay = i * delayPerPoint;
        let pointProgress = (animationProgress - delay) / moveDuration;
        pointProgress = Math.max(0, Math.min(1, pointProgress));
        const x = fromX + (to.x - fromX) * pointProgress;
        const y = fromY + (to.y - fromY) * pointProgress;
        const z = fromZ + (to.z - fromZ) * pointProgress;
        positions.push(x, y, z);
        const c = colorMap.get(to.value as string) || new THREE.Color('#CCCCCC');
        colors.push(c.r, c.g, c.b);
      }
      geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));
      geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
      const material = new THREE.PointsMaterial({
        vertexColors: true,
        size: 0.7,
        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);
        })()
      });
      const points = new THREE.Points(geometry, material);
      scene.add(points);
    }
    // 渲染循环
    const animate = () => {
      animationIdRef.current = requestAnimationFrame(animate);
      controls.update();
      renderer.render(scene, camera);
    };
    animate();
    // 清理
    return () => {
      if (animationIdRef.current !== null) {
        cancelAnimationFrame(animationIdRef.current);
      }
      if (controlsRef.current) {
        controlsRef.current.dispose();
      }
      if (rendererRef.current) {
        rendererRef.current.dispose();
      }
    };
  }, [cs7Data, cs8Data, cs75Data, animationProgress]);

  return <div ref={containerRef} className="point-cloud-container" style={{ width: "100%", height: "700px", minHeight: 600 }} />;
};

export default EmbryoGeneration;