import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
import { Label } from '@/components/ui/label';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import SearchableSelect from '@/components/ui/select-search';
import { DateRangePicker } from '@/components/date-range';
import { router } from '@inertiajs/react';
import { Loader2, RefreshCcw, RefreshCw } from 'lucide-react';
import React from 'react';
import { toast } from 'sonner';

interface FiltersState {
    dateRange: { from: string; to: string };
    setDateRange: (v: { from: string; to: string }) => void;
    state: string | undefined;
    setState: (v: string) => void;
    logement: string | undefined;
    setLogement: (v: string) => void;
    minRating: string;
    setMinRating: (v: string) => void;
    source: string;
    setSource: (v: string) => void;
    coHost: string;
    setCoHost: (v: string) => void;
}

interface FiltersCardProps {
    filters: FiltersState;
    logements: { id: number; name: string; internal_name?: string | null; [key: string]: unknown }[];
    coHosts: { id: string | number; name: string }[];
    sources: string[];
    isAdmin: boolean;
    /** Inertia route name to reset to when the user clicks the refresh button. */
    refreshRoute: 'reviews' | 'questionnaires' | 'reviews.stats';
    /** Hide the source filter when the page is dedicated to a single source (e.g. questionnaires). */
    showSourceFilter?: boolean;
    /** Hide the Sync button on pages where it's not relevant (e.g. questionnaires). */
    showSyncButton?: boolean;
    t: (ns: string, k: string) => string;
}

type SyncRunStatus = 'pending' | 'running' | 'completed' | 'failed';

interface SyncRun {
    id: number;
    status: SyncRunStatus;
    stats: { reviews_created?: number; reviews_updated?: number; reservations?: number } | null;
    error_message: string | null;
    from_date: string | null;
    started_at: string | null;
    finished_at: string | null;
    created_at: string;
}

const POLL_INTERVAL_MS = 5000;
const RECENT_FINISH_WINDOW_MS = 30_000;

export function FiltersCard({
    filters,
    logements,
    coHosts,
    sources,
    isAdmin,
    refreshRoute,
    showSourceFilter = true,
    showSyncButton = true,
    t,
}: FiltersCardProps) {
    const {
        dateRange,
        setDateRange,
        state,
        setState,
        logement,
        setLogement,
        minRating,
        setMinRating,
        source,
        setSource,
        coHost,
        setCoHost,
    } = filters;

    const [syncRun, setSyncRun] = React.useState<SyncRun | null>(null);
    const [syncFromDate, setSyncFromDate] = React.useState<string>('');
    const [syncOpen, setSyncOpen] = React.useState(false);
    const previousStatusRef = React.useRef<SyncRunStatus | null>(null);
    const pollTimerRef = React.useRef<number | null>(null);

    const isActiveStatus = (status: SyncRunStatus | undefined) =>
        status === 'pending' || status === 'running';

    const isSyncing = isActiveStatus(syncRun?.status);

    const stopPolling = React.useCallback(() => {
        if (pollTimerRef.current !== null) {
            window.clearInterval(pollTimerRef.current);
            pollTimerRef.current = null;
        }
    }, []);

    const fetchStatus = React.useCallback(async (): Promise<SyncRun | null> => {
        try {
            const res = await fetch(route('reviews.sync.status'), {
                headers: { Accept: 'application/json' },
                credentials: 'same-origin',
            });
            if (!res.ok) return null;
            const data = (await res.json()) as { run: SyncRun | null };
            return data.run;
        } catch {
            return null;
        }
    }, []);

    const handleStatusUpdate = React.useCallback(
        (run: SyncRun | null, opts: { toastOnTransition: boolean }) => {
            const previousStatus = previousStatusRef.current;
            setSyncRun(run);
            previousStatusRef.current = run?.status ?? null;

            if (!run) return;

            // Only toast on transitions FROM an active state TO a terminal state.
            const transitioning =
                opts.toastOnTransition &&
                isActiveStatus(previousStatus ?? undefined) &&
                !isActiveStatus(run.status);

            if (transitioning && run.status === 'completed') {
                const created = run.stats?.reviews_created ?? 0;
                const updated = run.stats?.reviews_updated ?? 0;
                const reservations = run.stats?.reservations ?? 0;
                toast.success(
                    `Sync terminée : ${created} nouvelles, ${updated} mises à jour (${reservations} réservations).`,
                );
                router.reload({ only: ['items', 'stats', 'sources'] });
            } else if (transitioning && run.status === 'failed') {
                toast.error(`Sync échouée : ${run.error_message ?? 'erreur inconnue'}`);
            }
        },
        [],
    );

    const startPolling = React.useCallback(() => {
        stopPolling();
        pollTimerRef.current = window.setInterval(async () => {
            const run = await fetchStatus();
            handleStatusUpdate(run, { toastOnTransition: true });
            if (!isActiveStatus(run?.status)) {
                stopPolling();
            }
        }, POLL_INTERVAL_MS);
    }, [fetchStatus, handleStatusUpdate, stopPolling]);

    // On mount: pull the last run. If active, start polling. If it just finished within
    // the last 30s, swallow the toast (it belongs to the previous tab visit).
    React.useEffect(() => {
        let cancelled = false;
        (async () => {
            const run = await fetchStatus();
            if (cancelled) return;

            const isRecentFinish =
                run?.finished_at &&
                Date.now() - new Date(run.finished_at).getTime() < RECENT_FINISH_WINDOW_MS;

            previousStatusRef.current = run?.status ?? null;
            setSyncRun(run);

            if (isActiveStatus(run?.status)) {
                startPolling();
            } else if (isRecentFinish && run?.status === 'completed') {
                // Page was reloaded right after sync finished — refresh data once.
                router.reload({ only: ['items', 'stats', 'sources'] });
            }
        })();

        return () => {
            cancelled = true;
            stopPolling();
        };
    }, [fetchStatus, startPolling, stopPolling]);

    const triggerSync = () => {
        setSyncOpen(false);
        const data: Record<string, string> = {};
        if (syncFromDate) data.from_date = syncFromDate;
        router.post(route('reviews.sync'), data, {
            preserveScroll: true,
            onSuccess: async () => {
                const run = await fetchStatus();
                handleStatusUpdate(run, { toastOnTransition: false });
                if (isActiveStatus(run?.status)) {
                    startPolling();
                }
            },
        });
    };

    const syncButtonLabel = isSyncing
        ? t('reviews', 'sync_running')
        : t('reviews', 'sync_now');

    return (
        <Card id="filter-container" className="mb-3">
            <CardContent className="flex flex-col items-start justify-between gap-4 px-4 py-2 sm:flex-row">
                <div className="order-2 grid grid-cols-1 gap-1 gap-4 space-y-2 sm:order-1 md:grid-cols-2">
                    <div>
                        <Label className="mb-2 block">{t('reviews', 'review_date')}</Label>
                        <DateRangePicker date={dateRange} setDate={setDateRange} />
                    </div>
                    <div className="flex flex-col gap-2 sm:flex-row">
                        <div className="max-w-lg">
                            <Label className="mb-2 block">{t('reviews', 'properties')}</Label>
                            <SearchableSelect
                                value={logement}
                                onValueChange={setLogement}
                                items={logements}
                                allOptionLabel={t('reviews', 'all_properties')}
                            />
                        </div>
                    </div>
                    <div>
                        <Label className="mb-2 block">{t('reviews', 'min_rating')}</Label>
                        <Select name="minRating" value={minRating} onValueChange={setMinRating}>
                            <SelectTrigger className="text-secondary rounded-2xl bg-white">
                                <SelectValue placeholder={t('reviews', 'all_ratings')} />
                            </SelectTrigger>
                            <SelectContent>
                                <SelectGroup>
                                    <SelectItem value="0">{t('reviews', 'all_ratings')}</SelectItem>
                                    <SelectItem value="1">≥ 1 ★</SelectItem>
                                    <SelectItem value="2">≥ 2 ★</SelectItem>
                                    <SelectItem value="3">≥ 3 ★</SelectItem>
                                    <SelectItem value="4">≥ 4 ★</SelectItem>
                                    <SelectItem value="5">5 ★</SelectItem>
                                </SelectGroup>
                            </SelectContent>
                        </Select>
                    </div>
                    {showSourceFilter && (
                        <div>
                            <Label className="mb-2 block">{t('reviews', 'source')}</Label>
                            <Select name="source" value={source} onValueChange={setSource}>
                                <SelectTrigger className="text-secondary rounded-2xl bg-white">
                                    <SelectValue placeholder={t('reviews', 'all_sources')} />
                                </SelectTrigger>
                                <SelectContent>
                                    <SelectGroup>
                                        <SelectItem value="tous">{t('reviews', 'all_sources')}</SelectItem>
                                        {sources.map((s) => (
                                            <SelectItem key={s} value={s}>
                                                {s}
                                            </SelectItem>
                                        ))}
                                    </SelectGroup>
                                </SelectContent>
                            </Select>
                        </div>
                    )}
                </div>

                <div className="order-1 ml-auto flex max-w-xs items-center justify-between gap-2 sm:order-2">
                    {isAdmin && (
                        <Select name="coHost" value={coHost || ''} onValueChange={setCoHost}>
                            <SelectTrigger className="text-secondary w-[200px] bg-white">
                                <SelectValue
                                    placeholder={t('reviews', 'franchise')}
                                    className="text-secondary bg-white"
                                />
                            </SelectTrigger>
                            <SelectContent>
                                <SelectGroup>
                                    {coHosts.map((c) => (
                                        <SelectItem key={c.id} value={String(c.id)}>
                                            {c.name}
                                        </SelectItem>
                                    ))}
                                </SelectGroup>
                            </SelectContent>
                        </Select>
                    )}
                    <Select name="state" value={state || 'tous'} onValueChange={setState}>
                        <SelectTrigger className="text-secondary bg-white">
                            <SelectValue placeholder={t('reviews', 'select_country')} />
                        </SelectTrigger>
                        <SelectContent>
                            <SelectGroup>
                                <SelectItem value="tous">{t('reviews', 'all')}</SelectItem>
                                <SelectItem value="Tunisie">{t('reviews', 'tunisia')}</SelectItem>
                                <SelectItem value="France">{t('reviews', 'france')}</SelectItem>
                            </SelectGroup>
                        </SelectContent>
                    </Select>
                    {showSyncButton && (
                        <Popover open={syncOpen} onOpenChange={setSyncOpen}>
                            <PopoverTrigger asChild>
                                <Button variant="default" disabled={isSyncing} className="gap-2">
                                    {isSyncing ? (
                                        <Loader2 className="h-4 w-4 animate-spin" />
                                    ) : (
                                        <RefreshCw className="h-4 w-4" />
                                    )}
                                    {syncButtonLabel}
                                </Button>
                            </PopoverTrigger>
                            <PopoverContent className="w-72" align="end">
                                <div className="flex flex-col gap-3">
                                    <div>
                                        <Label htmlFor="sync-from-date" className="mb-2 block">
                                            {t('reviews', 'sync_from_date')}
                                        </Label>
                                        <input
                                            id="sync-from-date"
                                            type="date"
                                            value={syncFromDate}
                                            onChange={(e) => setSyncFromDate(e.target.value)}
                                            className="border-input w-full rounded-md border bg-white px-3 py-2 text-sm"
                                        />
                                        <p className="text-muted-foreground mt-1 text-xs">
                                            {t('reviews', 'sync_empty_means_all')}
                                        </p>
                                    </div>
                                    <Button onClick={triggerSync} disabled={isSyncing} className="w-full">
                                        {isSyncing ? (
                                            <>
                                                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                                                {t('reviews', 'sync_running')}
                                            </>
                                        ) : (
                                            t('reviews', 'sync_launch')
                                        )}
                                    </Button>
                                </div>
                            </PopoverContent>
                        </Popover>
                    )}
                    <Button
                        variant="ghost"
                        className="cursor-pointer"
                        onClick={() => router.get(route(refreshRoute), {}, { preserveState: false, replace: true })}
                    >
                        <RefreshCcw className="h-4 w-4" />
                    </Button>
                </div>
            </CardContent>
        </Card>
    );
}
