"use client";

import * as React from "react";
import { usePathname, useSearchParams } from "next/navigation";
import {
  completeNavigationProgress,
  subscribeNavigationProgress,
} from "@/lib/navigation-progress";

const START_VALUE = 18;
const MAX_ACTIVE_VALUE = 90;

export default function RouteProgress() {
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const [visible, setVisible] = React.useState(false);
  const [progress, setProgress] = React.useState(0);
  const intervalRef = React.useRef<number | null>(null);
  const finishTimeoutRef = React.useRef<number | null>(null);
  const safetyTimeoutRef = React.useRef<number | null>(null);
  const activeRef = React.useRef(false);
  const routeKey = `${pathname ?? ""}?${searchParams?.toString() ?? ""}`;

  const clearTimers = React.useCallback(() => {
    if (intervalRef.current !== null) {
      window.clearInterval(intervalRef.current);
      intervalRef.current = null;
    }

    if (finishTimeoutRef.current !== null) {
      window.clearTimeout(finishTimeoutRef.current);
      finishTimeoutRef.current = null;
    }

    if (safetyTimeoutRef.current !== null) {
      window.clearTimeout(safetyTimeoutRef.current);
      safetyTimeoutRef.current = null;
    }
  }, []);

  const finish = React.useCallback(() => {
    if (!activeRef.current) {
      return;
    }

    activeRef.current = false;
    clearTimers();
    setProgress(100);

    finishTimeoutRef.current = window.setTimeout(() => {
      setVisible(false);
      setProgress(0);
    }, 220);
  }, [clearTimers]);

  const start = React.useCallback(() => {
    clearTimers();
    activeRef.current = true;
    setVisible(true);
    setProgress(START_VALUE);

    window.requestAnimationFrame(() => {
      setProgress(28);
    });

    intervalRef.current = window.setInterval(() => {
      setProgress((current) => {
        if (current >= MAX_ACTIVE_VALUE) {
          return current;
        }

        const delta = Math.max((MAX_ACTIVE_VALUE - current) * 0.14, 1.5);
        return Math.min(MAX_ACTIVE_VALUE, current + delta);
      });
    }, 180);

    safetyTimeoutRef.current = window.setTimeout(() => {
      finish();
    }, 12000);
  }, [clearTimers, finish]);

  React.useEffect(() => {
    return subscribeNavigationProgress((event) => {
      if (event === "start") {
        start();
        return;
      }

      finish();
    });
  }, [finish, start]);

  React.useEffect(() => {
    finish();
  }, [finish, routeKey]);

  React.useEffect(() => {
    return () => {
      clearTimers();
    };
  }, [clearTimers]);

  return (
    <div
      aria-hidden="true"
      className="pointer-events-none fixed inset-x-0 top-0 z-[100] h-1 overflow-hidden"
    >
      <div
        className={`absolute inset-0 transition-opacity duration-200 ${
          visible ? "opacity-100" : "opacity-0"
        }`}
      >
        <div
          className="h-full origin-right bg-[linear-gradient(90deg,hsl(var(--primary))_0%,hsl(var(--route-progress))_100%)] shadow-[0_0_16px_hsl(var(--route-progress)/0.55)] transition-[transform] duration-200 ease-out"
          style={{ transform: `scaleX(${progress / 100})` }}
        />
      </div>
    </div>
  );
}
