import { useVirtualizer } from '@tanstack/react-virtual';
import { useRef, useCallback } from 'react';
import { useInfiniteQuery } from '@tanstack/react-query';
import { api, type Thread } from '@/api/client';
import { useUI } from '@/store/ui';
import { ThreadRow } from './ThreadRow';
import { queueMutation } from '@/sync/engine';
import { Archive, Trash2, MailOpen, Clock, X } from 'lucide-react';

type Props = { folderId: string };

export function ThreadList({ folderId }: Props) {
  const {
    accountId, selectedThreadId, selectThread,
    checkedThreadIds, toggleCheck, clearChecks,
  } = useUI();
  const parentRef = useRef<HTMLDivElement>(null);

  const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isPending } = useInfiniteQuery({
    queryKey: ['threads', folderId],
    queryFn: ({ pageParam }) =>
      api.threads.list(folderId, { limit: 50, before: pageParam as string | undefined }),
    getNextPageParam: (last) => last.next_cursor ?? undefined,
    initialPageParam: undefined as string | undefined,
    enabled: !!folderId,
  });

  const threads = data?.pages.flatMap((p) => p.threads) ?? [];

  const virtualizer = useVirtualizer({
    count: threads.length + (hasNextPage ? 1 : 0),
    getScrollElement: () => parentRef.current,
    estimateSize: () => 40,
    overscan: 12,
    onChange: (v) => {
      const lastItem = v.getVirtualItems().at(-1);
      if (!lastItem) return;
      if (lastItem.index >= threads.length - 1 && hasNextPage && !isFetchingNextPage) {
        fetchNextPage();
      }
    },
  });

  const handleStar = useCallback((e: React.MouseEvent, thread: Thread) => {
    e.stopPropagation();
    if (!accountId) return;
    queueMutation(accountId, 'flag', thread.id, { flagged: !thread.has_flagged });
  }, [accountId]);

  const handleCheck = useCallback((e: React.MouseEvent, threadId: string) => {
    e.stopPropagation();
    toggleCheck(threadId);
  }, [toggleCheck]);

  const handleArchive = useCallback((_: React.MouseEvent, thread: Thread) => {
    if (!accountId) return;
    queueMutation(accountId, 'move', thread.id, { folder_special_use: 'archive' });
  }, [accountId]);

  const handleDelete = useCallback((_: React.MouseEvent, thread: Thread) => {
    if (!accountId) return;
    queueMutation(accountId, 'move', thread.id, { folder_special_use: 'trash' });
  }, [accountId]);

  const handleMarkRead = useCallback((_: React.MouseEvent, thread: Thread) => {
    if (!accountId) return;
    queueMutation(accountId, 'flag', thread.id, { seen: thread.unread_count > 0 });
  }, [accountId]);

  const handleSnooze = useCallback((_: React.MouseEvent, _thread: Thread) => {
    // Snooze: Phase 3 — needs server support. No-op for now.
  }, []);

  const bulkAction = (op: 'archive' | 'trash' | 'read') => {
    if (!accountId) return;
    for (const id of checkedThreadIds) {
      if (op === 'archive') queueMutation(accountId, 'move', id, { folder_special_use: 'archive' });
      else if (op === 'trash') queueMutation(accountId, 'move', id, { folder_special_use: 'trash' });
      else if (op === 'read') queueMutation(accountId, 'flag', id, { seen: true });
    }
    clearChecks();
  };

  if (isPending) return <ThreadListSkeleton />;
  if (!threads.length) return (
    <div className="flex flex-col items-center justify-center h-full gap-2 text-gmail-text-secondary text-mail-sm">
      <div className="w-12 h-12 rounded-full bg-gmail-surface flex items-center justify-center mb-2">
        <MailOpen size={22} className="text-gmail-text-muted" />
      </div>
      <p>No conversations</p>
    </div>
  );

  return (
    <div ref={parentRef} className="h-full overflow-y-auto">
      {checkedThreadIds.size > 0 && (
        <div className="sticky top-0 z-20 flex items-center gap-1 px-4 py-1.5 bg-gmail-blue-focus border-b border-gmail-border">
          <button
            onClick={clearChecks}
            title="Clear selection"
            className="w-8 h-8 flex items-center justify-center rounded-full hover:bg-black/10 transition-colors"
          >
            <X size={18} className="text-gmail-text-secondary" />
          </button>
          <span className="text-mail-sm text-gmail-text-primary font-medium px-2">
            {checkedThreadIds.size} selected
          </span>
          <div className="w-px h-5 bg-gmail-border mx-1" />
          <BulkAction onClick={() => bulkAction('archive')} title="Archive">
            <Archive size={18} />
          </BulkAction>
          <BulkAction onClick={() => bulkAction('trash')} title="Delete">
            <Trash2 size={18} />
          </BulkAction>
          <BulkAction onClick={() => bulkAction('read')} title="Mark as read">
            <MailOpen size={18} />
          </BulkAction>
          <BulkAction onClick={() => {}} title="Snooze">
            <Clock size={18} />
          </BulkAction>
        </div>
      )}

      <div style={{ height: virtualizer.getTotalSize(), position: 'relative' }}>
        {virtualizer.getVirtualItems().map((vi) => {
          if (vi.index >= threads.length) {
            return (
              <div
                key="loader"
                style={{ position: 'absolute', top: vi.start, left: 0, right: 0, height: vi.size }}
                className="flex items-center justify-center"
              >
                <span className="text-gmail-text-muted text-mail-sm">Loading…</span>
              </div>
            );
          }

          const thread = threads[vi.index];
          return (
            <div
              key={thread.id}
              style={{ position: 'absolute', top: vi.start, left: 0, right: 0, height: vi.size }}
            >
              <ThreadRow
                thread={thread}
                isSelected={selectedThreadId === thread.id}
                isChecked={checkedThreadIds.has(thread.id)}
                onSelect={() => selectThread(thread.id)}
                onCheck={(e) => handleCheck(e, thread.id)}
                onStar={(e) => handleStar(e, thread)}
                onArchive={(e) => handleArchive(e, thread)}
                onDelete={(e) => handleDelete(e, thread)}
                onMarkRead={(e) => handleMarkRead(e, thread)}
                onSnooze={(e) => handleSnooze(e, thread)}
              />
            </div>
          );
        })}
      </div>
    </div>
  );
}

function BulkAction({
  onClick, title, children,
}: { onClick: () => void; title: string; children: React.ReactNode }) {
  return (
    <button
      onClick={onClick}
      title={title}
      className="w-9 h-9 flex items-center justify-center rounded-full text-gmail-text-secondary hover:bg-black/10 hover:text-gmail-text-primary transition-colors"
    >
      {children}
    </button>
  );
}

function ThreadListSkeleton() {
  return (
    <div>
      {Array.from({ length: 16 }).map((_, i) => (
        <div key={i} className="flex items-center gap-3 pl-6 pr-4 h-10 border-b border-gmail-border/60 animate-pulse">
          <div className="w-4 h-4 rounded bg-gray-200 flex-none" />
          <div className="w-4 h-4 rounded bg-gray-100 flex-none" />
          <div className="w-6 h-6 rounded-full bg-gray-200 flex-none" />
          <div className="w-32 h-3 rounded bg-gray-200 flex-none" />
          <div className="flex-1 h-3 rounded bg-gray-100" />
          <div className="w-12 h-3 rounded bg-gray-100 flex-none" />
        </div>
      ))}
    </div>
  );
}
