"use client";

import { useEffect, useRef } from "react";

interface Landmark {
  x: number;
  y: number;
  z: number;
  visibility: number;
}

interface AnimatedSkeletonProps {
  landmarks: Landmark[] | null;
  width?: number;
  height?: number;
}

// Neon color palette (Just Dance style)
const NEON_COLORS = {
  primary: "#FF6B35",    // Neon Orange
  secondary: "#FF1493", // Hot Pink
  accent: "#00FFFF",    // Cyan
  highlight: "#FFD700", // Gold
};

// Body part definitions for filled shapes
const BODY_PARTS = {
  torso: [11, 12, 24, 23], // Shoulders to hips
  leftArm: [11, 13, 15],   // Left shoulder, elbow, wrist
  rightArm: [12, 14, 16],  // Right shoulder, elbow, wrist
  leftLeg: [23, 25, 27],   // Left hip, knee, ankle
  rightLeg: [24, 26, 28],  // Right hip, knee, ankle
};

// Connection definitions for limbs
const LIMB_CONNECTIONS = [
  { start: 11, end: 13, color: NEON_COLORS.primary },   // Left upper arm
  { start: 13, end: 15, color: NEON_COLORS.secondary }, // Left forearm
  { start: 12, end: 14, color: NEON_COLORS.primary },   // Right upper arm
  { start: 14, end: 16, color: NEON_COLORS.secondary }, // Right forearm
  { start: 23, end: 25, color: NEON_COLORS.accent },    // Left thigh
  { start: 25, end: 27, color: NEON_COLORS.highlight }, // Left shin
  { start: 24, end: 26, color: NEON_COLORS.accent },    // Right thigh
  { start: 26, end: 28, color: NEON_COLORS.highlight }, // Right shin
];

export default function AnimatedSkeleton({
  landmarks,
  width = 600,
  height = 800,
}: AnimatedSkeletonProps) {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    if (!landmarks || !canvasRef.current) return;

    const canvas = canvasRef.current;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    // Set canvas size
    canvas.width = width;
    canvas.height = height;

    // Clear canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Calculate scale factor based on canvas size (reference: 600x800)
    const scaleFactor = Math.min(width / 600, height / 800);

    // Enable shadows for glow effect
    ctx.shadowBlur = 20 * scaleFactor;

    // Helper function to calculate depth scale (z closer = larger)
    const getDepthScale = (z: number): number => {
      // z ranges roughly from -1 (far) to 1 (close)
      // Map to scale: far = 0.7, close = 1.3
      return 1.0 + z * 0.3;
    };

    // Helper function to get depth-based brightness
    const getDepthBrightness = (z: number): number => {
      // Closer = brighter, farther = dimmer
      return 0.7 + z * 0.3;
    };

    // Helper function to draw a rounded cylindrical limb with depth
    const drawGlowingLimb = (
      start: Landmark,
      end: Landmark,
      color: string,
      baseThickness: number = 25
    ) => {
      if (start.visibility < 0.5 || end.visibility < 0.5) return;

      const startX = start.x * canvas.width;
      const startY = start.y * canvas.height;
      const endX = end.x * canvas.width;
      const endY = end.y * canvas.height;

      // Calculate average z for depth
      const avgZ = (start.z + end.z) / 2;
      const depthScale = getDepthScale(avgZ);
      const brightness = getDepthBrightness(avgZ);
      const thickness = baseThickness * scaleFactor * depthScale;

      // Calculate perpendicular direction for cylindrical gradient
      const dx = endX - startX;
      const dy = endY - startY;
      const length = Math.sqrt(dx * dx + dy * dy);
      
      if (length === 0) return;

      // Perpendicular vector (rotated 90 degrees)
      const perpX = -dy / length;
      const perpY = dx / length;

      // Calculate midpoint
      const midX = (startX + endX) / 2;
      const midY = (startY + endY) / 2;

      // Add drop shadow for depth (farther = stronger shadow)
      ctx.save();
      ctx.shadowColor = "rgba(0, 0, 0, 0.6)";
      ctx.shadowBlur = 15 * scaleFactor * (1 - avgZ);
      ctx.shadowOffsetX = 5 * scaleFactor * (1 - avgZ);
      ctx.shadowOffsetY = 8 * scaleFactor * (1 - avgZ);

      // Parse color and adjust brightness
      const adjustedColor = adjustColorBrightness(color, brightness);

      // Create cylindrical gradient perpendicular to limb direction
      const halfThickness = thickness / 2;
      const gradientStart = {
        x: midX - perpX * halfThickness,
        y: midY - perpY * halfThickness
      };
      const gradientEnd = {
        x: midX + perpX * halfThickness,
        y: midY + perpY * halfThickness
      };

      // Draw glow layers (multiple passes for intense glow)
      for (let i = 3; i >= 0; i--) {
        ctx.globalAlpha = (0.3 - i * 0.05) * brightness;
        ctx.shadowColor = adjustedColor;
        ctx.shadowBlur = (30 + i * 10) * scaleFactor * depthScale;
        ctx.strokeStyle = adjustedColor;
        ctx.lineWidth = thickness + i * 8 * scaleFactor * depthScale;
        ctx.lineCap = "round";

        ctx.beginPath();
        ctx.moveTo(startX, startY);
        ctx.lineTo(endX, endY);
        ctx.stroke();
      }

      // Create cylindrical gradient for rounded appearance
      const cylGradient = ctx.createLinearGradient(
        gradientStart.x,
        gradientStart.y,
        gradientEnd.x,
        gradientEnd.y
      );

      // Darker on edges, brighter in center (cylinder effect)
      const darkColor = adjustColorBrightness(color, brightness * 0.4);
      const midColor = adjustColorBrightness(color, brightness * 0.85);
      const centerColor = adjustColorBrightness(color, brightness * 1.15);

      cylGradient.addColorStop(0, darkColor);
      cylGradient.addColorStop(0.3, midColor);
      cylGradient.addColorStop(0.5, centerColor);
      cylGradient.addColorStop(0.7, midColor);
      cylGradient.addColorStop(1, darkColor);

      // Draw main limb with cylindrical gradient
      ctx.globalAlpha = brightness;
      ctx.shadowBlur = 15 * scaleFactor * depthScale;
      ctx.strokeStyle = cylGradient;
      ctx.lineWidth = thickness;
      ctx.lineCap = "round";

      ctx.beginPath();
      ctx.moveTo(startX, startY);
      ctx.lineTo(endX, endY);
      ctx.stroke();

      // Add center highlight stripe along the limb
      const highlightGradient = ctx.createLinearGradient(
        gradientStart.x * 0.7 + gradientEnd.x * 0.3,
        gradientStart.y * 0.7 + gradientEnd.y * 0.3,
        gradientStart.x * 0.3 + gradientEnd.x * 0.7,
        gradientStart.y * 0.3 + gradientEnd.y * 0.7
      );
      
      const highlightAlpha = 0.5 * brightness;
      highlightGradient.addColorStop(0, "rgba(255, 255, 255, 0)");
      highlightGradient.addColorStop(0.5, `rgba(255, 255, 255, ${highlightAlpha})`);
      highlightGradient.addColorStop(1, "rgba(255, 255, 255, 0)");

      ctx.strokeStyle = highlightGradient;
      ctx.lineWidth = thickness * 0.35;
      ctx.beginPath();
      ctx.moveTo(startX, startY);
      ctx.lineTo(endX, endY);
      ctx.stroke();

      ctx.restore();
    };

    // Helper function to adjust color brightness
    const adjustColorBrightness = (hexColor: string, brightness: number): string => {
      const r = parseInt(hexColor.slice(1, 3), 16);
      const g = parseInt(hexColor.slice(3, 5), 16);
      const b = parseInt(hexColor.slice(5, 7), 16);
      
      const newR = Math.min(255, Math.floor(r * brightness));
      const newG = Math.min(255, Math.floor(g * brightness));
      const newB = Math.min(255, Math.floor(b * brightness));
      
      return `rgb(${newR}, ${newG}, ${newB})`;
    };

    // Draw torso as filled shape with rounded 3D cylindrical effect
    const drawTorso = () => {
      const indices = BODY_PARTS.torso;
      const points = indices.map((i) => landmarks[i]).filter((l) => l.visibility > 0.5);

      if (points.length === 4) {
        // Calculate average z for torso depth
        const avgZ = points.reduce((sum, p) => sum + p.z, 0) / points.length;
        const brightness = getDepthBrightness(avgZ);
        const depthScale = getDepthScale(avgZ);

        const coords = points.map((p) => ({
          x: p.x * canvas.width,
          y: p.y * canvas.height,
        }));

        ctx.save();

        const centerX = coords.reduce((sum, c) => sum + c.x, 0) / coords.length;
        const centerY = coords.reduce((sum, c) => sum + c.y, 0) / coords.length;

        // Calculate torso width for cylindrical gradient
        const leftX = Math.min(coords[0].x, coords[3].x);
        const rightX = Math.max(coords[1].x, coords[2].x);
        const torsoWidth = Math.abs(rightX - leftX);

        // Need a minimum width to draw torso
        if (torsoWidth < 5 * scaleFactor) {
          ctx.restore();
          return;
        }

        // Create cylindrical gradient (left to right for rounded effect)
        const cylinderGradient = ctx.createLinearGradient(
          leftX,
          centerY,
          rightX,
          centerY
        );
        
        // Simple cylinder effect: dark edges, bright center
        const darkEdge = adjustColorBrightness(NEON_COLORS.secondary, brightness * 0.7);
        const midColor = adjustColorBrightness(NEON_COLORS.primary, brightness * 1.0);
        const brightCenter = adjustColorBrightness(NEON_COLORS.primary, brightness * 1.3);
        
        cylinderGradient.addColorStop(0, darkEdge);
        cylinderGradient.addColorStop(0.2, midColor);
        cylinderGradient.addColorStop(0.5, brightCenter);
        cylinderGradient.addColorStop(0.8, midColor);
        cylinderGradient.addColorStop(1, darkEdge);

        // Draw glow layer
        ctx.globalAlpha = 0.4 * brightness;
        ctx.shadowColor = adjustColorBrightness(NEON_COLORS.primary, brightness);
        ctx.shadowBlur = 50 * scaleFactor * depthScale;
        ctx.fillStyle = cylinderGradient;

        ctx.beginPath();
        ctx.moveTo(coords[0].x, coords[0].y);
        for (let i = 1; i < coords.length; i++) {
          ctx.lineTo(coords[i].x, coords[i].y);
        }
        ctx.closePath();
        ctx.fill();

        // Draw main torso - BRIGHT and SOLID
        ctx.globalAlpha = 1.0;
        ctx.shadowColor = adjustColorBrightness(NEON_COLORS.primary, brightness);
        ctx.shadowBlur = 25 * scaleFactor * depthScale;
        ctx.fillStyle = cylinderGradient;
        ctx.fill();

        // Add white highlight in center - ensure radius is positive
        ctx.shadowBlur = 0;
        const highlightRadius = Math.max(10 * scaleFactor, torsoWidth * 0.4);
        const highlightGradient = ctx.createRadialGradient(
          centerX,
          centerY,
          0,
          centerX,
          centerY,
          highlightRadius
        );
        highlightGradient.addColorStop(0, `rgba(255, 255, 255, ${0.3 * brightness})`);
        highlightGradient.addColorStop(0.6, `rgba(255, 255, 255, ${0.1 * brightness})`);
        highlightGradient.addColorStop(1, "rgba(255, 255, 255, 0)");

        ctx.fillStyle = highlightGradient;
        ctx.fill();

        ctx.restore();
      }
    };

    // Sort limbs by depth (draw farther ones first)
    const limbsWithDepth = LIMB_CONNECTIONS.map(({ start, end, color }) => {
      if (start < landmarks.length && end < landmarks.length) {
        const avgZ = (landmarks[start].z + landmarks[end].z) / 2;
        return { start, end, color, z: avgZ };
      }
      return null;
    }).filter(Boolean).sort((a, b) => (a?.z || 0) - (b?.z || 0));

    // Draw all limbs in depth order
    limbsWithDepth.forEach((limb) => {
      if (limb) {
        drawGlowingLimb(landmarks[limb.start], landmarks[limb.end], limb.color);
      }
    });

    // Draw torso (in middle layer)
    drawTorso();

    // Draw head with intense glow and depth
    const head = landmarks[0]; // Nose
    if (head && head.visibility > 0.5) {
      const x = head.x * canvas.width;
      const y = head.y * canvas.height;
      const headZ = head.z;
      const depthScale = getDepthScale(headZ);
      const brightness = getDepthBrightness(headZ);
      const radius = 35 * scaleFactor * depthScale;

      ctx.save();
      
      // Add drop shadow for depth
      ctx.shadowColor = "rgba(0, 0, 0, 0.7)";
      ctx.shadowBlur = 20 * scaleFactor * (1 - headZ);
      ctx.shadowOffsetX = 6 * scaleFactor * (1 - headZ);
      ctx.shadowOffsetY = 10 * scaleFactor * (1 - headZ);

      // Outer glow layers
      for (let i = 4; i >= 0; i--) {
        ctx.globalAlpha = (0.2 - i * 0.03) * brightness;
        ctx.shadowColor = NEON_COLORS.highlight;
        ctx.shadowBlur = (50 + i * 10) * scaleFactor * depthScale;
        ctx.fillStyle = NEON_COLORS.highlight;

        ctx.beginPath();
        ctx.arc(x, y, radius + i * 6 * scaleFactor * depthScale, 0, 2 * Math.PI);
        ctx.fill();
      }

      // Main head with gradient
      const headGradient = ctx.createRadialGradient(x, y, 0, x, y, radius);
      headGradient.addColorStop(0, adjustColorBrightness("#FFD700", brightness));
      headGradient.addColorStop(0.7, adjustColorBrightness("#FF6B35", brightness));
      headGradient.addColorStop(1, adjustColorBrightness("#FF1493", brightness));

      ctx.globalAlpha = brightness;
      ctx.shadowBlur = 25 * scaleFactor * depthScale;
      ctx.shadowColor = NEON_COLORS.highlight;
      ctx.fillStyle = headGradient;

      ctx.beginPath();
      ctx.arc(x, y, radius, 0, 2 * Math.PI);
      ctx.fill();

      // Add highlight spot (more prominent on closer heads)
      const highlightGradient = ctx.createRadialGradient(
        x - radius * 0.3,
        y - radius * 0.3,
        0,
        x - radius * 0.3,
        y - radius * 0.3,
        radius * 0.6
      );
      const highlightAlpha = 0.8 * brightness;
      highlightGradient.addColorStop(0, `rgba(255, 255, 255, ${highlightAlpha})`);
      highlightGradient.addColorStop(1, "rgba(255, 255, 255, 0)");

      ctx.shadowBlur = 0;
      ctx.fillStyle = highlightGradient;
      ctx.beginPath();
      ctx.arc(x - radius * 0.3, y - radius * 0.3, radius * 0.6, 0, 2 * Math.PI);
      ctx.fill();

      ctx.restore();
    }

    // Reset context
    ctx.globalAlpha = 1;
    ctx.shadowBlur = 0;
  }, [landmarks, width, height]);

  return (
    <canvas
      ref={canvasRef}
      className="w-full h-auto"
      style={{ 
        maxWidth: `${width}px`, 
        aspectRatio: `${width}/${height}`,
        filter: "contrast(1.1) brightness(1.1)", // Enhance the neon effect
      }}
    />
  );
}
