import { Button } from '@admin/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@admin/components/ui/card';
import axios from 'axios';
import { format } from 'date-fns';
import { Activity, AlertCircle, Clock, Package, User } from 'lucide-react';
import { useCallback, useEffect, useRef, useState } from 'react';

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

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

interface ActivityState {
    items: ActivityLog[];
    meta: CursorMeta | null;
}

interface ProfileActivityLogProps {
    userUid: string | number;
    initialPage?: number;
    perPage?: number;
}

const ActivityLogSkeleton = () => (
    <Card className="mb-4">
        <CardContent className="p-4">
            <div className="flex items-start space-x-4">
                <div className="h-10 w-10 animate-pulse rounded-full bg-gray-200"></div>
                <div className="flex-1 space-y-2">
                    <div className="h-4 w-3/4 animate-pulse rounded bg-gray-200"></div>
                    <div className="h-3 w-1/2 animate-pulse rounded bg-gray-200"></div>
                    <div className="h-3 w-1/4 animate-pulse rounded bg-gray-200"></div>
                </div>
            </div>
        </CardContent>
    </Card>
);

const getActionIcon = (action: string, sizeClass = 'h-3 w-3') => {
    const a = action?.toLowerCase() || '';
    switch (a) {
        case 'create':
        case 'created':
            return <Activity className={`${sizeClass} text-green-600`} />;
        case 'update':
        case 'updated':
            return <Package className={`${sizeClass} text-blue-600`} />;
        case 'delete':
        case 'deleted':
            return <AlertCircle className={`${sizeClass} text-red-600`} />;
        case 'login':
        case 'logout':
            return <User className={`${sizeClass} text-purple-600`} />;
        default:
            return <Activity className={`${sizeClass} text-gray-600`} />;
    }
};

const getActionColor = (action: string): string => {
    switch (action.toLowerCase()) {
        case 'create':
        case 'created':
            return 'bg-green-100 text-green-800';
        case 'update':
        case 'updated':
            return 'bg-blue-100 text-blue-800';
        case 'delete':
        case 'deleted':
            return 'bg-red-100 text-red-800';
        case 'login':
        case 'logout':
            return 'bg-purple-100 text-purple-800';
        default:
            return 'bg-gray-100 text-gray-800';
    }
};

// Small TimelineItem component (shadcn style)
const TimelineItem = ({ isLast, date, moduleName, description }: { isLast: boolean; date: string; moduleName: string; description: string }) => {
    return (
        <div className="flex min-h-[4rem] items-stretch space-x-4">
            <div className="relative flex flex-col items-center">
                {/* absolute vertical line that spans the full height of the item */}
                {!isLast && <div className="absolute top-0 bottom-0 left-1/2 w-px -translate-x-1/2 transform bg-gray-200" />}

                {/* dot sits above the line */}
                <div className="relative z-10 flex items-center justify-center">
                    <div className="flex h-4 w-4 items-center justify-center rounded-full border-2 border-gray-200 bg-white">
                        <div className="h-1.5 w-1.5 rounded-full bg-gray-400" />
                    </div>
                </div>
            </div>

            <div className="flex-1">
                <div className="text-sm text-gray-900">
                    <span className="text-sm text-gray-800">{description}</span>
                </div>
                <div className="mt-2 flex items-center gap-2 text-xs text-gray-400">
                    <Clock className="h-3 w-3" />
                    <span>{date}</span>
                </div>
            </div>
        </div>
    );
};

export function ProfileActivityLog({ userUid, initialPage = 1, perPage = 5 }: ProfileActivityLogProps) {
    const [activityState, setActivityState] = useState<ActivityState>({ items: [], meta: null });
    const [loading, setLoading] = useState(true);
    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 scrollContainerRef = useRef<HTMLDivElement | null>(null);
    const observerRef = useRef<IntersectionObserver | null>(null);

    const canAutoLoad = activityState.meta?.has_more && !loadingMore && !!cursor;

    const fetchActivityLogs = async (cursorParam?: string, append: boolean = false) => {
        try {
            if (append) {
                setLoadingMore(true);
            } else {
                setLoading(true);
            }
            const response = await axios.get(route('activity-log.show', userUid), {
                params: {
                    per_page: perPage,
                    ...(cursorParam ? { cursor: cursorParam } : {}),
                },
            });

            const { data, meta } = response.data;

            setActivityState((prev) => ({
                items: append ? [...prev.items, ...data] : data,
                meta,
            }));

            setCursor(meta?.next_cursor || undefined);
            setError(null);
        } catch (err) {
            console.error('Error fetching activity logs:', err);
            setError('Failed to load activity logs');
        } finally {
            setLoading(false);
            setLoadingMore(false);
        }
    };

    useEffect(() => {
        // reset when user changes
        setActivityState({ items: [], meta: null });
        setCursor(undefined);
        fetchActivityLogs();
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [userUid, perPage]);

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

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

    // Setup observer
    useEffect(() => {
        if (!sentinelRef.current) return;
        if (!canAutoLoad) {
            if (observerRef.current) {
                observerRef.current.disconnect();
            }
            return;
        }
        const options: IntersectionObserverInit = {
            root: scrollContainerRef.current, // observe within scrollable container
            rootMargin: '100px', // start loading a bit earlier
            threshold: 0.05,
        };
        observerRef.current = new IntersectionObserver(handleIntersect, options);
        observerRef.current.observe(sentinelRef.current);
        return () => {
            observerRef.current?.disconnect();
        };
    }, [handleIntersect, canAutoLoad]);

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

    const formatProperties = (properties: Record<string, any>): string => {
        if (!properties || Object.keys(properties).length === 0) {
            return '';
        }

        try {
            return Object.entries(properties)
                .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
                .join(', ');
        } catch {
            return 'Invalid properties';
        }
    };

    if (loading && activityState.items.length === 0) {
        return (
            <Card className="">
                <CardHeader>
                    <CardTitle className="flex items-center gap-2">
                        <Activity className="h-5 w-5" />
                        Activity Log
                    </CardTitle>
                </CardHeader>
                <CardContent>
                    <div className="space-y-4">
                        {Array.from({ length: 5 }).map((_, index) => (
                            <ActivityLogSkeleton key={index} />
                        ))}
                    </div>
                </CardContent>
            </Card>
        );
    }

    if (error) {
        return (
            <Card>
                <CardHeader>
                    <CardTitle className="flex items-center gap-2">
                        <Activity className="h-5 w-5" />
                        Activity Log
                    </CardTitle>
                </CardHeader>
                <CardContent>
                    <div className="py-8 text-center">
                        <AlertCircle className="mx-auto mb-4 h-12 w-12 text-red-500" />
                        <p className="mb-4 text-red-600">{error}</p>
                        <Button onClick={() => fetchActivityLogs()} variant="outline">
                            Try Again
                        </Button>
                    </div>
                </CardContent>
            </Card>
        );
    }

    if (!loading && activityState.items.length === 0) {
        return (
            <Card>
                <CardHeader>
                    <CardTitle className="flex items-center gap-2">
                        <Activity className="h-5 w-5" />
                        Activity Log
                    </CardTitle>
                </CardHeader>
                <CardContent>
                    <div className="py-8 text-center">
                        <Activity className="mx-auto mb-4 h-12 w-12 text-gray-400" />
                        <p className="text-gray-600">No activity logs found for this user.</p>
                    </div>
                </CardContent>
            </Card>
        );
    }

    return (
        <Card className="space-y-10 px-0">
            <CardHeader className="mb-3 border-b px-4 pt-1 pb-5">
                <CardTitle className="flex items-center gap-2 text-lg">
                    {/* <Activity className="h-5 w-5" /> */}
                    Activity Log
                    {/* <Badge variant="secondary" className="ml-auto">
                        {activityState.items.length}
                        {activityState.meta?.total !== undefined && ` / ${activityState.meta.total}`}
                    </Badge> */}
                </CardTitle>
            </CardHeader>
            <CardContent>
                <div ref={scrollContainerRef} className="custom-scrollbar max-h-96 space-y-4 overflow-y-auto pr-1">
                    <div className="relative">
                        {/* Vertical timeline container (shadcn-style) */}
                        {activityState.items.map((log: ActivityLog, idx: number) => {
                            const isLast = idx === activityState.items.length - 1;
                            return (
                                <TimelineItem
                                    key={log.id}
                                    isLast={isLast}
                                    date={formatDate(log.created_at)}
                                    moduleName={log.module?.name || 'General'}
                                    description={log.description || 'No description available'}
                                />
                            );
                        })}
                    </div>

                    {/* Infinite scroll sentinel */}
                    {activityState.meta?.has_more && (
                        <div className="space-y-2 pt-2">
                            <div ref={sentinelRef} aria-hidden="true" className="h-2 w-full" />
                            <div className="text-center">
                                <Button onClick={loadMore} disabled={loadingMore || !activityState.meta?.has_more} variant="outline" size="sm">
                                    {loadingMore ? (
                                        <>
                                            <div className="mr-2 h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"></div>
                                            Loading...
                                        </>
                                    ) : (
                                        'Load More'
                                    )}
                                </Button>
                            </div>
                            {loadingMore && (
                                <div className="flex items-center justify-center py-1 text-xs text-gray-500">
                                    <div className="mr-2 h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" />
                                    Loading more...
                                </div>
                            )}
                        </div>
                    )}

                    {/* Pagination Info */}
                    <div className="pt-2 text-center text-sm text-gray-500">
                        Loaded {activityState.items.length}
                        {activityState.meta?.total !== undefined && ` of ${activityState.meta.total}`}
                        {activityState.meta?.has_more &&
                            activityState.meta?.total !== undefined &&
                            ` • ${activityState.meta.total - activityState.items.length} remaining`}
                    </div>
                </div>
            </CardContent>
        </Card>
    );
}
