import { useEffect, useMemo, useState } from 'preact/hooks'

export const trottleDebounce = <T extends any[], R>(
    fn: (...args: T) => R,
    delay: number,
    options: { leading?: boolean; trailing?: boolean } = {},
): ((...args: T) => R | undefined) => {
    let lastCall = 0
    let lastResult: R | undefined
    let lastArgs: T | undefined
    let timeout: NodeJS.Timeout | undefined

    const leading = options.leading ?? true
    const trailing = options.trailing ?? true

    return (...args: T): R | undefined => {
        lastArgs = args
        if (leading && Date.now() - lastCall >= delay) {
            lastCall = Date.now()
            lastResult = fn(...args)
        } else {
            if (timeout) {
                clearTimeout(timeout)
            }
            timeout = setTimeout(() => {
                if (trailing && lastArgs) {
                    lastCall = Date.now()
                    lastResult = fn(...lastArgs)
                }
            }, delay)
        }
        return lastResult
    }
}

export type ClassValue = string | ClassValue[] | Record<string, boolean> | false | undefined

export function clsx(...args: ClassValue[]): string {
    return args
        .flatMap(arg => {
            if (typeof arg === 'string') {
                return arg
            } else if (Array.isArray(arg)) {
                return clsx(...arg)
            } else if (typeof arg === 'boolean') {
                return []
            } else if (typeof arg === 'object') {
                return Object.entries(arg).flatMap(([key, value]) => (value ? key : []))
            } else {
                return []
            }
        })
        .join(' ')
}

export const isMobile = () => {
    const [windowWidth, setWindowWidth] = useState(0)

    useEffect(() => {
        setWindowWidth(window.innerWidth)

        const handleResize = () => setWindowWidth(window.innerWidth)
        window.addEventListener('resize', handleResize)

        return () => window.removeEventListener('resize', handleResize)
    }, [])

    return windowWidth < 1024
}
