import { Badge } from '@admin/components/ui/badge';
import { Button } from '@admin/components/ui/button';
import { Sheet, SheetContent, SheetHeader } from '@admin/components/ui/sheet';
import { formatAction } from '@admin/lib/format-action';
import axios from 'axios';
import { format } from 'date-fns';
import { Activity, AlertCircle, Clock, Globe, Loader2, User } from 'lucide-react';
import { useCallback, useEffect, useRef, useState } from 'react';

interface ActivityLog {
    id: number;
    user: { id: number; name: string; email: string } | null;
    module: { id: number; name: string } | null;
    action: string;
    description: string | null;
    ip_address: string | null;
    properties: Record<string, any> | null;
    created_at: string;
}

interface CursorMeta {
    per_page: number;
    next_cursor?: string | null;
    prev_cursor?: string | null;
    has_more: boolean;
    total?: number;
    remaining?: number;
    model_class?: string;
    model_id?: number | string | null;
}

interface ModelActivityLogModalProps {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    modelClass: string;
    modelId?: number | string;
    perPage?: number;
    title?: string;
    action?: string;
    actions?: string[];
    settingKey?: string;
    onClearFilters?: () => void;
}

export const ActivityLogSidebar = ({
    open,
    onOpenChange,
    modelClass,
    modelId,
    perPage = 10,
    title,
    action,
    actions,
    settingKey,
    onClearFilters,
}: ModelActivityLogModalProps) => {
    const [logs, setLogs] = useState<ActivityLog[]>([]);
    const [meta, setMeta] = useState<CursorMeta | null>(null);
    const [loading, setLoading] = useState(false);
    const [loadingMore, setLoadingMore] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [cursor, setCursor] = useState<string | undefined>();
    const sentinelRef = useRef<HTMLDivElement | null>(null);
    const scrollRef = useRef<HTMLDivElement | null>(null);
    const observerRef = useRef<IntersectionObserver | null>(null);

    const fetchLogs = async (cursorParam?: string, append = false) => {
        try {
            append ? setLoadingMore(true) : setLoading(true);
            const response = await axios.get(route('activity-log.action', modelClass), {
                params: {
                    per_page: perPage,
                    model_id: modelId,
                    // support single action or multiple actions
                    action: Array.isArray(actions) && actions.length > 0 ? actions : action,
                    setting_key: settingKey,
                    ...(cursorParam ? { cursor: cursorParam } : {}),
                },
            });
            const { data, meta } = response.data;
            setLogs((prev) => (append ? [...prev, ...data] : data));
            setMeta(meta);
            setCursor(meta?.next_cursor || undefined);
            setError(null);
        } catch (e) {
            console.error(e);
            setError('Failed to load activity logs');
        } finally {
            setLoading(false);
            setLoadingMore(false);
        }
    };

    // Reset and load when modal opens or identifiers change
    useEffect(() => {
        if (open) {
            setLogs([]);
            setMeta(null);
            setCursor(undefined);
            fetchLogs();
        }
    }, [open, modelClass, modelId, perPage, action, actions, settingKey]);

    const loadMore = () => {
        if (meta?.has_more && cursor) fetchLogs(cursor, true);
    };

    const handleIntersect = useCallback(
        (entries: IntersectionObserverEntry[]) => {
            const first = entries[0];
            if (first.isIntersecting) loadMore();
        },
        [cursor, meta?.has_more, loadingMore],
    );

    useEffect(() => {
        if (!sentinelRef.current) return;
        if (!(meta?.has_more && cursor)) {
            observerRef.current?.disconnect();
            return;
        }
        observerRef.current = new IntersectionObserver(handleIntersect, {
            root: scrollRef.current,
            rootMargin: '120px',
            threshold: 0.05,
        });
        observerRef.current.observe(sentinelRef.current);
        return () => observerRef.current?.disconnect();
    }, [handleIntersect, meta?.has_more, cursor]);

    const formatDate = (value: string) => {
        try {
            return format(new Date(value), 'MMM dd, yyyy HH:mm');
        } catch {
            return value;
        }
    };

    return (
        <Sheet open={open} onOpenChange={onOpenChange}>
            <SheetContent side="right" className="flex h-full w-full max-w-md flex-col md:w-[560px]">
                <SheetHeader className="border-b">
                    <div className="flex w-full flex-col md:flex-row md:items-start">
                        <div className="flex items-center gap-3">
                            <Activity className="h-5 w-5 text-gray-600" />
                            <div>
                                <div className="text-lg font-semibold">{title || 'Activity Log'}</div>
                                {meta?.total !== undefined ? (
                                    <div className="text-xs text-gray-500">
                                        Showing <span className="font-medium">{logs?.length}</span> of{' '}
                                        <span className="font-medium">{meta.total}</span>
                                    </div>
                                ) : (
                                    <div className="text-xs text-gray-500">{logs?.length} items</div>
                                )}
                            </div>
                        </div>
                    </div>
                </SheetHeader>
                <div className="flex h-full flex-col justify-between overflow-hidden px-4">
                    <div className="h-full">
                        {(action || (Array.isArray(actions) && actions.length > 0) || settingKey) && (
                            <div className="mb-3 flex flex-wrap items-center gap-2 text-xs">
                                {/*<Badge variant="outline" className="bg-amber-50 border-amber-300 text-amber-700 flex items-center gap-1">*/}
                                {/*  Filtered*/}
                                {/*  {actions && actions.length > 0 ? (*/}
                                {/*    <span className="font-mono">actions=[{actions.join(', ')}]</span>*/}
                                {/*  ) : (*/}
                                {/*    action && <span className="font-mono">action={action}</span>*/}
                                {/*  )}*/}
                                {/*  {settingKey && <span className="font-mono">key={settingKey}</span>}*/}
                                {/*</Badge>*/}
                                {onClearFilters && (
                                    <Button size="sm" variant="ghost" className="h-6 px-2" onClick={onClearFilters}>
                                        Clear
                                    </Button>
                                )}
                            </div>
                        )}
                        {error && (
                            <div className="flex items-center gap-2 rounded border bg-red-50 p-4 text-sm text-red-700">
                                <AlertCircle className="h-4 w-4" /> {error}
                                <Button size="sm" variant="outline" onClick={() => fetchLogs()}>
                                    Retry
                                </Button>
                            </div>
                        )}
                        {!error && (
                            <div ref={scrollRef} className="custom-scrollbar max-h-[87vh] space-y-3 overflow-y-auto pr-1">
                                {loading && logs?.length === 0 && (
                                    <div className="flex items-center justify-center py-8 text-sm text-gray-500">
                                        <Loader2 className="mr-2 h-4 w-4 animate-spin" /> Loading...
                                    </div>
                                )}
                                {logs?.map((log) => (
                                    <div key={log.id} className="rounded-lg border bg-background p-3">
                                        <div className="mb-1 flex items-center gap-2">
                                            <Badge variant="outline">{formatAction(log.action)}</Badge>
                                            {log.module && (
                                                <Badge variant="outline" className="border-blue-200 bg-blue-50 text-blue-700">
                                                    {log.module.name}
                                                </Badge>
                                            )}
                                            <span className="ml-auto flex items-center gap-1 text-xs text-gray-500">
                                                <Clock className="h-3 w-3" /> {formatDate(log.created_at)}
                                            </span>
                                        </div>
                                        <div className="mb-1 text-sm text-primary">{log.description || 'No description'}</div>
                                        <div className="mb-1 flex flex-wrap gap-3 text-xs text-gray-500">
                                            {log.ip_address && (
                                                <span className="flex items-center gap-1">
                                                    <Globe className="h-3 w-3" />
                                                    {log.ip_address}
                                                </span>
                                            )}
                                            {log.user && (
                                                <span className="flex items-center gap-1">
                                                    <User className="h-3 w-3" />
                                                    {log.user.name || log.user.email}
                                                </span>
                                            )}
                                        </div>
                                    </div>
                                ))}

                                {meta?.has_more && (
                                    <div className="py-3">
                                        <div ref={sentinelRef} className="h-2" />
                                        {!('IntersectionObserver' in window) && (
                                            <div className="text-center">
                                                <Button size="sm" onClick={loadMore} disabled={loadingMore} variant="outline" className="w-full">
                                                    {loadingMore ? (
                                                        <>
                                                            <Loader2 className="mr-2 h-4 w-4 animate-spin" /> Loading...
                                                        </>
                                                    ) : (
                                                        'Load More'
                                                    )}
                                                </Button>
                                            </div>
                                        )}
                                        {loadingMore && (
                                            <div className="flex items-center justify-center py-2 text-xs text-gray-500">
                                                <Loader2 className="mr-2 h-3 w-3 animate-spin" /> Loading more...
                                            </div>
                                        )}
                                    </div>
                                )}

                                {!loading && logs?.length === 0 && (
                                    <div className="py-10 text-center text-sm text-gray-500">
                                        <Activity className="mx-auto mb-2 h-10 w-10 text-gray-300" />
                                        No activity logs found.
                                    </div>
                                )}
                            </div>
                        )}
                    </div>

                    <div className="pt-3 text-center text-xs text-gray-500">
                        Loaded {logs?.length}
                        {meta?.total !== undefined && ` of ${meta.total}`}
                        {meta?.remaining !== undefined && meta.remaining > 0 && ` • ${meta.remaining} more`}
                    </div>
                </div>
            </SheetContent>
        </Sheet>
    );
};
