import {
  ErrorBoundary,
  Suspense,
  type ErrorBoundaryFallbackProps,
} from '@suspensive/react';
import { SuspenseQuery } from '@suspensive/react-query';
import { QueryErrorResetBoundary, useMutation } from '@tanstack/react-query';

import { postMutations, postQueries, type Post } from '@/entities/post';
import { Button } from '@/shared/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/shared/ui/card';
import { openConfirmDialog } from '@/shared/ui/confirm-dialog';

const VISIBLE_COUNT = 6;

export const PostListPanel = () => {
  return (
    <Card>
      <CardHeader>
        <CardTitle>최근 글</CardTitle>
      </CardHeader>
      <CardContent>
        <QueryErrorResetBoundary>
          {({ reset }) => (
            <ErrorBoundary onReset={reset} fallback={PostListErrorFallback}>
              <Suspense fallback={<PostListSkeleton />}>
                <SuspenseQuery {...postQueries.list()}>
                  {({ data: posts }) => (
                    <ul className="space-y-1">
                      {posts.slice(0, VISIBLE_COUNT).map((post) => (
                        <PostListItem key={post.id} post={post} />
                      ))}
                    </ul>
                  )}
                </SuspenseQuery>
              </Suspense>
            </ErrorBoundary>
          )}
        </QueryErrorResetBoundary>
      </CardContent>
    </Card>
  );
};

const PostListItem = ({ post }: { post: Post }) => {
  const { mutate, isPending } = useMutation(postMutations.remove(post.id));

  const handleDelete = async () => {
    const confirmed = await openConfirmDialog({
      title: '글을 삭제할까요?',
      description: `“${post.title}”이(가) 삭제돼요. 이 작업은 되돌릴 수 없어요.`,
      confirmLabel: '삭제',
      tone: 'destructive',
    });

    if (!confirmed) {
      return;
    }

    mutate();
  };

  return (
    <li className="flex items-start justify-between gap-2 rounded-lg p-2 transition-colors hover:bg-muted">
      <div className="min-w-0">
        <p className="truncate text-sm font-medium">{post.title}</p>
        <p className="line-clamp-1 text-sm text-muted-foreground">
          {post.body}
        </p>
      </div>
      <Button
        variant="ghost"
        size="sm"
        onClick={() => {
          handleDelete();
        }}
        disabled={isPending}
      >
        {isPending ? '삭제 중…' : '삭제'}
      </Button>
    </li>
  );
};

const PostListErrorFallback = ({
  error,
  reset,
}: ErrorBoundaryFallbackProps) => {
  return (
    <div className="space-y-3 rounded-xl border p-6 text-center">
      <p className="text-sm font-medium">목록을 불러오지 못했어요.</p>
      <p className="text-sm text-muted-foreground">{error.message}</p>
      <Button variant="outline" onClick={reset}>
        다시 시도
      </Button>
    </div>
  );
};

const PostListSkeleton = () => {
  return (
    <div className="space-y-2" aria-busy="true">
      {Array.from({ length: VISIBLE_COUNT }, (_, index) => (
        <div key={index} className="h-12 animate-pulse rounded-lg bg-muted" />
      ))}
    </div>
  );
};
