/**
 * Custom React hooks
 * @description Reusable hooks following AgenticIQ best practices
 */

import { useState, useEffect, useRef, type RefObject } from 'react'

/**
 * Hook for managing media queries
 * @description Tracks whether a media query matches
 * @param query - Media query string
 * @returns Boolean indicating if query matches
 * @example
 * const isMobile = useMediaQuery('(max-width: 768px)')
 */
export function useMediaQuery(query: string): boolean {
    const [matches, setMatches] = useState(false)

    useEffect(() => {
        const media = window.matchMedia(query)

        if (media.matches !== matches) {
            setMatches(media.matches)
        }

        const listener = () => setMatches(media.matches)
        media.addEventListener('change', listener)

        return () => media.removeEventListener('change', listener)
    }, [matches, query])

    return matches
}

/**
 * Hook for debouncing values
 * @description Delays updating a value until after a specified delay
 * @param value - Value to debounce
 * @param delay - Delay in milliseconds
 * @returns Debounced value
 * @example
 * const debouncedSearch = useDebounce(searchTerm, 500)
 */
export function useDebounce<T>(value: T, delay: number): T {
    const [debouncedValue, setDebouncedValue] = useState<T>(value)

    useEffect(() => {
        const handler = setTimeout(() => {
            setDebouncedValue(value)
        }, delay)

        return () => {
            clearTimeout(handler)
        }
    }, [value, delay])

    return debouncedValue
}

/**
 * Hook for handling click outside events
 * @description Closes dropdown/modal when clicking outside the element
 * @param handler - Callback function to execute when click outside occurs
 * @param enabled - Whether the hook is enabled
 * @returns Ref to attach to the element
 * @example
 * const ref = useClickOutside(() => setIsOpen(false), isOpen)
 */
export function useClickOutside<T extends HTMLElement>(
    handler: () => void,
    enabled: boolean = true
): RefObject<T> {
    const ref = useRef<T>(null)

    useEffect(() => {
        if (!enabled) return

        const handleClick = (event: MouseEvent) => {
            if (ref.current && !ref.current.contains(event.target as Node)) {
                handler()
            }
        }

        document.addEventListener('mousedown', handleClick)
        return () => document.removeEventListener('mousedown', handleClick)
    }, [handler, enabled])

    return ref
}

/**
 * Hook for handling escape key press
 * @description Executes callback when Escape key is pressed
 * @param handler - Callback function to execute
 * @param enabled - Whether the hook is enabled
 * @example
 * useEscapeKey(() => onClose(), isOpen)
 */
export function useEscapeKey(handler: () => void, enabled: boolean = true): void {
    useEffect(() => {
        if (!enabled) return

        const handleEscape = (event: KeyboardEvent) => {
            if (event.key === 'Escape') {
                handler()
            }
        }

        document.addEventListener('keydown', handleEscape)
        return () => document.removeEventListener('keydown', handleEscape)
    }, [handler, enabled])
}

/**
 * Hook for locking/unlocking body scroll
 * @description Prevents body scroll when modal/dialog is open
 * @param locked - Whether body scroll should be locked
 * @example
 * useBodyScrollLock(isModalOpen)
 */
export function useBodyScrollLock(locked: boolean): void {
    useEffect(() => {
        if (locked) {
            document.body.style.overflow = 'hidden'
        } else {
            document.body.style.overflow = 'unset'
        }

        return () => {
            document.body.style.overflow = 'unset'
        }
    }, [locked])
}
