import AppBooleanFilter from '@/components/filters/app-boolean-filter';
import AppDateRangeFilter from '@/components/filters/app-date-range-filter';
import AppDropdownFilter from '@/components/filters/app-dropdown-filter';
import AppMultiSelectFilter, { MultiSelectOption } from '@/components/filters/app-multiselect-filter'; // legacy
import { Option as SearchableOption } from '@/components/form/fields/SearchableMultiSelectField';
import {
    AlertDialog,
    AlertDialogAction,
    AlertDialogCancel,
    AlertDialogContent,
    AlertDialogDescription,
    AlertDialogFooter,
    AlertDialogHeader,
    AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet';
import { cn } from '@/lib/utils';
import { BulkAction, PaginatedData } from '@/types';
import { router } from '@inertiajs/react';
import { Table } from '@tanstack/react-table';
import { Activity, ChevronDown, ListFilterPlus, RotateCcw, Search, SlidersHorizontal } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useDebouncedCallback } from 'use-debounce';
import { FormField } from './form';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Label } from './ui/label';
import { Skeleton } from './ui/skeleton';

export type FilterConfig = {
    type: 'boolean' | 'dropdown' | 'multiselect' | 'searchable-multiselect' | 'date-range';
    label: string;
    name: string;
    value: any;
    options?: { label: string; value: number }[]; // for dropdown
    onChange?: (name: string, value: any) => void;
    // multiselect specific
    fetchType?: 'user' | 'module' | 'action';
    // date-range specific (value will be start|end combined string or object)
};
// Wrapper to embed SearchableMultiSelectField without refactoring whole toolbar form
const InlineSearchableMultiSelect = ({
    name,
    valueString,
    options = [],
    placeholder,
    onChange,
}: {
    name: string;
    valueString: string;
    options: { label: string; value: string }[];
    placeholder?: string;
    onChange: (vals: string[]) => void;
}) => {
    const initialArray = valueString ? valueString.split(',').filter(Boolean) : [];
    const methods = useForm<{ [k: string]: string[] }>({ defaultValues: { [name]: initialArray } });

    // Sync external changes
    useEffect(() => {
        const current = methods.getValues(name) || [];
        const next = valueString ? valueString.split(',').filter(Boolean) : [];
        if (JSON.stringify(current) !== JSON.stringify(next)) {
            methods.setValue(name, next, { shouldDirty: false, shouldTouch: false });
        }
    }, [valueString, name, methods]);

    const searchableOptions: SearchableOption[] = useMemo(() => (options || []).map((o) => ({ value: o.value, label: o.label })), [options]);

    return (
        <FormProvider {...methods}>
            <FormField
                type="multiselect"
                name={name}
                searchable
                placeholder={placeholder || 'Select'}
                options={searchableOptions || []}
                required={false}
                onChange={(vals) => {
                    onChange(vals);
                }}
            />
        </FormProvider>
    );
};

interface DataTableToolbarProps<TData> {
    table: Table<TData>;
    paginatedData: PaginatedData<TData>;
    filters?: FilterConfig[];
    bulkActions?: BulkAction<TData>[];
    className?: string;
    resetColumnVisibility?: () => void;
    loading?: boolean;
    // Select-all across pages integration
    selectAllActive?: boolean;
    onSelectAll?: () => void;
    onClearSelectAll?: () => void;
    navigate?: (params: Record<string, any>) => void;
    handleActivitySidebar?: any;
}

const DataTableToolbar = <TData,>({
    table,
    paginatedData,
    filters = [],
    bulkActions = [],
    className,
    resetColumnVisibility,
    loading = true,
    selectAllActive = false,
    onSelectAll,
    onClearSelectAll,
    navigate,
    handleActivitySidebar,
}: DataTableToolbarProps<TData>) => {
    const uRLSearchParams = new URLSearchParams(window.location.search);
    const search = uRLSearchParams.get('search');
    const { queryParams } = paginatedData || {};
    const safeQueryParams = useMemo(() => queryParams || {}, [queryParams]);
    const [activeDialog, setActiveDialog] = useState<{ action: BulkAction<TData>; items: TData[] } | null>(null);
    const [dropdownOpen, setDropdownOpen] = useState(false);
    const [filterOpen, setFilterOpen] = useState(false);
    const [pendingFilters, setPendingFilters] = useState<Record<string, any>>({});
    const [searchValue, setSearchValue] = useState(search || '');
    const selectedRows = table.getSelectedRowModel().rows.map((r) => r.original);

    const handleBulkAction = (action: BulkAction<TData>, items: TData[]) => {
        if (action.confirm) {
            setActiveDialog({ action, items });
        } else {
            action.onClick(items);
            table.toggleAllPageRowsSelected(false);
        }
    };

    const handleConfirmAction = () => {
        if (!activeDialog) return;
        activeDialog.action.onClick(activeDialog.items);
        setActiveDialog(null);
        table.toggleAllPageRowsSelected(false);
    };

    const handleDebouncedSearch = useDebouncedCallback((value: string) => {
        const updatedQueryParams: Record<string, any> = { ...safeQueryParams, page: 1 };
        if (value.length > 2) updatedQueryParams.search = value;
        else delete updatedQueryParams.search;

        if (navigate) {
            navigate(updatedQueryParams);
            router.get(
                route(route()?.current?.() ?? ''),
                { search: updatedQueryParams.search, per_page: updatedQueryParams.per_page, page: safeQueryParams.page },
                { preserveState: true, preserveScroll: true },
            );
        } else {
            router.get(route(route()?.current?.() ?? ''), updatedQueryParams, {
                preserveScroll: true,
                preserveState: true,
                replace: true,
            });
        }
    }, 500);

    // Wrapper to close filter sheet immediately when user starts typing search
    const handleImmediateSearchChange = (value: string) => {
        setSearchValue(value);
        if (filterOpen) setFilterOpen(false); // close filter menu
        handleDebouncedSearch(value);
    };

    // Handle pending filter changes (doesn't apply immediately)
    const handlePendingFilterChange = (name: string, value: any) => {
        setPendingFilters((prev) => ({
            ...prev,
            [name]: value,
        }));
    };

    // Apply pending filters to query params
    const applyFilters = () => {
        const updatedQueryParams: Record<string, any> = { ...safeQueryParams, page: 1 };

        // Apply all pending filters
        Object.entries(pendingFilters).forEach(([name, value]) => {
            if (value !== undefined && value !== null && value !== '') {
                updatedQueryParams[name] = value;
            } else {
                delete updatedQueryParams[name];
            }
        });

        if (navigate) {
            navigate(updatedQueryParams);
        } else {
            router.get(route(route()?.current?.() ?? ''), updatedQueryParams, {
                preserveScroll: true,
                preserveState: true,
                replace: true,
            });
        }

        setFilterOpen(false);
    };

    // Clear all pending filters and immediately apply (refetch data)
    const clearAllPendingFilters = () => {
        setSearchValue('');
        // Reset to initial state - only keep essential params like route params, remove all query params
        const clearedParams: Record<string, any> = {
            page: 1,
            per_page: 10, // Reset to default per_page value
        };

        // Remove all filter-related params
        (filters || []).forEach((filter) => {
            if (!filter) return;
            if (filter.type === 'date-range') {
                delete clearedParams[filter.name + '_start'];
                delete clearedParams[filter.name + '_end'];
            }
            delete clearedParams[filter.name];
        });

        // Remove search param
        delete clearedParams.search;

        if (navigate) {
            navigate(clearedParams);
        }
        router.get(route(route()?.current?.() ?? ''), clearedParams, {
            preserveScroll: true,
            preserveState: true,
            replace: true,
        });
        setSearchValue('');
        // Clear all pending filter values
        const clearedFilters: Record<string, any> = {};
        (filters || []).forEach((filter) => {
            if (!filter) return;
            if (filter.type === 'date-range') {
                clearedFilters[filter.name + '_start'] = '';
                clearedFilters[filter.name + '_end'] = '';
            } else {
                clearedFilters[filter.name] = '';
            }
        });
        setPendingFilters(clearedFilters);
        setFilterOpen(false);
    };

    // Initialize pending filters when component mounts or filters change
    useEffect(() => {
        const initialFilters: Record<string, any> = {};
        (filters || []).forEach((filter) => {
            if (!filter) return;
            if (filter.type === 'date-range') {
                initialFilters[filter.name + '_start'] = safeQueryParams[filter.name + '_start'] || '';
                initialFilters[filter.name + '_end'] = safeQueryParams[filter.name + '_end'] || '';
            } else {
                initialFilters[filter.name] = filter?.name ? safeQueryParams[filter.name] || '' : '';
            }
        });

        // Only update if the filters have actually changed
        setPendingFilters((prev) => {
            if (JSON.stringify(prev) !== JSON.stringify(initialFilters)) {
                return initialFilters;
            }
            return prev;
        });
    }, [filters, safeQueryParams]);

    // Get the current value for a filter (from pending or query params)
    const getFilterValue = (filterName: string) => {
        const raw = pendingFilters[filterName] !== undefined ? pendingFilters[filterName] : safeQueryParams[filterName];
        if (Array.isArray(raw)) return raw.join(','); // normalize array values to comma string
        if (raw === undefined || raw === null) return '';
        return typeof raw === 'string' ? raw : String(raw);
    };

    // Check if any filters are active
    const hasActiveFilters = () => {
        return (filters || []).some((filter) => {
            if (!filter) return false;
            if (filter.type === 'date-range') {
                const start = safeQueryParams[filter.name + '_start'];
                const end = safeQueryParams[filter.name + '_end'];
                return (start && start !== '') || (end && end !== '');
            }
            const paramValue = filter?.name ? safeQueryParams[filter.name] : undefined;
            return paramValue !== undefined && paramValue !== null && paramValue !== '';
        });
    };

    const activeFiltersCount = (filters || []).reduce((count, filter) => {
        if (!filter) return count;
        if (filter.type === 'date-range') {
            const start = safeQueryParams[filter.name + '_start'];
            const end = safeQueryParams[filter.name + '_end'];
            if (start && start !== '') count++;
            if (end && end !== '') count++;
            return count;
        }
        const paramValue = filter?.name ? safeQueryParams[filter.name] : undefined;
        if (paramValue !== undefined && paramValue !== null && paramValue !== '') count++;
        return count;
    }, 0);

    return (
        <>
            {/* Toolbar */}
            <div className={cn('flex items-center justify-between gap-4 overflow-x-auto rounded-t-lg border-b bg-card p-4', className)}>
                <div className="flex items-center gap-4">
                    {/* Rows per page selector */}
                    {!loading ? (
                        <div className="flex items-center space-x-2">
                            <Select
                                defaultValue="10"
                                value={String(safeQueryParams.per_page || paginatedData?.meta?.per_page || 10)}
                                onValueChange={(value) => {
                                    const perPage = parseInt(value, 10) || 10;
                                    const updatedQueryParams: Record<string, any> = { ...safeQueryParams, per_page: perPage, page: 1 };

                                    if (navigate) {
                                        navigate(updatedQueryParams);
                                        router.get(
                                            route(route()?.current?.() ?? ''),
                                            { per_page: updatedQueryParams.per_page, page: safeQueryParams.page },
                                            { preserveState: true, preserveScroll: true },
                                        );
                                    } else {
                                        router.get(route(route()?.current?.() ?? ''), updatedQueryParams, {
                                            preserveScroll: true,
                                            preserveState: true,
                                            replace: true,
                                        });
                                    }
                                }}
                            >
                                <SelectTrigger className="h-9 w-20">
                                    <SelectValue />
                                </SelectTrigger>
                                <SelectContent>
                                    {[10, 25, 50, 100].map((n) => (
                                        <SelectItem className="" key={n} value={String(n)}>
                                            {n}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                        </div>
                    ) : (
                        <div className="flex items-center">
                            <Skeleton width={80} height={32} variant="rect" />
                        </div>
                    )}

                    {/* Bulk Actions */}
                    {!loading && bulkActions.length > 0 ? (
                        <DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>
                            <DropdownMenuTrigger asChild disabled={selectedRows.length === 0}>
                                <Button
                                    variant="outline"
                                    disabled={selectedRows.length === 0}
                                    className="h-9 border-2 border-gray-200 bg-card text-text-primary"
                                    size="sm"
                                >
                                    Bulk actions ({selectedRows.length}) <ChevronDown className="size-4" />
                                </Button>
                            </DropdownMenuTrigger>
                            <DropdownMenuContent align="start" className="w-48">
                                {bulkActions.map((action, idx) => (
                                    <DropdownMenuItem
                                        key={idx}
                                        className={action.className}
                                        onSelect={() => {
                                            setDropdownOpen(false);
                                            handleBulkAction(action, selectedRows);
                                        }}
                                    >
                                        {action.icon && <action.icon className="size-4 text-inherit" />} {action.label}
                                    </DropdownMenuItem>
                                ))}
                            </DropdownMenuContent>
                        </DropdownMenu>
                    ) : loading && bulkActions.length > 0 ? (
                        <Skeleton width={140} height={32} variant="rect" />
                    ) : null}

                    {/* Reset button */}
                    {!loading ? (
                        <Button
                            className="h-9 border border-gray-200 bg-card px-3 text-primary"
                            variant="outline"
                            size="sm"
                            onClick={() => clearAllPendingFilters()}
                        >
                            <RotateCcw className="size-3" />
                            Reset
                        </Button>
                    ) : (
                        <Skeleton width={80} height={32} variant="rect" />
                    )}

                    {/* Selected count & cross-page select all */}
                    {!loading && selectedRows.length > 0 && (
                        <div className="flex items-center gap-2 text-sm text-muted-foreground">
                            <span className="font-medium whitespace-nowrap">
                                {selectAllActive
                                    ? `All ${paginatedData?.meta?.total ?? selectedRows.length} selected`
                                    : `${selectedRows.length} selected`}
                            </span>
                            {!selectAllActive &&
                                onSelectAll &&
                                paginatedData?.meta?.total &&
                                selectedRows.length > 0 &&
                                paginatedData.meta.total > selectedRows.length && (
                                    <button
                                        type="button"
                                        onClick={onSelectAll}
                                        className="cursor-pointer rounded px-1 py-0.5 text-primary transition-colors hover:bg-primary/5 focus:ring-2 focus:ring-primary/30 focus:outline-none"
                                        title="Select all matching rows"
                                    >
                                        Select all {paginatedData.meta.total}
                                    </button>
                                )}
                            {selectAllActive && onClearSelectAll && (
                                <button
                                    type="button"
                                    onClick={onClearSelectAll}
                                    className="cursor-pointer rounded px-1 py-0.5 text-primary/70 transition-colors hover:bg-primary/5 hover:text-primary focus:ring-2 focus:ring-primary/30 focus:outline-none"
                                    title="Clear select all"
                                >
                                    Clear
                                </button>
                            )}
                        </div>
                    )}
                </div>

                {/* Search */}
                <div className="flex items-center gap-2">
                    <div className="relative">
                        {!loading ? (
                            <>
                                <Search className="pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-gray-400" />
                                <Input
                                    type="search"
                                    placeholder="Search..."
                                    className="h-9 max-w-sm pl-8"
                                    defaultValue={searchValue ?? ''}
                                    onChange={(e) => handleImmediateSearchChange(e.target.value)}
                                />
                            </>
                        ) : (
                            <Skeleton width={240} height={36} variant="rect" />
                        )}
                    </div>
                    {/* Filter Button as Sheet Trigger */}
                    {filters.length > 0 && !loading ? (
                        <Sheet open={filterOpen} onOpenChange={setFilterOpen}>
                            <SheetTrigger asChild>
                                <Button variant="outline" size="sm" className="h-9 border-2 border-gray-200 bg-card px-3 text-primary">
                                    <SlidersHorizontal className="mr-2 h-4 w-4" />
                                    Filter
                                    {activeFiltersCount > 0 && (
                                        <span className="absolute -top-2 -right-2 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-xs font-medium text-primary-foreground">
                                            {activeFiltersCount}
                                        </span>
                                    )}
                                </Button>
                            </SheetTrigger>
                            <SheetContent side="right" className="flex h-full w-[400px] max-w-none flex-col">
                                <SheetHeader className="flex-shrink-0 border-b">
                                    <div className="flex items-center justify-between">
                                        <SheetTitle className="flex items-center gap-2 text-lg font-semibold">
                                            <SlidersHorizontal size={18} />
                                            Filters
                                        </SheetTitle>
                                    </div>
                                    <SheetDescription className="text-sm text-muted-foreground">
                                        Refine your search using advanced filters.
                                        {/* {hasActiveFilters() && <span className="ml-1 font-medium text-primary">({activeFiltersCount} active)</span>} */}
                                    </SheetDescription>
                                </SheetHeader>

                                <div className="mx-4 flex h-full flex-col justify-between">
                                    <div className="space-y-6">
                                        {filters?.map((filter) => {
                                            if (!filter || !filter.name) return null;
                                            return (
                                                <div key={filter.name} className="space-y-2">
                                                    <div className="flex items-center justify-between">
                                                        <Label className="font-semibold">{filter.label}</Label>
                                                    </div>
                                                    <div className={filter.type === 'dropdown' ? 'w-full' : ''}>
                                                        {filter.type === 'boolean' && (
                                                            <AppBooleanFilter
                                                                value={Boolean(getFilterValue(filter.name))}
                                                                onChange={(val) => handlePendingFilterChange(filter.name, val ? '1' : '0')}
                                                            />
                                                        )}
                                                        {filter.type === 'dropdown' && filter.options && (
                                                            <AppDropdownFilter
                                                                value={getFilterValue(filter.name) || ''}
                                                                options={filter.options}
                                                                onChange={(val) => handlePendingFilterChange(filter.name, val)}
                                                            />
                                                        )}
                                                        {filter.type === 'multiselect' && (filter.fetchType || filter.options) && (
                                                            <AppMultiSelectFilter
                                                                value={(getFilterValue(filter.name) || '').split(',').filter(Boolean)}
                                                                onChange={(vals) => handlePendingFilterChange(filter.name, vals.join(','))}
                                                                initialOptions={
                                                                    filter.options
                                                                        ? filter.options.map((o) => ({ value: o.value, label: o.label }))
                                                                        : []
                                                                }
                                                                fetcher={async ({ search, cursor, pageSize }) => {
                                                                    if (filter.fetchType) {
                                                                        const params = new URLSearchParams();
                                                                        params.set('type', filter.fetchType!);
                                                                        if (search) params.set('search', search);
                                                                        if (cursor) params.set('cursor', cursor);
                                                                        params.set('per_page', String(pageSize));
                                                                        const res = await fetch(
                                                                            route('activity-log.filter-options') + '?' + params.toString(),
                                                                            { headers: { Accept: 'application/json' } },
                                                                        );
                                                                        const json = await res.json();
                                                                        const data: MultiSelectOption[] = (json.data || []).map((d: any) => ({
                                                                            value: d.id ?? d.value,
                                                                            label: d.name ?? d.label ?? d.value,
                                                                        }));
                                                                        return { data, nextCursor: json.next_cursor };
                                                                    }
                                                                    const staticAll: MultiSelectOption[] = (filter.options || []).map((o) => ({
                                                                        value: o.value,
                                                                        label: o.label,
                                                                    }));
                                                                    const filtered = search
                                                                        ? staticAll.filter((o) =>
                                                                              o.label.toLowerCase().includes(search.toLowerCase()),
                                                                          )
                                                                        : staticAll;
                                                                    return { data: filtered.slice(0, pageSize), nextCursor: null };
                                                                }}
                                                            />
                                                        )}
                                                        {filter.type === 'searchable-multiselect' && filter.options && (
                                                            <InlineSearchableMultiSelect
                                                                name={filter.name}
                                                                valueString={getFilterValue(filter.name) || ''}
                                                                options={filter.options}
                                                                onChange={(vals) => handlePendingFilterChange(filter.name, vals.join(','))}
                                                                placeholder={`Select ${filter.label.toLowerCase()}...`}
                                                            />
                                                        )}
                                                        {filter.type === 'date-range' && (
                                                            <AppDateRangeFilter
                                                                startDate={getFilterValue(filter.name + '_start') || ''}
                                                                endDate={getFilterValue(filter.name + '_end') || ''}
                                                                onStartDateChange={(val) => handlePendingFilterChange(filter.name + '_start', val)}
                                                                onEndDateChange={(val) => handlePendingFilterChange(filter.name + '_end', val)}
                                                            />
                                                        )}
                                                    </div>
                                                </div>
                                            );
                                        })}
                                    </div>

                                    {/* Filter Action Buttons */}
                                    <SheetFooter>
                                        <div className="flex gap-2 pt-4">
                                            <Button variant="outline" size="sm" onClick={clearAllPendingFilters} className="flex-1">
                                                <RotateCcw className="h-4 w-4" />
                                                Clear All
                                            </Button>
                                            <Button size="sm" onClick={applyFilters} className="flex-1">
                                                <ListFilterPlus className="h-4 w-4" />
                                                Apply Filters
                                            </Button>
                                        </div>
                                    </SheetFooter>
                                </div>
                            </SheetContent>
                        </Sheet>
                    ) : filters.length > 0 && loading ? (
                        <Skeleton width={88} height={36} variant="rect" />
                    ) : null}

                    {/* More options */}
                    {!loading ? (
                        <DropdownMenu>
                            <DropdownMenuTrigger asChild>
                                <Button variant="outline" size="sm" className="h-9 border-2 border-gray-200 bg-card px-2 text-primary">
                                    <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                        <path
                                            strokeLinecap="round"
                                            strokeLinejoin="round"
                                            strokeWidth="2"
                                            d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z"
                                        />
                                    </svg>
                                </Button>
                            </DropdownMenuTrigger>
                            <DropdownMenuContent align="end">
                                {route()?.current?.() !== 'activity-log.index' && (
                                    <DropdownMenuItem onSelect={handleActivitySidebar} className="cursor-pointer">
                                        <Activity className="size-4 text-inherit" />
                                        Activity
                                    </DropdownMenuItem>
                                )}
                            </DropdownMenuContent>
                        </DropdownMenu>
                    ) : (
                        <Skeleton width={40} height={36} variant="rect" />
                    )}
                </div>
            </div>

            {/* Confirm Dialog */}
            {activeDialog && (
                <AlertDialog open={!!activeDialog} onOpenChange={() => setActiveDialog(null)}>
                    <AlertDialogContent className="max-w-sm lg:max-w-md">
                        <AlertDialogHeader>
                            <AlertDialogTitle>Confirm Action</AlertDialogTitle>
                            <AlertDialogDescription>
                                Are you sure you want to perform this action on {activeDialog.items.length} item(s)?
                            </AlertDialogDescription>
                        </AlertDialogHeader>
                        <AlertDialogFooter>
                            <AlertDialogCancel onClick={() => setActiveDialog(null)}>Cancel</AlertDialogCancel>
                            <AlertDialogAction className="bg-red-500 hover:bg-red-600" onClick={handleConfirmAction}>
                                Confirm
                            </AlertDialogAction>
                        </AlertDialogFooter>
                    </AlertDialogContent>
                </AlertDialog>
            )}
        </>
    );
};

export default DataTableToolbar;
