import React, { useEffect, useRef } from 'react';

interface Point {
  x: number;
  y: number;
}

interface ShapeDefinition {
  points: Point[];
  type: 'doc' | 'brain' | 'code' | 'graph';
}

interface DocumentEntity {
  id: number;
  gridX: number;
  gridY: number;
  life: number;
  state: 'forming' | 'flipping' | 'fading';
  flipProgress: number;
  opacity: number;
  shape: ShapeDefinition;
}

const Background: React.FC<{ theme: 'light' | 'dark' }> = ({ theme }) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    let animationFrameId: number;
    let mouseX = -1000;
    let mouseY = -1000;

    // Grid configuration
    const DOT_SPACING = 25; // Denser grid
    const DOT_RADIUS = 1.2;

    // Shape Definitions
    const DOC_SHAPE: ShapeDefinition = {
      type: 'doc',
      points: [
        { x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }, /* corner fold */ { x: 4, y: 1 },
        { x: 0, y: 1 }, { x: 0, y: 2 }, { x: 0, y: 3 }, { x: 0, y: 4 }, { x: 0, y: 5 },
        { x: 4, y: 2 }, { x: 4, y: 3 }, { x: 4, y: 4 }, { x: 4, y: 5 },
        { x: 1, y: 5 }, { x: 2, y: 5 }, { x: 3, y: 5 },
        { x: 3, y: 0 }, { x: 4, y: 1 },
        { x: 1, y: 2 }, { x: 2, y: 2 }, { x: 3, y: 2 },
        { x: 1, y: 4 }, { x: 2, y: 4 }, { x: 3, y: 4 },
      ]
    };

    const CODE_SHAPE: ShapeDefinition = {
      type: 'code',
      points: [
        // <
        { x: 2, y: 0 }, { x: 1, y: 1 }, { x: 0, y: 2 }, { x: 1, y: 3 }, { x: 2, y: 4 },
        // /
        { x: 3, y: 0 }, { x: 3, y: 4 }, // Slash approximation
        // >
        { x: 4, y: 0 }, { x: 5, y: 1 }, { x: 6, y: 2 }, { x: 5, y: 3 }, { x: 4, y: 4 },
      ]
    };

    const BRAIN_SHAPE: ShapeDefinition = {
      type: 'brain',
      points: [
        { x: 2, y: 0 }, { x: 3, y: 0 },
        { x: 1, y: 1 }, { x: 4, y: 1 },
        { x: 0, y: 2 }, { x: 5, y: 2 },
        { x: 0, y: 3 }, { x: 5, y: 3 },
        { x: 1, y: 4 }, { x: 4, y: 4 },
        { x: 2, y: 5 }, { x: 3, y: 5 },
        // Internal connections
        { x: 2, y: 2 }, { x: 3, y: 2 },
        { x: 2, y: 3 }, { x: 3, y: 3 },
      ]
    };

    const GRAPH_SHAPE: ShapeDefinition = {
      type: 'graph',
      points: [
        { x: 0, y: 4 }, { x: 1, y: 3 }, { x: 2, y: 4 }, { x: 3, y: 2 }, { x: 4, y: 3 }, { x: 5, y: 0 },
        // Nodes
        { x: 0, y: 4 }, { x: 2, y: 4 }, { x: 3, y: 2 }, { x: 5, y: 0 }
      ]
    };

    const SHAPES = [DOC_SHAPE, CODE_SHAPE, BRAIN_SHAPE, GRAPH_SHAPE];

    let documents: DocumentEntity[] = [];
    let nextDocId = 0;
    let lastSpawnTime = 0;
    let pulseTime = 0;

    const resize = () => {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    };
    window.addEventListener('resize', resize);
    resize();

    const handleMouseMove = (e: MouseEvent) => {
      mouseX = e.clientX;
      mouseY = e.clientY;
    };
    window.addEventListener('mousemove', handleMouseMove);

    const spawnDocument = () => {
      const cols = Math.ceil(canvas.width / DOT_SPACING);
      const rows = Math.ceil(canvas.height / DOT_SPACING);

      // Spawn shapes only in the edge regions (left 15% or right 15%)
      // to avoid cluttering the content area
      const leftZoneCols = Math.floor(cols * 0.12);
      const rightZoneStart = Math.floor(cols * 0.88);
      
      // Randomly pick left or right edge zone
      const useLeftZone = Math.random() < 0.5;
      const gridX = useLeftZone 
        ? Math.floor(Math.random() * Math.max(1, leftZoneCols - 8))
        : rightZoneStart + Math.floor(Math.random() * Math.max(1, cols - rightZoneStart - 8));
      
      const gridY = Math.floor(Math.random() * (rows - 8));
      const shape = SHAPES[Math.floor(Math.random() * SHAPES.length)];

      documents.push({
        id: nextDocId++,
        gridX,
        gridY,
        life: 0,
        state: 'forming',
        flipProgress: 0,
        opacity: 0,
        shape
      });
    };

    const draw = (timestamp: number) => {
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      const cols = Math.ceil(canvas.width / DOT_SPACING);
      const rows = Math.ceil(canvas.height / DOT_SPACING);

      const baseDotColor = theme === 'dark' ? 'rgba(255, 255, 255, 0.15)' : 'rgba(0, 0, 0, 0.15)';
      const activeDotColor = theme === 'dark' ? 'rgba(99, 102, 241, 0.9)' : 'rgba(79, 70, 229, 0.9)';

      // Pulse wave
      pulseTime += 0.05;

      // Define content-safe zone (center area where text is displayed)
      // Dots will fade out as they approach this zone
      const contentLeft = canvas.width * 0.15;  // Left 15% is safe for dots
      const contentRight = canvas.width * 0.85; // Right 15% is safe for dots
      const contentTop = canvas.height * 0.08;  // Top 8% is safe for dots
      const fadeWidth = 100; // Pixels over which dots fade out

      // Draw background grid with interaction
      ctx.fillStyle = baseDotColor;
      for (let i = 0; i < cols; i++) {
        for (let j = 0; j < rows; j++) {
          const x = i * DOT_SPACING + (DOT_SPACING / 2);
          const y = j * DOT_SPACING + (DOT_SPACING / 2);

          // Calculate opacity based on distance from content zone
          let zoneOpacity = 1;
          
          // Fade out dots as they enter the content area
          if (x > contentLeft && x < contentRight && y > contentTop) {
            // Inside content zone - calculate fade based on distance from edges
            const distFromLeft = x - contentLeft;
            const distFromRight = contentRight - x;
            const distFromTop = y - contentTop;
            
            const minDistX = Math.min(distFromLeft, distFromRight);
            const minDist = Math.min(minDistX, distFromTop);
            
            // Fade out completely within fadeWidth pixels of entering content zone
            zoneOpacity = Math.max(0, 1 - (minDist / fadeWidth));
            
            // Skip drawing dots that are fully transparent
            if (zoneOpacity < 0.01) continue;
          }

          // Mouse interaction
          const dx = x - mouseX;
          const dy = y - mouseY;
          const dist = Math.sqrt(dx * dx + dy * dy);

          let scale = 1;
          let alpha = 1;

          // Mouse ripple
          if (dist < 150) {
            scale = 1 + (150 - dist) / 150; // Scale up to 2x
            alpha = 1 + (150 - dist) / 100;
          }

          // Global pulse wave
          const wave = Math.sin(x * 0.01 + y * 0.01 + pulseTime) * 0.5 + 0.5;
          if (wave > 0.8) {
            scale += 0.2;
            alpha += 0.2;
          }

          ctx.globalAlpha = Math.min(alpha, 0.5) * zoneOpacity; // Apply zone fade
          ctx.beginPath();
          ctx.arc(x, y, DOT_RADIUS * scale, 0, Math.PI * 2);
          ctx.fill();
        }
      }
      ctx.globalAlpha = 1;

      // Update and draw entities
      if (timestamp - lastSpawnTime > 1500) { // Slightly faster spawn
        spawnDocument();
        lastSpawnTime = timestamp;
      }

      documents = documents.filter(doc => doc.state !== 'fading' || doc.opacity > 0.01);

      documents.forEach(doc => {
        if (doc.state === 'forming') {
          doc.opacity += 0.03;
          if (doc.opacity >= 1) {
            doc.opacity = 1;
            doc.state = 'flipping';
          }
        } else if (doc.state === 'flipping') {
          doc.flipProgress += 0.03;
          if (doc.flipProgress >= Math.PI) {
            doc.state = 'fading';
          }
        } else if (doc.state === 'fading') {
          doc.opacity -= 0.03;
        }

        const centerX = doc.gridX + 3; // Approx center

        ctx.fillStyle = activeDotColor;

        doc.shape.points.forEach(pt => {
          const gx = doc.gridX + pt.x;
          const gy = doc.gridY + pt.y;

          let screenX = gx * DOT_SPACING + (DOT_SPACING / 2);
          const screenY = gy * DOT_SPACING + (DOT_SPACING / 2);

          if (doc.state === 'flipping' || doc.state === 'fading') {
            const docCenterScreenX = centerX * DOT_SPACING + (DOT_SPACING / 2);
            const relativeX = screenX - docCenterScreenX;
            const scaleX = Math.cos(doc.flipProgress);
            screenX = docCenterScreenX + (relativeX * scaleX);
          }

          ctx.globalAlpha = doc.opacity;
          ctx.beginPath();
          ctx.arc(screenX, screenY, DOT_RADIUS * 2.8, 0, Math.PI * 2);
          ctx.fill();
          ctx.globalAlpha = 1.0;
        });
      });

      animationFrameId = requestAnimationFrame(draw);
    };

    animationFrameId = requestAnimationFrame(draw);

    return () => {
      window.removeEventListener('resize', resize);
      window.removeEventListener('mousemove', handleMouseMove);
      cancelAnimationFrame(animationFrameId);
    };
  }, [theme]);

  return (
    <canvas
      ref={canvasRef}
      className="fixed top-0 left-0 w-full h-full -z-10 pointer-events-none"
    />
  );
};

export default Background;
