import { useState, useCallback, useEffect, useMemo } from "react";
import { debounce } from "lodash";

interface UseSearchProps {
    initialValue?: string;
    onSearch: (value: string) => void;
    debounceMs?: number;
}

interface UseSearchReturn {
    searchValue: string;
    handleSearch: (e: React.ChangeEvent<HTMLInputElement>) => void;
    setSearchValue: (value: string) => void;
    clearSearch: () => void;
    isSearching: boolean;
}

export function useSearchImproved({
    initialValue = '',
    onSearch,
    debounceMs = 500
}: UseSearchProps): UseSearchReturn {
    const [searchValue, setSearchValue] = useState(initialValue);
    const [isSearching, setIsSearching] = useState(false);

    // Sync with initial value when it changes
    useEffect(() => {
        setSearchValue(initialValue);
    }, [initialValue]);

    // Memoized debounced search function
    const debouncedSearch = useMemo(
        () => debounce((value: string) => {
            onSearch(value);
            setIsSearching(false);
        }, debounceMs),
        [onSearch, debounceMs]
    );

    // Cleanup on unmount
    useEffect(() => {
        return () => {
            debouncedSearch.cancel();
        };
    }, [debouncedSearch]);

    const handleSearch = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
        const value = e.target.value;
        setSearchValue(value);

        // Set searching state
        setIsSearching(true);

        // Jika value kosong (user menghapus semua text), langsung trigger search
        if (value.trim() === '') {
            debouncedSearch.cancel();
            onSearch('');
            setIsSearching(false);
        } else {
            debouncedSearch(value);
        }
    }, [debouncedSearch, onSearch]);

    const clearSearch = useCallback(() => {
        setSearchValue('');
        debouncedSearch.cancel();
        onSearch('');
        setIsSearching(false);
    }, [debouncedSearch, onSearch]);

    const handleSetSearchValue = useCallback((value: string) => {
        setSearchValue(value);
        // Trigger immediate search when setting value programmatically
        debouncedSearch.cancel();
        onSearch(value);
        setIsSearching(false);
    }, [debouncedSearch, onSearch]);

    return {
        searchValue,
        handleSearch,
        setSearchValue: handleSetSearchValue,
        clearSearch,
        isSearching,
    };
}

// Contoh penggunaan di komponen:
/*
const { searchValue, handleSearch, clearSearch, isSearching } = useSearchImproved({
    initialValue: params.search || '',
    onSearch: useCallback((value: string) => {
        setParams({ search: value.trim() || undefined });
    }, [setParams]),
    debounceMs: 500,
});

// Di JSX:
<div className="position-relative">
    <Form.Control
        type="search"
        value={searchValue}
        onChange={handleSearch}
        placeholder="Search..."
    />
    {searchValue && (
        <Button
            variant="link"
            size="sm"
            className="position-absolute end-0 top-50 translate-middle-y"
            onClick={clearSearch}
            style={{ zIndex: 10 }}
        >
            ×
        </Button>
    )}
    {isSearching && <small className="text-muted">Searching...</small>}
</div>
*/