"use client";

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

export const Loader = ({ minDuration = 750, fadeMs = 600 }) => {
  const [barDone, setBarDone] = useState(false);
  const barStyles = useSpring({
    from: { width: "0%" },
    to: { width: "100%" },
    config: { duration: minDuration },
    onRest: () => setBarDone(true),
  });

  const { progress } = useProgress();
  const [assetsDone, setAssetsDone] = useState(false);
  useEffect(() => {
    if (progress === 100) setAssetsDone(true);
  }, [progress]);

  const [visible, setVisible] = useState(true);

  useEffect(() => {
    if (barDone && assetsDone) {
      const id = setTimeout(() => setVisible(false), fadeMs);
      return () => clearTimeout(id);
    }
  }, [barDone, assetsDone, fadeMs]);

  const overlay = useTransition(visible, {
    from: { opacity: 1 },
    leave: { opacity: 0 },
    config: { duration: fadeMs, easing: (t) => t * t },
  });

  return createPortal(
    overlay(
      (styles, show) =>
        show && (
          <div>
            {/* @ts-expect-error children not typed bug */}
            <animated.div
              style={{
                ...styles,
                position: "fixed",
                inset: 0,
                background: "#1b1b1b",
                zIndex: 1e9,
                display: "flex",
                flexDirection: "column",
                alignItems: "center",
                justifyContent: "center",
                gap: "1.5rem",
                fontSize: "2.25rem",
                color: "#fff",
                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={{ ...barStyles, height: "100%", background: "#fff" }}
                >
                  {/* @ts-expect-error children not typed bug */}
                  <animated.div className="text-[#1b1b1b] text-xs flex h-full items-center justify-center">
                    {barStyles.width.to((w) => {
                      const p = parseInt(w) || 0;
                      return p > 5 ? p : "";
                    })}
                  </animated.div>
                </animated.div>
              </div>
            </animated.div>
          </div>
        )
    ),
    document.body
  );
};
