"use client";

import { useProgress } from "@react-three/drei";
import { animated, useSpring, useTransition } from "@react-spring/web";
import { useEffect, useState, useRef } from "react";
import { createPortal } from "react-dom";

export const Loader = ({ minDuration = 750, fadeMs = 600 }) => {
  const { progress } = useProgress();
  const [loadedAt, setLoadedAt] = useState<number | null>(null);

  const maxSeen = useRef(0);
  if (progress > maxSeen.current) maxSeen.current = progress;

  useEffect(() => {
    if (maxSeen.current === 100 && loadedAt === null) setLoadedAt(Date.now());
  }, [loadedAt]);

  const visible =
    loadedAt === null || Date.now() - loadedAt < minDuration + fadeMs;

  const barSpring = useSpring({
    from: { width: "0%" },
    to: { width: "100%" },
    config: { duration: minDuration },
  });

  const overlay = useTransition(visible, {
    from: { opacity: 1 },
    enter: { opacity: 1 },
    leave: { opacity: 0 },
    config: { duration: fadeMs, easing: (t) => Math.pow(t, 2) },
  });

  return createPortal(
    overlay(
      (styles, show) =>
        show && (
          // @ts-expect-error children not typed bug
          <animated.div
            style={{
              ...styles,
              position: "fixed",
              inset: 0,
              background: "#1b1b1b",
              zIndex: 999999999,
              display: "flex",
              flexDirection: "column",
              alignItems: "center",
              justifyContent: "center",
              gap: "1.5rem",
              fontSize: "2.25rem",
              color: "white",
              pointerEvents: "none",
              paddingTop: "2.5rem",
            }}
          >
            <p>Loading…</p>

            <div
              style={{
                width: 192,
                height: 16,
                background: "#4b4b4b",
                borderRadius: 8,
                overflow: "hidden",
              }}
            >
              {/* @ts-expect-error children not typed bug */}
              <animated.div
                style={{
                  ...barSpring,
                  height: "100%",
                  background: "#ffffff",
                }}
              >
                {/* @ts-expect-error children not typed bug */}
                <animated.div className="text-[#1b1b1b] text-xs justify-center flex items-center h-full">
                  {barSpring.width.to((w) => {
                    const p = parseInt(w) || 0;
                    return `${p > 5 ? p : ""}`;
                  })}
                </animated.div>
              </animated.div>
            </div>
          </animated.div>
        )
    ),
    document.body
  );
};
