/*
 * Copyright (c) 2023-2025 Datalayer, Inc.
 * Distributed under the terms of the Modified BSD License.
 */
import { useEffect, useState, useMemo } from 'react';
import { useParamsRR } from '../navigation/adapters/react-router.js';
import { useParamsNext, useSearchParamsNext, } from '../navigation/adapters/nextjs.js';
/**
 * Hook to get URL parameters
 * Works with Next.js App Router, React Router, or falls back to URL parsing
 */
export const useParams = () => {
    // State for fallback URL search params
    const [searchParams, setSearchParams] = useState({});
    // Detect environment
    const isNextJs = typeof window !== 'undefined' && !!window.__NEXT_DATA__;
    const isClient = typeof window !== 'undefined';
    // Try to get params from different sources
    let routeParams = {};
    const queryParams = {};
    let paramsSource = 'fallback';
    // 1. Try Next.js first (if detected)
    if (isNextJs && useParamsNext) {
        try {
            // eslint-disable-next-line react-hooks/rules-of-hooks
            routeParams = useParamsNext() || {};
            paramsSource = 'nextjs';
            // Also get search params in Next.js
            if (useSearchParamsNext) {
                try {
                    // eslint-disable-next-line react-hooks/rules-of-hooks
                    const searchParamsObj = useSearchParamsNext();
                    if (searchParamsObj) {
                        searchParamsObj.forEach((value, key) => {
                            queryParams[key] = value;
                        });
                    }
                }
                catch {
                    // Not in Next.js context or search params not available
                }
            }
        }
        catch {
            // Not in Next.js router context
        }
    }
    // 2. Try React Router (if not Next.js)
    if (paramsSource === 'fallback' && !isNextJs && useParamsRR) {
        try {
            // eslint-disable-next-line react-hooks/rules-of-hooks
            routeParams = useParamsRR() || {};
            paramsSource = 'react-router';
        }
        catch {
            // Not in React Router context
        }
    }
    // 3. Get URL search params (for React Router and fallback)
    useEffect(() => {
        if (!isClient || paramsSource === 'nextjs')
            return;
        const updateSearchParams = () => {
            const params = {};
            const urlParams = new URLSearchParams(window.location.search);
            urlParams.forEach((value, key) => {
                params[key] = value;
            });
            setSearchParams(params);
        };
        updateSearchParams();
        // Listen for URL changes
        window.addEventListener('popstate', updateSearchParams);
        window.addEventListener('pushstate', updateSearchParams);
        window.addEventListener('replacestate', updateSearchParams);
        return () => {
            window.removeEventListener('popstate', updateSearchParams);
            window.removeEventListener('pushstate', updateSearchParams);
            window.removeEventListener('replacestate', updateSearchParams);
        };
    }, [isClient, paramsSource]);
    // Combine all params with proper memoization to prevent re-renders
    const combinedParams = useMemo(() => {
        const result = {};
        // Add route params
        for (const [key, value] of Object.entries(routeParams)) {
            if (value !== undefined) {
                // Handle array values (Next.js catch-all routes)
                result[key] = Array.isArray(value) ? value.join('/') : String(value);
            }
        }
        // Add query params (Next.js)
        for (const [key, value] of Object.entries(queryParams)) {
            result[key] = value;
        }
        // Add search params (React Router and fallback)
        if (paramsSource !== 'nextjs') {
            for (const [key, value] of Object.entries(searchParams)) {
                result[key] = value;
            }
        }
        // Fallback route params are not supported without router configuration
        return result;
    }, [
        // Use JSON.stringify for deep comparison
        JSON.stringify(routeParams),
        JSON.stringify(queryParams),
        JSON.stringify(searchParams),
        paramsSource,
    ]);
    return combinedParams;
};
