import { ChevronDown } from "lucide-react";

import { MODEL_OPTIONS } from "../constants/models";
import IBMLogo from "./icons/IBMLogo";
import HfLogo from "./icons/HfLogo";

import { useEffect, useRef } from "react";

// Define the structure of our animated dots
interface Dot {
  x: number;
  y: number;
  vx: number;
  vy: number;
  radius: number;
  opacity: number;
}

export const LoadingScreen = ({
  isLoading,
  progress,
  error,
  loadSelectedModel,
  selectedModelId,
  isModelDropdownOpen,
  setIsModelDropdownOpen,
  handleModelSelect,
}: {
  isLoading: boolean;
  progress: number;
  error: string | null;
  loadSelectedModel: () => void;
  selectedModelId: string;
  isModelDropdownOpen: boolean;
  setIsModelDropdownOpen: (isOpen: boolean) => void;
  handleModelSelect: (modelId: string) => void;
}) => {
  const model = MODEL_OPTIONS.find((opt) => opt.id === selectedModelId);
  const canvasRef = useRef<HTMLCanvasElement>(null);

  // Background Animation Effect
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

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

    let animationFrameId: number;
    let dots: Dot[] = [];
    const maxConnectionDistance = 130; // Max distance to draw a line between dots
    const dotSpeed = 0.3; // How fast dots move

    const setup = () => {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      dots = [];
      // Adjust dot density based on screen area
      const numDots = Math.floor((canvas.width * canvas.height) / 20000);

      for (let i = 0; i < numDots; ++i) {
        dots.push({
          x: Math.random() * canvas.width,
          y: Math.random() * canvas.height,
          vx: (Math.random() - 0.5) * dotSpeed, // Random horizontal velocity
          vy: (Math.random() - 0.5) * dotSpeed, // Random vertical velocity
          radius: Math.random() * 1.5 + 0.5,
          opacity: Math.random() * 0.5 + 0.2,
        });
      }
    };

    const draw = () => {
      if (!ctx) return;
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // 1. Update and draw dots
      dots.forEach((dot) => {
        // Update position
        dot.x += dot.vx;
        dot.y += dot.vy;

        // Bounce off edges
        if (dot.x <= 0 || dot.x >= canvas.width) dot.vx *= -1;
        if (dot.y <= 0 || dot.y >= canvas.height) dot.vy *= -1;

        // Draw dot
        ctx.beginPath();
        ctx.arc(dot.x, dot.y, dot.radius, 0, Math.PI * 2);
        ctx.fillStyle = `rgba(255, 255, 255, ${dot.opacity})`;
        ctx.fill();
      });

      // 2. Draw connecting lines
      ctx.lineWidth = 0.5; // Use a thin line for connections
      for (let i = 0; i < dots.length; i++) {
        for (let j = i + 1; j < dots.length; j++) {
          const dot1 = dots[i];
          const dot2 = dots[j];
          const dx = dot1.x - dot2.x;
          const dy = dot1.y - dot2.y;
          const distance = Math.sqrt(dx * dx + dy * dy);

          // If dots are close enough, draw a line
          if (distance < maxConnectionDistance) {
            // Calculate opacity based on distance (closer = more opaque)
            const opacity = 1 - distance / maxConnectionDistance;
            ctx.strokeStyle = `rgba(255, 255, 255, ${opacity * 0.3})`; // Faint white lines
            ctx.beginPath();
            ctx.moveTo(dot1.x, dot1.y);
            ctx.lineTo(dot2.x, dot2.y);
            ctx.stroke();
          }
        }
      }

      animationFrameId = requestAnimationFrame(draw);
    };

    const handleResize = () => {
      cancelAnimationFrame(animationFrameId);
      setup();
      draw();
    };

    setup();
    draw();

    window.addEventListener("resize", handleResize);

    return () => {
      window.removeEventListener("resize", handleResize);
      cancelAnimationFrame(animationFrameId);
    };
  }, []);

  return (
    <div className="relative flex flex-col items-center justify-center h-screen bg-gradient-to-br from-[#031b4e] via-[#06183d] to-[#010409] text-gray-100 text-[16px] md:text-[17px] p-8 overflow-hidden">
      {/* Background Canvas for Animation */}
      <canvas
        ref={canvasRef}
        className="absolute top-0 left-0 w-full h-full z-0"
      />

      {/* Vignette Overlay */}
      <div className="absolute top-0 left-0 w-full h-full z-10 bg-[radial-gradient(ellipse_at_center,_rgba(3,27,78,0)_30%,_rgba(1,4,9,0.85)_95%)]"></div>

      {/* Main Content */}
      <div className="relative z-20 max-w-3xl w-full flex flex-col items-center bg-white/5 border border-white/10 backdrop-blur-xl rounded-3xl p-10 shadow-[0_35px_65px_rgba(3,27,78,0.55)] space-y-8">
        <div className="flex items-center justify-center gap-6 text-5xl md:text-6xl">
          <a
            href="https://huggingface.co/ibm-granite"
            target="_blank"
            rel="noopener noreferrer"
            title="IBM Granite"
          >
            <div className="size-24 md:size-28 bg-blue-500 rounded-sm p-2 flex items-center justify-center">
              <IBMLogo className="text-white" />
            </div>
          </a>
          <span className="text-[#78a9ff]">×</span>
          <a
            href="https://huggingface.co/docs/transformers.js"
            target="_blank"
            rel="noopener noreferrer"
            title="Transformers.js"
          >
            <HfLogo className="h-24 md:h-28 text-gray-300 hover:text-white transition-colors" />
          </a>
        </div>

        <div className="w-full text-center">
          <h1 className="text-5xl font-semibold mb-2 text-white tracking-tight">
            Granite-4.0 WebGPU
          </h1>
          <p className="text-md md:text-lg text-[#a6c8ff]">
            In-browser tool calling, powered by Transformers.js
          </p>
        </div>

        <div className="w-full text-left text-[#d0e2ff] space-y-4 text-xl">
          <p>
            This demo showcases in-browser tool calling with Granite-4.0, a new
            series of models by{" "}
            <a
              href="https://huggingface.co/ibm-granite"
              target="_blank"
              rel="noopener noreferrer"
              className="text-[#78a9ff] hover:underline font-medium"
            >
              IBM Granite
            </a>{" "}
            designed for edge AI and on-device deployment.
          </p>
          <p>
            Everything runs entirely in your browser with{" "}
            <a
              href="https://huggingface.co/docs/transformers.js"
              target="_blank"
              rel="noopener noreferrer"
              className="text-[#78a9ff] hover:underline font-medium"
            >
              Transformers.js
            </a>{" "}
            and ONNX Runtime Web, meaning no data is sent to a server. It can
            even run offline!
          </p>
        </div>

        <p className="text-[#a6c8ff]">
          Select a model and click load to get started.
        </p>

        <div className="relative w-full max-w-lg">
          <div className="flex rounded-2xl border border-white/12 bg-white/10 overflow-hidden shadow-[0_18px_45px_rgba(3,27,78,0.45)]">
            <button
              onClick={isLoading ? undefined : loadSelectedModel}
              disabled={isLoading}
              className={`flex-1 flex items-center justify-center font-semibold transition-all text-lg ${isLoading ? "bg-white/5 text-[#8da2d8] cursor-not-allowed" : "bg-[#0f62fe] hover:bg-[#0043ce] text-white"}`}
            >
              <div className="px-6 py-3">
                {isLoading ? (
                  <div className="flex items-center">
                    <span className="inline-block w-5 h-5 border-2 border-white/80 border-t-transparent rounded-full animate-spin"></span>
                    <span className="ml-3 text-md font-medium">
                      Loading... ({progress}%)
                    </span>
                  </div>
                ) : (
                  `Load ${model?.label}`
                )}
              </div>
            </button>
            <button
              onClick={(e) => {
                if (!isLoading) {
                  e.stopPropagation();
                  setIsModelDropdownOpen(!isModelDropdownOpen);
                }
              }}
              aria-label="Select model"
              className="px-4 py-3 border-l border-white/15 bg-[#0f62fe] hover:bg-[#0043ce] transition-colors text-white disabled:cursor-not-allowed disabled:bg-white/5"
              disabled={isLoading}
            >
              <ChevronDown size={24} />
            </button>
          </div>

          {isModelDropdownOpen && (
            <div className="absolute left-0 right-0 bottom-full mb-3 bg-[#02102c]/98 border border-white/12 rounded-xl shadow-[0_22px_55px_rgba(3,27,78,0.55)] z-10 w-full overflow-visible backdrop-blur-2xl">
              {MODEL_OPTIONS.map((option) => (
                <button
                  key={option.id}
                  onClick={() => handleModelSelect(option.id)}
                  className={`w-full px-5 py-3 text-left text-sm font-medium rounded-lg border transition-all ${
                    selectedModelId === option.id
                      ? "border-[#78a9ff]/60 bg-[#0f62fe]/25 text-white shadow-[0_10px_25px_rgba(15,98,254,0.25)]"
                      : "border-transparent text-[#d0e2ff] hover:border-[#78a9ff]/30 hover:bg-white/12 hover:text-white"
                  }`}
                >
                  <div className="font-medium">{option.label}</div>
                  <div className="text-md text-[#95a8dd]">{option.size}</div>
                </button>
              ))}
            </div>
          )}
        </div>

        {error && (
          <div className="bg-[#2d0709]/70 border border-[#ff8389]/40 rounded-2xl p-4 w-full max-w-md text-center shadow-[0_15px_35px_rgba(45,7,9,0.4)]">
            <p className="text-sm text-[#ffb3b8]">Error: {error}</p>
            <button
              onClick={loadSelectedModel}
              className="mt-3 text-sm px-4 py-2 rounded-full bg-white/15 hover:bg-white/25 border border-white/20 text-white font-semibold transition-all"
            >
              Retry
            </button>
          </div>
        )}
      </div>

      {/* Click-away listener for dropdown */}
      {isModelDropdownOpen && (
        <div
          className="fixed inset-0 z-5"
          onClick={() => setIsModelDropdownOpen(false)}
        />
      )}
    </div>
  );
};
