import { ChevronDown } from "lucide-react";
import { MODEL_OPTIONS } from "../constants/models";
import HfLogo from "./icons/HfLogo";
import MCPLogo from "./icons/MCPLogo";
import WebGPULogo from "./icons/WebGPULogo";
import { useEffect, useMemo, useRef, useState } from "react";
import ReactDOM from "react-dom";

type Dot = {
  x: number;
  y: number;
  radius: number;
  speed: number;
  opacity: number;
  blur: number;
  pulse: number;
  pulseSpeed: 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 = useMemo(
    () => MODEL_OPTIONS.find((opt) => opt.id === selectedModelId),
    [selectedModelId]
  );

  // Refs
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const dropdownBtnRef = useRef<HTMLButtonElement>(null);
  const dropdownRef = useRef<HTMLDivElement>(null);

  // For keyboard navigation
  const [activeIndex, setActiveIndex] = useState(
    Math.max(
      0,
      MODEL_OPTIONS.findIndex((m) => m.id === selectedModelId)
    )
  );

  // Background Animation Effect (crisper dots + reduced motion)
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

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

    const prefersReduced =
      typeof window !== "undefined" &&
      window.matchMedia &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;

    let animationFrameId: number;
    let dots: Dot[] = [];

    const setup = () => {
      const dpr = Math.max(1, Math.min(2, window.devicePixelRatio || 1));
      const { innerWidth, innerHeight } = window;
      canvas.width = Math.floor(innerWidth * dpr);
      canvas.height = Math.floor(innerHeight * dpr);
      canvas.style.width = `${innerWidth}px`;
      canvas.style.height = `${innerHeight}px`;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);

      dots = [];
      const numDots = Math.floor((innerWidth * innerHeight) / 12000);
      for (let i = 0; i < numDots; ++i) {
        dots.push({
          x: Math.random() * innerWidth,
          y: Math.random() * innerHeight,
          radius: Math.random() * 2 + 0.3,
          speed: prefersReduced ? 0 : Math.random() * 0.3 + 0.05,
          opacity: Math.random() * 0.4 + 0.1,
          blur: Math.random() > 0.8 ? Math.random() * 1.5 + 0.5 : 0,
          pulse: Math.random() * Math.PI * 2,
          pulseSpeed: prefersReduced ? 0 : Math.random() * 0.02 + 0.01,
        });
      }
    };

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

      dots.forEach((dot) => {
        dot.y += dot.speed;
        dot.pulse += dot.pulseSpeed;

        if (dot.y > height + dot.radius) {
          dot.y = -dot.radius;
          dot.x = Math.random() * width;
        }

        const pulseFactor = 1 + Math.sin(dot.pulse) * 0.2;
        const currentRadius = dot.radius * pulseFactor;
        const currentOpacity = dot.opacity * (0.8 + Math.sin(dot.pulse) * 0.2);

        ctx.beginPath();
        ctx.arc(dot.x, dot.y, currentRadius, 0, Math.PI * 2);
        ctx.fillStyle = `rgba(255, 255, 255, ${currentOpacity})`;
        if (dot.blur > 0) ctx.filter = `blur(${dot.blur}px)`;
        ctx.fill();
        ctx.filter = "none";
      });

      animationFrameId = requestAnimationFrame(draw);
    };

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

    setup();
    draw();
    window.addEventListener("resize", handleResize);

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

  // Close dropdown on Escape / click outside
  useEffect(() => {
    if (!isModelDropdownOpen) return;

    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") setIsModelDropdownOpen(false);
      if (e.key === "ArrowDown") {
        e.preventDefault();
        setActiveIndex((i) => Math.min(MODEL_OPTIONS.length - 1, i + 1));
      }
      if (e.key === "ArrowUp") {
        e.preventDefault();
        setActiveIndex((i) => Math.max(0, i - 1));
      }
      if (e.key === "Enter") {
        e.preventDefault();
        const opt = MODEL_OPTIONS[activeIndex];
        if (opt) {
          handleModelSelect(opt.id);
          setIsModelDropdownOpen(false);
          dropdownBtnRef.current?.focus();
        }
      }
    };

    const onClick = (e: MouseEvent) => {
      const target = e.target as Node;
      if (
        dropdownRef.current &&
        !dropdownRef.current.contains(target) &&
        !dropdownBtnRef.current?.contains(target)
      ) {
        setIsModelDropdownOpen(false);
      }
    };

    document.addEventListener("keydown", onKey);
    document.addEventListener("mousedown", onClick);
    return () => {
      document.removeEventListener("keydown", onKey);
      document.removeEventListener("mousedown", onClick);
    };
  }, [
    isModelDropdownOpen,
    activeIndex,
    setIsModelDropdownOpen,
    handleModelSelect,
  ]);

  return (
    <div className="relative flex flex-col items-center justify-center min-h-screen bg-gradient-to-br from-gray-900 via-slate-900 to-gray-900 text-white p-6 overflow-hidden">
      {/* Background Canvas */}
      <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(15,23,42,0.1)_0%,_rgba(15,23,42,0.4)_40%,_rgba(15,23,42,0.9)_100%)]" />

      {/* Grid Overlay */}
      <div className="absolute inset-0 z-5 opacity-[0.02] bg-[linear-gradient(rgba(255,255,255,0.1)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.1)_1px,transparent_1px)] bg-[size:50px_50px]" />

      {/* Main Content */}
      <div className="relative z-20 max-w-4xl w-full flex flex-col items-center">
        {/* Logos */}
        <div className="flex items-center justify-center mb-8 gap-5">
          <a
            href="https://gpuweb.github.io/gpuweb/"
            target="_blank"
            rel="noopener noreferrer"
            title="WebGPU"
            className="transform transition-all duration-300 hover:scale-105 hover:-translate-y-1"
          >
            <WebGPULogo className="h-16 w-16 md:h-20 md:w-20 text-gray-300 hover:text-white drop-shadow-lg" />
          </a>
          <span className="text-gray-500 text-3xl font-extralight">×</span>
          <a
            href="https://huggingface.co/docs/transformers.js"
            target="_blank"
            rel="noopener noreferrer"
            title="Transformers.js"
            className="transform transition-all duration-300 hover:scale-105 hover:-translate-y-1"
          >
            <HfLogo className="h-16 md:h-20 text-gray-300 hover:text-white drop-shadow-lg" />
          </a>
          <span className="text-gray-500 text-3xl font-extralight">×</span>
          <a
            href="https://modelcontextprotocol.io/"
            target="_blank"
            rel="noopener noreferrer"
            title="Model Context Protocol"
            className="transform transition-all duration-300 hover:scale-105 hover:-translate-y-1"
          >
            <MCPLogo className="h-16 md:h-20 text-gray-300 hover:text-white drop-shadow-lg" />
          </a>
        </div>

        {/* Hero */}
        <div className="text-center mb-8 space-y-4">
          <h1 className="text-5xl sm:text-6xl md:text-7xl font-black bg-gradient-to-r from-white via-gray-100 to-gray-300 bg-clip-text text-transparent tracking-tight leading-none">
            WebGPU MCP
          </h1>
          <p className="text-lg sm:text-xl md:text-2xl text-gray-300 font-light leading-relaxed">
            Run WebGPU-based models with tool calling in your browser, powered
            by the{" "}
            <a
              href="https://modelcontextprotocol.io/"
              target="_blank"
              rel="noopener noreferrer"
            >
              <span className="text-indigo-400 font-medium">
                Model Context Protocol (MCP)
              </span>{" "}
              enabling secure, real-time connections to remote servers.
            </a>
          </p>
          <div className="w-24 h-1 bg-gradient-to-r from-indigo-500 to-purple-500 rounded-full mx-auto" />
        </div>

        {/* Description Cards */}
        <div className="grid md:grid-cols-2 gap-6 text-gray-400 mb-10">
          <div className="bg-white/5 backdrop-blur-sm rounded-xl p-6 border border-white/10">
            <h3 className="text-white font-semibold mb-3 flex items-center">
              <div className="w-2 h-2 bg-indigo-500 rounded-full mr-3" />
              Model Context Protocol
            </h3>
            <p className="text-sm leading-relaxed">
              Connect seamlessly to remote{" "}
              <a
                href="https://modelcontextprotocol.io/"
                target="_blank"
                rel="noopener noreferrer"
                className="text-indigo-400 hover:underline"
              >
                MCP servers
              </a>{" "}
              using streaming or SSE protocols with support for no-auth, basic
              auth, and OAuth.
            </p>
          </div>

          <div className="bg-white/5 backdrop-blur-sm rounded-xl p-6 border border-white/10">
            <h3 className="text-white font-semibold mb-3 flex items-center">
              <div className="w-2 h-2 bg-purple-500 rounded-full mr-3" />
              WebGPU Models
            </h3>
            <p className="text-sm leading-relaxed">
              Supports any WebGPU-compatible models from{" "}
              <a
                href="https://huggingface.co/onnx-community"
                target="_blank"
                rel="noopener noreferrer"
                className="text-indigo-400 hover:underline"
              >
                Hugging Face ONNX Community
              </a>{" "}
              that support tool calling, optimized for on-device deployment.
            </p>
          </div>
        </div>

        <p className="text-gray-400 text-base sm:text-lg mb-10">
          Everything runs entirely in your browser with{" "}
          <a
            href="https://huggingface.co/docs/transformers.js"
            target="_blank"
            rel="noopener noreferrer"
            className="text-indigo-400 hover:underline font-medium"
          >
            Transformers.js
          </a>{" "}
          and ONNX Runtime Web.
        </p>

        {/* Action */}
        <div className="text-center space-y-6">
          <p className="text-gray-400 text-base sm:text-lg font-medium">
            Select a model to load locally, and connect to a remote MCP server
            to get started.
          </p>

          <div className="relative inline-block">
            <div className="flex rounded-2xl shadow-2xl overflow-hidden">
              <button
                onClick={isLoading ? undefined : loadSelectedModel}
                disabled={isLoading}
                className={`flex items-center justify-center font-bold transition-all text-lg ${
                  isLoading
                    ? "bg-gray-700 text-gray-400 cursor-not-allowed"
                    : "bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-500 hover:to-purple-500 text-white shadow-lg hover:shadow-xl transform hover:scale-[1.01] active:scale-[0.99]"
                }`}
                aria-live="polite"
                aria-busy={isLoading}
                aria-label={
                  isLoading
                    ? `Loading ${model?.label ?? "model"} ${progress}%`
                    : `Load ${model?.label ?? "model"}`
                }
              >
                <div className="px-8 py-4">
                  {isLoading ? (
                    <div className="flex items-center">
                      <div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
                      <span className="ml-3 font-semibold">
                        Loading... {progress}%
                      </span>
                    </div>
                  ) : (
                    <span className="font-semibold">Load {model?.label}</span>
                  )}
                </div>
              </button>

              <button
                ref={dropdownBtnRef}
                onClick={(e) => {
                  if (!isLoading) {
                    e.stopPropagation();
                    setIsModelDropdownOpen(!isModelDropdownOpen);
                    setActiveIndex(
                      Math.max(
                        0,
                        MODEL_OPTIONS.findIndex((m) => m.id === selectedModelId)
                      )
                    );
                  }
                }}
                aria-haspopup="menu"
                aria-expanded={isModelDropdownOpen}
                aria-label="Select model"
                className={`px-4 py-4 border-l border-white/20 transition-all ${
                  isLoading
                    ? "bg-gray-700 cursor-not-allowed"
                    : "bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-500 hover:to-purple-500 hover:shadow-lg transform hover:scale-[1.01] active:scale-[0.99]"
                }`}
                disabled={isLoading}
              >
                <ChevronDown
                  size={20}
                  className={`transition-transform duration-200 ${
                    isModelDropdownOpen ? "rotate-180" : ""
                  }`}
                />
              </button>
            </div>

            {/* Dropdown - render in portal to avoid z-index issues */}
            {isModelDropdownOpen &&
              typeof document !== "undefined" &&
              ReactDOM.createPortal(
                <>
                  {/* Backdrop */}
                  <div
                    className="fixed inset-0 z-[999]"
                    onClick={() => setIsModelDropdownOpen(false)}
                  />
                  {/* Dropdown */}
                  <div
                    ref={dropdownRef}
                    role="menu"
                    aria-label="Model options"
                    style={{
                      position: "fixed",
                      bottom: dropdownBtnRef.current
                        ? `${
                            window.innerHeight -
                            dropdownBtnRef.current.getBoundingClientRect().top
                          }px`
                        : "auto",
                      left: dropdownBtnRef.current
                        ? `${
                            dropdownBtnRef.current.getBoundingClientRect().left
                          }px`
                        : "auto",
                      width: dropdownBtnRef.current
                        ? `${
                            dropdownBtnRef.current.getBoundingClientRect()
                              .width + 200
                          }px`
                        : "320px",
                      zIndex: 1000,
                    }}
                    className="bg-gray-900 border-2 border-gray-600 rounded-2xl shadow-2xl overflow-y-auto max-h-[300px] min-w-[320px]"
                    onClick={(e) => e.stopPropagation()}
                  >
                    {MODEL_OPTIONS.map((option, index) => {
                      const selected = selectedModelId === option.id;
                      const isActive = activeIndex === index;
                      return (
                        <button
                          key={option.id}
                          role="menuitem"
                          aria-checked={selected}
                          onMouseEnter={() => setActiveIndex(index)}
                          onClick={(e) => {
                            e.stopPropagation();
                            handleModelSelect(option.id);
                            setIsModelDropdownOpen(false);
                            dropdownBtnRef.current?.focus();
                          }}
                          className={`w-full px-6 py-4 text-left transition-all duration-150 relative outline-none border-b border-gray-700/50 last:border-b-0 cursor-pointer ${
                            selected
                              ? "bg-indigo-600 text-white hover:bg-indigo-500"
                              : "bg-gray-800 text-gray-300 hover:bg-gray-700 hover:text-white active:bg-gray-600"
                          } ${index === 0 ? "rounded-t-2xl" : ""} ${
                            index === MODEL_OPTIONS.length - 1
                              ? "rounded-b-2xl"
                              : ""
                          } ${isActive && !selected ? "bg-gray-700" : ""}`}
                        >
                          <div className="flex items-center justify-between">
                            <div className="flex-1">
                              <div
                                className={`font-semibold text-base mb-1 ${
                                  selected ? "text-white" : "text-gray-100"
                                }`}
                              >
                                {option.label}
                              </div>
                              <div
                                className={`text-sm ${
                                  selected ? "text-indigo-200" : "text-gray-500"
                                }`}
                              >
                                {option.size}
                              </div>
                            </div>
                            {selected && (
                              <div className="flex items-center gap-2 ml-4">
                                <span className="text-xs font-medium text-indigo-200">
                                  Selected
                                </span>
                                <svg
                                  className="w-5 h-5 text-white"
                                  fill="currentColor"
                                  viewBox="0 0 20 20"
                                >
                                  <path
                                    fillRule="evenodd"
                                    d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
                                    clipRule="evenodd"
                                  />
                                </svg>
                              </div>
                            )}
                          </div>
                        </button>
                      );
                    })}
                  </div>
                </>,
                document.body
              )}
          </div>
        </div>

        {/* Error */}
        {error && (
          <div
            role="alert"
            className="bg-red-900/30 backdrop-blur-sm border border-red-500/50 rounded-2xl p-6 mt-8 max-w-md text-center"
          >
            <p className="text-red-200 mb-4 font-medium">Error: {error}</p>
            <button
              onClick={loadSelectedModel}
              className="bg-gradient-to-r from-red-600 to-red-700 hover:from-red-500 hover:to-red-600 px-6 py-3 rounded-xl font-semibold transition-all transform hover:scale-105 active:scale-95 shadow-lg"
            >
              Try Again
            </button>
          </div>
        )}
      </div>
    </div>
  );
};
