import { useEffect, useRef, useState, useCallback } from "react";
import { Copy, Check } from "lucide-react";
import { Button } from "@/components/ui/button";

const SSH_COMMAND = "ssh portfolio@keshavanand.net";

const CHARACTERS =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#$%^&*()_+-=[]{}|;:,.<>?/\\~`";

interface Particle {
  x: number;
  y: number;
  char: string;
  opacity: number;
  targetX: number;
  targetY: number;
  vx: number;
  vy: number;
  life: number;
  maxLife: number;
  size: number;
  color: string;
}

function ParticleBackground() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const particlesRef = useRef<Particle[]>([]);
  const mouseRef = useRef({
    x: window.innerWidth / 2,
    y: window.innerHeight / 2,
  });
  const animationRef = useRef<number>();
  const frameCountRef = useRef(0);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

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

    const resizeCanvas = () => {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    };

    resizeCanvas();
    window.addEventListener("resize", resizeCanvas);

    const colors = [
      "#a6e3a1",
      "#94e2d5",
      "#89dceb",
      "#74c7ec",
      "#89b4fa",
      "#cba6f7",
    ];

    const createParticle = (
      x: number,
      y: number,
      isAmbient = false
    ): Particle => {
      const angle = Math.random() * Math.PI * 2;
      const speed = isAmbient
        ? Math.random() * 0.5 + 0.2
        : Math.random() * 2 + 1;
      const color = colors[Math.floor(Math.random() * colors.length)];
      const spread = isAmbient ? 200 : 120;
      return {
        x: x + (Math.random() - 0.5) * spread,
        y: y + (Math.random() - 0.5) * spread,
        char: CHARACTERS[Math.floor(Math.random() * CHARACTERS.length)],
        opacity: isAmbient
          ? Math.random() * 0.4 + 0.1
          : Math.random() * 0.8 + 0.2,
        targetX: x,
        targetY: y,
        vx: Math.cos(angle) * speed,
        vy: Math.sin(angle) * speed,
        life: 0,
        maxLife: isAmbient ? Math.random() * 120 + 80 : Math.random() * 80 + 50,
        size: Math.random() * 10 + 12,
        color,
      };
    };

    const handleMouseMove = (e: MouseEvent) => {
      mouseRef.current = { x: e.clientX, y: e.clientY };

      for (let i = 0; i < 5; i++) {
        if (particlesRef.current.length < 400) {
          particlesRef.current.push(createParticle(e.clientX, e.clientY));
        }
      }
    };

    const animate = () => {
      ctx.fillStyle = "#000000";
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      frameCountRef.current++;

      if (
        frameCountRef.current % 3 === 0 &&
        particlesRef.current.length < 400
      ) {
        const mx = mouseRef.current.x;
        const my = mouseRef.current.y;
        particlesRef.current.push(createParticle(mx, my, true));
      }

      if (
        frameCountRef.current % 8 === 0 &&
        particlesRef.current.length < 400
      ) {
        const rx = Math.random() * canvas.width;
        const ry = Math.random() * canvas.height;
        particlesRef.current.push(createParticle(rx, ry, true));
      }

      particlesRef.current = particlesRef.current.filter((p) => {
        p.life++;

        const dx = mouseRef.current.x - p.x;
        const dy = mouseRef.current.y - p.y;
        const distance = Math.sqrt(dx * dx + dy * dy) || 1;

        if (distance < 200) {
          const force = (200 - distance) / 200;
          p.vx += (dx / distance) * force * 0.4;
          p.vy += (dy / distance) * force * 0.4;
        }

        p.vx *= 0.97;
        p.vy *= 0.97;

        p.x += p.vx;
        p.y += p.vy;

        const lifeRatio = p.life / p.maxLife;
        const fadeOpacity =
          lifeRatio < 0.15
            ? lifeRatio * 6.67
            : lifeRatio > 0.7
            ? (1 - lifeRatio) * 3.33
            : 1;

        const distanceOpacity = Math.max(0.15, 1 - distance / 400);
        const finalOpacity = p.opacity * fadeOpacity * distanceOpacity;

        if (finalOpacity > 0.01) {
          ctx.font = `${p.size}px 'JetBrains Mono', monospace`;
          ctx.fillStyle = p.color;
          ctx.globalAlpha = finalOpacity;
          ctx.fillText(p.char, p.x, p.y);
          ctx.globalAlpha = 1;
        }

        return p.life < p.maxLife;
      });

      animationRef.current = requestAnimationFrame(animate);
    };

    window.addEventListener("mousemove", handleMouseMove);
    animate();

    return () => {
      window.removeEventListener("resize", resizeCanvas);
      window.removeEventListener("mousemove", handleMouseMove);
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
    };
  }, []);

  return (
    <canvas
      ref={canvasRef}
      className="fixed inset-0 z-0"
      style={{ background: "#000000" }}
      data-testid="canvas-background"
    />
  );
}

function CommandBox() {
  const [copied, setCopied] = useState(false);
  const [isAnimating, setIsAnimating] = useState(false);
  const [showHowItWorks, setShowHowItWorks] = useState(false);

  useEffect(() => {
    const timer = setTimeout(() => {
      setShowHowItWorks(true);
    }, 2000);
    return () => clearTimeout(timer);
  }, []);

  const handleCopy = useCallback(async () => {
    try {
      await navigator.clipboard.writeText(SSH_COMMAND);
      setIsAnimating(true);
      setCopied(true);
      setTimeout(() => setIsAnimating(false), 150);
      setTimeout(() => setCopied(false), 2000);
    } catch (err) {
      console.error("Failed to copy:", err);
    }
  }, []);

  return (
    <div className="flex flex-col items-center justify-center min-h-screen p-4 sm:p-6">
      <div className="flex-1 flex items-center justify-center w-full max-w-[90vw] md:max-w-none">
        <div
          className="relative z-10 flex flex-wrap items-center justify-center md:justify-start gap-3 md:gap-4 px-4 py-3 md:px-6 md:py-4 rounded-xl border border-border/30 backdrop-blur-sm shadow-2xl w-full md:w-auto overflow-hidden"
          style={{ backgroundColor: "rgba(49, 50, 68, 0.8)" }}
          data-testid="command-box"
        >
          <div className="flex items-center gap-2 md:gap-4 flex-1 md:flex-none justify-center md:justify-start">
            <span
              className="text-muted-foreground shrink-0"
              data-testid="text-prompt"
            >
              $
            </span>
            <code
              className="text-sm sm:text-base md:text-lg lg:text-xl font-mono truncate"
              style={{ color: "#a6e3a1" }}
              data-testid="text-ssh-command"
            >
              {SSH_COMMAND}
            </code>
          </div>
          <Button
            size="icon"
            variant="ghost"
            onClick={handleCopy}
            className={`shrink-0 text-muted-foreground transition-transform duration-150 ${
              isAnimating ? "scale-90" : "scale-100"
            }`}
            aria-label={copied ? "Copied to clipboard" : "Copy SSH command"}
            data-testid="button-copy"
          >
            {copied ? (
              <Check
                className="h-4 w-4 md:h-5 md:w-5"
                style={{ color: "#a6e3a1" }}
              />
            ) : (
              <Copy className="h-4 w-4 md:h-5 md:w-5" />
            )}
          </Button>
        </div>
      </div>

      <div className="pb-12 md:pb-16">
        <a
          href="/docs"
          className={`relative z-10 px-6 py-3 rounded-lg border border-border/20 backdrop-blur-md text-sm font-mono text-muted-foreground transition-all duration-1000 hover:border-primary/40 hover:text-primary hover-elevate ${
            showHowItWorks
              ? "opacity-100 translate-y-0"
              : "opacity-0 translate-y-8"
          }`}
          style={{ backgroundColor: "rgba(30, 30, 46, 0.4)" }}
          data-testid="link-how-it-works"
        >
          How it Works
        </a>
      </div>
    </div>
  );
}

export default function Home() {
  return (
    <div className="min-h-screen w-full relative overflow-hidden bg-black">
      <ParticleBackground />
      <CommandBox />
    </div>
  );
}
