import CommentContent from './comment-content';
import CommentThreadSidebar from './comment-thread-sidebar';
import {Avatar, Button, TooltipProvider} from '@tryghost/shade/components';
import {type Comment, useHideComment, useShowComment, useUnpinComment} from '@tryghost/admin-x-framework/api/comments';
import {CommentHeader} from './comment-header';
import {CommentMenu} from './comment-menu';
import {CommentMetrics} from './comment-metrics';
import {buildThreadLink} from './thread-link';
import {Link, useSearchParams} from '@tryghost/admin-x-framework';
import {LoadMoreButton, useInfiniteVirtualScroll, useScrollRestoration, useVirtualListWindow} from '@/shared/virtual-list';
import {LucideIcon, cn} from '@tryghost/shade/utils';
import {forwardRef, useEffect, useRef, useState} from 'react';
import {useCommentsPinningEnabled} from '@/comments/hooks/use-comments-pinning-enabled';

const SpacerRow = ({height}: { height: number }) => (
    <div aria-hidden="true" className="flex">
        <div className="flex" style={{height}} />
    </div>
);

// TODO: Remove forwardRef once we have upgraded to React 19
const PlaceholderRow = forwardRef<HTMLDivElement>(function PlaceholderRow(
    props,
    ref
) {
    return (
        <div
            ref={ref}
            {...props}
            aria-hidden="true"
            className="relative flex flex-col"
        >
            <div className="relative z-10 h-24 animate-pulse">
                <div className="h-full rounded-md bg-muted" data-testid="loading-placeholder" />
            </div>
        </div>
    );
});

function CommentsList({
    items,
    totalItems,
    hasNextPage,
    isFetchingNextPage,
    fetchNextPage,
    resetKey,
    onAddFilter,
    isLoading,
    dislikesEnabled
}: {
    items: Comment[];
    totalItems: number;
    hasNextPage?: boolean;
    isFetchingNextPage?: boolean;
    fetchNextPage: () => void;
    resetKey: string;
    onAddFilter: (field: string, value: string, operator?: string) => void;
    isLoading?: boolean;
    dislikesEnabled: boolean;
}) {
    const parentRef = useRef<HTMLDivElement>(null);
    const {visibleItemCount, canLoadMore, loadMore} = useVirtualListWindow(totalItems, {resetKey});
    const [searchParams, setSearchParams] = useSearchParams();
    const [threadSidebarOpen, setThreadSidebarOpen] = useState(false);
    const [selectedThreadCommentId, setSelectedThreadCommentId] = useState<string | null>(null);

    const {mutate: hideComment} = useHideComment();
    const {mutate: showComment} = useShowComment();
    const {mutate: unpinComment} = useUnpinComment();
    const commentsPinningEnabled = useCommentsPinningEnabled();

    const handleCloseSidebar = (open: boolean) => {
        setThreadSidebarOpen(open);
        if (!open) {
            // Remove thread param from URL when sidebar closes
            const newParams = new URLSearchParams(searchParams);
            newParams.delete('thread');
            setSearchParams(newParams, {replace: true});
        }
    };

    // Check for thread query parameter and open sidebar
    useEffect(() => {
        const threadParam = searchParams.get('thread');
        if (threadParam) {
            // Parse format: "is:comment-id"
            const match = threadParam.match(/^is:(.+)$/);
            if (match && match[1]) {
                const threadId = match[1];
                setSelectedThreadCommentId(threadId);
                setThreadSidebarOpen(true);
            } else {
                // No valid thread param, close sidebar
                setThreadSidebarOpen(false);
                setSelectedThreadCommentId(null);
            }
        } else {
            // No thread param, close sidebar
            setThreadSidebarOpen(false);
            setSelectedThreadCommentId(null);
        }
    }, [searchParams]);

    // Restore scroll position when navigating back from filtered views
    useScrollRestoration({parentRef, isLoading});

    const {visibleItems, spaceBefore, spaceAfter} = useInfiniteVirtualScroll({
        items,
        totalItems: visibleItemCount,
        hasNextPage,
        isFetchingNextPage,
        fetchNextPage,
        parentRef
    });

    return (
        <TooltipProvider>
            <div ref={parentRef} className="overflow-hidden border-t">
                <div
                    className="flex flex-col"
                    data-testid="comments-list"
                >
                    <div className="flex flex-col">
                        <SpacerRow height={spaceBefore} />
                        {visibleItems.map(({key, virtualItem, item, props}) => {
                            const shouldRenderPlaceholder =
                            virtualItem.index > items.length - 1;

                            if (shouldRenderPlaceholder) {
                                return <PlaceholderRow key={key} {...props} />;
                            }

                            return (
                                <div
                                    key={key}
                                    {...props}
                                    className='grid w-full grid-cols-1 items-start justify-between gap-4 border-b p-3 hover:bg-table-row-hover md:p-5 lg:grid-cols-[minmax(0,1fr)_144px]'
                                    data-testid="comment-list-row"
                                    onClick={() => {
                                    // Close sidebar when clicking on a comment in the main list
                                        if (threadSidebarOpen) {
                                            handleCloseSidebar(false);
                                        }
                                    }}
                                >
                                    <div className='flex items-start gap-3'>
                                        <Avatar
                                            className={cn('mt-0.5 size-6 md:size-8', item.status === 'hidden' && 'opacity-50')}
                                            email={item.member?.email}
                                            name={item.member?.name}
                                            src={item.member?.avatar_image}
                                        />

                                        <div className='flex min-w-0 flex-col gap-3'>
                                            <div>
                                                <CommentHeader
                                                    canComment={item.member?.can_comment}
                                                    createdAt={item.created_at}
                                                    isHidden={item.status === 'hidden'}
                                                    isPinned={commentsPinningEnabled && item.pinned}
                                                    memberId={item.member?.id}
                                                    memberName={item.member?.name}
                                                    postTitle={item.post?.title}
                                                    onAuthorClick={item.member?.id ? () => onAddFilter('author', item.member!.id) : undefined}
                                                    onPostClick={item.post?.id ? () => onAddFilter('post', item.post!.id) : undefined}
                                                    onUnpinClick={commentsPinningEnabled ? () => unpinComment({id: item.id}) : undefined}
                                                />

                                                {item.in_reply_to_snippet && (
                                                    <div className={`mb-1 line-clamp-1 max-w-3xl ${item.status === 'hidden' && 'opacity-50'}`}>
                                                        <span className="text-muted-foreground">Replied to:</span>&nbsp;
                                                        <Link
                                                            className="text-sm font-normal text-muted-foreground hover:text-foreground"
                                                            data-testid="replied-to-link"
                                                            to={buildThreadLink(searchParams, item.in_reply_to_id || item.parent_id) || ''}
                                                            onClick={(e) => {
                                                                e.stopPropagation();
                                                            }}
                                                        >
                                                            {item.in_reply_to_snippet}
                                                        </Link>
                                                    </div>
                                                )}
                                            </div>

                                            <CommentContent item={item} />

                                            <div className="flex flex-row flex-nowrap items-center gap-3">
                                                {item.status === 'published' && (
                                                    <Button className='text-foreground' size="sm" variant="outline" onClick={() => hideComment({id: item.id})}>
                                                        <LucideIcon.EyeOff/>
                                                    Hide
                                                    </Button>
                                                )}
                                                {item.status === 'hidden' && (
                                                    <Button className='text-foreground' size="sm" variant="outline" onClick={() => showComment({id: item.id})}>
                                                        <LucideIcon.Eye/>
                                                    Show
                                                    </Button>
                                                )}
                                                <CommentMetrics
                                                    className="ml-2"
                                                    comment={item}
                                                    dislikesEnabled={dislikesEnabled}
                                                />
                                                <CommentMenu
                                                    comment={item}
                                                />
                                            </div>
                                        </div>
                                    </div>

                                    <div>
                                        {item.post?.feature_image ? (
                                            <img
                                                alt={item.post.title || 'Post feature image'}
                                                className={`hidden aspect-video w-36 rounded object-cover lg:block ${item.status === 'hidden' && 'opacity-50'}`}
                                                src={item.post.feature_image}
                                            />
                                        ) : null}
                                    </div>
                                </div>
                            );
                        })}
                        <SpacerRow height={spaceAfter} />
                    </div>
                </div>

                {canLoadMore && (
                    <LoadMoreButton isLoading={isFetchingNextPage} onClick={loadMore} />
                )}

                <CommentThreadSidebar
                    commentId={selectedThreadCommentId}
                    dislikesEnabled={dislikesEnabled}
                    open={threadSidebarOpen}
                    onOpenChange={handleCloseSidebar}
                />
            </div>
        </TooltipProvider>
    );
}

export default CommentsList;
