import { useState, useRef, useEffect, useCallback } from 'react';
import { motion } from 'framer-motion';
import { RefreshCw, ChevronRight } from 'lucide-react';

export const BYPASS_KEY = 'bypass-human-check';
export const VERIFIED_KEY = 'human-verified';

interface HumanVerificationProps {
  onVerified: () => void;
}

const HumanVerification = ({ onVerified }: HumanVerificationProps) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [isDragging, setIsDragging] = useState(false);
  const [sliderX, setSliderX] = useState(0);
  const [isVerified, setIsVerified] = useState(false);
  const [error, setError] = useState(false);
  const [puzzleImage, setPuzzleImage] = useState<ImageData | null>(null);
  const [targetX, setTargetX] = useState(0);
  const trackRef = useRef<HTMLDivElement>(null);

  const CANVAS_WIDTH = 300;
  const CANVAS_HEIGHT = 150;
  const PIECE_WIDTH = 42;
  const PIECE_HEIGHT = 42;
  const NOTCH_SIZE = 10;
  const TOLERANCE = 6;

  // Check for bypass in URL on mount
  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    if (params.has(BYPASS_KEY) || window.location.pathname.includes(BYPASS_KEY)) {
      localStorage.setItem(VERIFIED_KEY, 'true');
      onVerified();
    }
  }, [onVerified]);

  const drawPuzzlePiecePath = (ctx: CanvasRenderingContext2D, x: number, y: number) => {
    const w = PIECE_WIDTH;
    const h = PIECE_HEIGHT;
    const n = NOTCH_SIZE;

    ctx.beginPath();
    ctx.moveTo(x, y);
    // Top edge
    ctx.lineTo(x + w, y);
    // Right edge with notch
    ctx.lineTo(x + w, y + h * 0.35);
    ctx.arc(x + w + n * 0.5, y + h * 0.5, n, -Math.PI * 0.5, Math.PI * 0.5, false);
    ctx.lineTo(x + w, y + h);
    // Bottom edge
    ctx.lineTo(x, y + h);
    // Left edge
    ctx.lineTo(x, y);
    ctx.closePath();
  };

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

    // Get theme color
    const computedStyle = getComputedStyle(document.documentElement);
    const primaryHsl = computedStyle.getPropertyValue('--primary').trim();
    const hslParts = primaryHsl.split(' ');
    const h = parseFloat(hslParts[0]) || 120;
    const s = parseFloat(hslParts[1]) || 100;
    const l = parseFloat(hslParts[2]) || 50;

    // Clear canvas
    ctx.fillStyle = '#0d0d0d';
    ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);

    // Create a visually interesting background pattern
    // Gradient base
    const gradient = ctx.createLinearGradient(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    gradient.addColorStop(0, `hsla(${h}, ${s}%, ${l * 0.15}%, 1)`);
    gradient.addColorStop(0.5, `hsla(${h}, ${s}%, ${l * 0.08}%, 1)`);
    gradient.addColorStop(1, `hsla(${h}, ${s}%, ${l * 0.12}%, 1)`);
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);

    // Draw circuit-like patterns
    ctx.strokeStyle = `hsla(${h}, ${s}%, ${l}%, 0.15)`;
    ctx.lineWidth = 1;
    for (let i = 0; i < 12; i++) {
      const startX = Math.random() * CANVAS_WIDTH;
      const startY = Math.random() * CANVAS_HEIGHT;
      ctx.beginPath();
      ctx.moveTo(startX, startY);
      // Draw horizontal then vertical line
      const midX = startX + (Math.random() - 0.5) * 80;
      ctx.lineTo(midX, startY);
      ctx.lineTo(midX, startY + (Math.random() - 0.5) * 60);
      ctx.stroke();
      // Draw node dots
      ctx.fillStyle = `hsla(${h}, ${s}%, ${l}%, 0.3)`;
      ctx.beginPath();
      ctx.arc(startX, startY, 2, 0, Math.PI * 2);
      ctx.fill();
    }

    // Matrix-style falling characters with distortion to prevent AI detection
    const chars = '01アイウエオカキクケコ田由甲申電网ЖДЯ§€¥£';
    for (let i = 0; i < 50; i++) {
      const cx = Math.random() * CANVAS_WIDTH;
      const cy = Math.random() * CANVAS_HEIGHT;
      const fontSize = 8 + Math.random() * 8;
      const rotation = (Math.random() - 0.5) * 0.6;
      const opacity = 0.08 + Math.random() * 0.2;
      const skewX = (Math.random() - 0.5) * 0.3;
      
      ctx.save();
      ctx.translate(cx, cy);
      ctx.rotate(rotation);
      ctx.transform(1, 0, skewX, 1, 0, 0); // Skew
      ctx.font = `${fontSize}px monospace`;
      ctx.fillStyle = `hsla(${h}, ${s}%, ${l}%, ${opacity})`;
      ctx.fillText(chars[Math.floor(Math.random() * chars.length)], 0, 0);
      ctx.restore();
    }

    // Add noise pixels to confuse OCR
    const imageData = ctx.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    const data = imageData.data;
    for (let i = 0; i < data.length; i += 4) {
      if (Math.random() < 0.03) {
        const noise = Math.random() * 40;
        data[i] += noise;     // R
        data[i + 1] += noise; // G
        data[i + 2] += noise; // B
      }
    }
    ctx.putImageData(imageData, 0, 0);

    // Interference lines crossing through characters
    ctx.strokeStyle = `hsla(${h}, ${s}%, ${l}%, 0.08)`;
    ctx.lineWidth = 1;
    for (let i = 0; i < 8; i++) {
      ctx.beginPath();
      ctx.moveTo(0, Math.random() * CANVAS_HEIGHT);
      ctx.bezierCurveTo(
        CANVAS_WIDTH * 0.3, Math.random() * CANVAS_HEIGHT,
        CANVAS_WIDTH * 0.7, Math.random() * CANVAS_HEIGHT,
        CANVAS_WIDTH, Math.random() * CANVAS_HEIGHT
      );
      ctx.stroke();
    }

    // Generate target position (where the piece should go)
    const newTargetX = Math.floor(Math.random() * (CANVAS_WIDTH - PIECE_WIDTH - 100)) + 80;
    const targetY = (CANVAS_HEIGHT - PIECE_HEIGHT) / 2;
    setTargetX(newTargetX);

    // Draw the target slot (dark cutout with glow)
    ctx.save();
    drawPuzzlePiecePath(ctx, newTargetX, targetY);
    ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
    ctx.fill();
    ctx.strokeStyle = `hsla(${h}, ${s}%, ${l}%, 0.5)`;
    ctx.lineWidth = 1.5;
    ctx.stroke();
    
    // Inner shadow effect
    ctx.shadowColor = `hsla(${h}, ${s}%, ${l}%, 0.3)`;
    ctx.shadowBlur = 4;
    ctx.shadowOffsetX = 0;
    ctx.shadowOffsetY = 0;
    ctx.stroke();
    ctx.restore();

    // Extract the puzzle piece image from a slightly different position for variation
    const extractX = 10;
    const extractY = targetY;
    
    // Create puzzle piece appearance
    const pieceCanvas = document.createElement('canvas');
    pieceCanvas.width = PIECE_WIDTH + NOTCH_SIZE + 4;
    pieceCanvas.height = PIECE_HEIGHT + 4;
    const pieceCtx = pieceCanvas.getContext('2d');
    if (pieceCtx) {
      // Draw piece background with pattern
      pieceCtx.fillStyle = `hsla(${h}, ${s}%, ${l}%, 0.9)`;
      drawPuzzlePiecePath(pieceCtx, 2, 2);
      pieceCtx.fill();
      
      // Add texture
      pieceCtx.strokeStyle = `hsla(${h}, ${s}%, ${l * 1.3}%, 0.6)`;
      pieceCtx.lineWidth = 1.5;
      drawPuzzlePiecePath(pieceCtx, 2, 2);
      pieceCtx.stroke();

      // Inner pattern
      pieceCtx.strokeStyle = 'rgba(0, 0, 0, 0.3)';
      pieceCtx.lineWidth = 1;
      pieceCtx.strokeRect(8, 8, PIECE_WIDTH - 12, PIECE_HEIGHT - 12);
      
      // Arrow indicator
      pieceCtx.fillStyle = 'rgba(0, 0, 0, 0.5)';
      pieceCtx.beginPath();
      const arrowCx = PIECE_WIDTH / 2 + 2;
      const arrowCy = PIECE_HEIGHT / 2 + 2;
      pieceCtx.moveTo(arrowCx - 6, arrowCy - 5);
      pieceCtx.lineTo(arrowCx + 6, arrowCy);
      pieceCtx.lineTo(arrowCx - 6, arrowCy + 5);
      pieceCtx.closePath();
      pieceCtx.fill();

      setPuzzleImage(pieceCtx.getImageData(0, 0, pieceCanvas.width, pieceCanvas.height));
    }

    // Draw scanlines
    ctx.fillStyle = 'rgba(0, 0, 0, 0.06)';
    for (let y = 0; y < CANVAS_HEIGHT; y += 2) {
      ctx.fillRect(0, y, CANVAS_WIDTH, 1);
    }

    // Border
    ctx.strokeStyle = `hsla(${h}, ${s}%, ${l}%, 0.4)`;
    ctx.lineWidth = 2;
    ctx.strokeRect(1, 1, CANVAS_WIDTH - 2, CANVAS_HEIGHT - 2);

    setSliderX(0);
    setError(false);
    setIsVerified(false);
  }, []);

  useEffect(() => {
    generatePuzzle();
  }, [generatePuzzle]);

  // Draw the puzzle piece at current position
  useEffect(() => {
    if (!canvasRef.current || !puzzleImage) return;
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    // Regenerate base image
    generatePuzzle();
  }, []);

  // Redraw canvas with piece at current slider position
  const redrawWithPiece = useCallback(() => {
    if (!canvasRef.current || !puzzleImage) return;
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    // Get theme color
    const computedStyle = getComputedStyle(document.documentElement);
    const primaryHsl = computedStyle.getPropertyValue('--primary').trim();
    const hslParts = primaryHsl.split(' ');
    const h = parseFloat(hslParts[0]) || 120;
    const s = parseFloat(hslParts[1]) || 100;
    const l = parseFloat(hslParts[2]) || 50;

    // Clear and redraw background
    ctx.fillStyle = '#0d0d0d';
    ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);

    const gradient = ctx.createLinearGradient(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    gradient.addColorStop(0, `hsla(${h}, ${s}%, ${l * 0.15}%, 1)`);
    gradient.addColorStop(0.5, `hsla(${h}, ${s}%, ${l * 0.08}%, 1)`);
    gradient.addColorStop(1, `hsla(${h}, ${s}%, ${l * 0.12}%, 1)`);
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);

    // Circuit patterns
    ctx.strokeStyle = `hsla(${h}, ${s}%, ${l}%, 0.15)`;
    ctx.lineWidth = 1;
    for (let i = 0; i < 12; i++) {
      const startX = (i * 37) % CANVAS_WIDTH;
      const startY = (i * 23) % CANVAS_HEIGHT;
      ctx.beginPath();
      ctx.moveTo(startX, startY);
      ctx.lineTo(startX + 40, startY);
      ctx.lineTo(startX + 40, startY + 30);
      ctx.stroke();
    }

    // Matrix chars with distortion
    const chars = '01アイウエオ田由甲申ЖДЯ§€¥';
    for (let i = 0; i < 35; i++) {
      const fontSize = 8 + (i % 5) * 2;
      const rotation = ((i % 7) - 3) * 0.15;
      const opacity = 0.08 + (i % 4) * 0.05;
      ctx.save();
      ctx.translate((i * 17) % CANVAS_WIDTH, (i * 13) % CANVAS_HEIGHT);
      ctx.rotate(rotation);
      ctx.font = `${fontSize}px monospace`;
      ctx.fillStyle = `hsla(${h}, ${s}%, ${l}%, ${opacity})`;
      ctx.fillText(chars[i % chars.length], 0, 0);
      ctx.restore();
    }

    // Add noise and interference
    const imgData = ctx.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    for (let i = 0; i < imgData.data.length; i += 4) {
      if (Math.random() < 0.025) {
        imgData.data[i] += Math.random() * 30;
        imgData.data[i + 1] += Math.random() * 30;
        imgData.data[i + 2] += Math.random() * 30;
      }
    }
    ctx.putImageData(imgData, 0, 0);

    const pieceY = (CANVAS_HEIGHT - PIECE_HEIGHT) / 2;

    // Draw target slot
    ctx.save();
    drawPuzzlePiecePath(ctx, targetX, pieceY);
    ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
    ctx.fill();
    ctx.strokeStyle = `hsla(${h}, ${s}%, ${l}%, 0.5)`;
    ctx.lineWidth = 1.5;
    ctx.stroke();
    ctx.restore();

    // Calculate piece position from slider
    const maxSlide = trackRef.current ? trackRef.current.clientWidth - 48 : 240;
    const pieceX = (sliderX / maxSlide) * (CANVAS_WIDTH - PIECE_WIDTH - NOTCH_SIZE - 10) + 5;

    // Draw draggable piece with shadow/glow
    ctx.save();
    
    let pieceColor = `hsla(${h}, ${s}%, ${l}%, 0.95)`;
    let borderColor = `hsla(${h}, ${s}%, ${l * 1.2}%, 1)`;
    let glowColor = `hsla(${h}, ${s}%, ${l}%, 0.6)`;
    
    if (error) {
      pieceColor = 'hsla(0, 70%, 50%, 0.95)';
      borderColor = 'hsl(0, 70%, 60%)';
      glowColor = 'hsla(0, 70%, 50%, 0.6)';
    } else if (isVerified) {
      pieceColor = 'hsla(142, 76%, 40%, 0.95)';
      borderColor = 'hsl(142, 76%, 55%)';
      glowColor = 'hsla(142, 76%, 40%, 0.6)';
    }

    // Glow effect
    ctx.shadowColor = glowColor;
    ctx.shadowBlur = 12;
    
    drawPuzzlePiecePath(ctx, pieceX, pieceY);
    ctx.fillStyle = pieceColor;
    ctx.fill();
    ctx.strokeStyle = borderColor;
    ctx.lineWidth = 2;
    ctx.stroke();
    
    ctx.shadowBlur = 0;

    // Inner pattern on piece
    ctx.strokeStyle = 'rgba(0, 0, 0, 0.3)';
    ctx.lineWidth = 1;
    ctx.strokeRect(pieceX + 6, pieceY + 6, PIECE_WIDTH - 12, PIECE_HEIGHT - 12);

    // Arrow
    ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
    ctx.beginPath();
    const arrowX = pieceX + PIECE_WIDTH / 2;
    const arrowY = pieceY + PIECE_HEIGHT / 2;
    ctx.moveTo(arrowX - 5, arrowY - 4);
    ctx.lineTo(arrowX + 5, arrowY);
    ctx.lineTo(arrowX - 5, arrowY + 4);
    ctx.closePath();
    ctx.fill();
    ctx.restore();

    // Scanlines
    ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
    for (let y = 0; y < CANVAS_HEIGHT; y += 2) {
      ctx.fillRect(0, y, CANVAS_WIDTH, 1);
    }

    // Border
    ctx.strokeStyle = `hsla(${h}, ${s}%, ${l}%, 0.4)`;
    ctx.lineWidth = 2;
    ctx.strokeRect(1, 1, CANVAS_WIDTH - 2, CANVAS_HEIGHT - 2);

  }, [sliderX, error, isVerified, targetX, puzzleImage]);

  useEffect(() => {
    redrawWithPiece();
  }, [sliderX, error, isVerified, redrawWithPiece]);

  const handleMouseDown = () => {
    setIsDragging(true);
    setError(false);
  };

  const handleMouseMove = (e: React.MouseEvent) => {
    if (!isDragging || !trackRef.current) return;
    const rect = trackRef.current.getBoundingClientRect();
    const x = Math.max(0, Math.min(e.clientX - rect.left - 24, rect.width - 48));
    setSliderX(x);
  };

  const handleMouseUp = () => {
    if (!isDragging || !trackRef.current) return;
    setIsDragging(false);

    const maxSlide = trackRef.current.clientWidth - 48;
    const pieceX = (sliderX / maxSlide) * (CANVAS_WIDTH - PIECE_WIDTH - NOTCH_SIZE - 10) + 5;
    const diff = Math.abs(pieceX - targetX);

    if (diff <= TOLERANCE) {
      setIsVerified(true);
      localStorage.setItem(VERIFIED_KEY, 'true');
      setTimeout(() => onVerified(), 500);
    } else {
      setError(true);
      setTimeout(() => {
        setSliderX(0);
        setError(false);
      }, 350);
    }
  };

  const handleTouchStart = () => {
    setIsDragging(true);
    setError(false);
  };

  const handleTouchMove = (e: React.TouchEvent) => {
    if (!isDragging || !trackRef.current) return;
    const touch = e.touches[0];
    const rect = trackRef.current.getBoundingClientRect();
    const x = Math.max(0, Math.min(touch.clientX - rect.left - 24, rect.width - 48));
    setSliderX(x);
  };

  return (
    <div className="fixed inset-0 z-[100] bg-background flex items-center justify-center p-4">
      <motion.div
        initial={{ opacity: 0, scale: 0.95 }}
        animate={{ opacity: 1, scale: 1 }}
        className="w-full max-w-[340px] space-y-3"
      >
        {/* Header */}
        <div className="text-center border border-primary/40 bg-primary/5 py-2.5 px-4">
          <div className="text-primary font-mono text-sm tracking-wider font-bold">
            SECURITY VERIFICATION
          </div>
          <div className="text-primary/50 font-mono text-[10px]">
            ANTI-BOT PROTOCOL v3.0
          </div>
        </div>

        {/* Canvas puzzle area */}
        <div className="border border-primary/30 overflow-hidden">
          <canvas
            ref={canvasRef}
            width={CANVAS_WIDTH}
            height={CANVAS_HEIGHT}
            className="w-full block"
          />
        </div>

        {/* Slider track */}
        <div
          ref={trackRef}
          className={`relative h-11 border-2 ${
            error ? 'border-destructive bg-destructive/10' :
            isVerified ? 'border-green-500 bg-green-500/10' :
            'border-primary/30 bg-primary/5'
          } transition-colors duration-200 cursor-pointer select-none`}
          onMouseMove={handleMouseMove}
          onMouseUp={handleMouseUp}
          onMouseLeave={handleMouseUp}
          onTouchMove={handleTouchMove}
          onTouchEnd={handleMouseUp}
        >
          {/* Track label */}
          <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
            <span className={`font-mono text-xs tracking-wide ${
              isVerified ? 'text-green-500' : 'text-primary/30'
            }`}>
              {isVerified ? '[ VERIFIED ]' : 'DRAG TO COMPLETE PUZZLE'}
            </span>
          </div>

          {/* Slider handle */}
          <motion.div
            className={`absolute top-0 h-full w-12 flex items-center justify-center cursor-grab active:cursor-grabbing ${
              error ? 'bg-destructive' :
              isVerified ? 'bg-green-500' :
              'bg-primary'
            } transition-colors duration-200`}
            style={{ left: sliderX }}
            onMouseDown={handleMouseDown}
            onTouchStart={handleTouchStart}
            animate={error ? { x: [0, -4, 4, -4, 4, 0] } : {}}
            transition={{ duration: 0.2 }}
          >
            <ChevronRight className="w-5 h-5 text-background" />
          </motion.div>
        </div>

        {/* Controls */}
        <div className="flex justify-end">
          <button
            onClick={generatePuzzle}
            className="flex items-center gap-1.5 text-xs font-mono text-primary/60 hover:text-primary transition-colors"
          >
            <RefreshCw className="w-3 h-3" />
            Refresh
          </button>
        </div>
      </motion.div>
    </div>
  );
};

export default HumanVerification;