import { useState, useEffect, useRef } from "react";
import { Box, ScrollArea, Text, ActionIcon } from "@mantine/core";
import { useViewer } from "@app/contexts/ViewerContext";
import { PrivateContent } from "@app/components/shared/PrivateContent";
import LocalIcon from "@app/components/shared/LocalIcon";
import ViewListIcon from "@mui/icons-material/ViewList";
import "@app/components/viewer/SidebarBase.css";

interface ThumbnailSidebarProps {
  visible: boolean;
  onToggle: () => void;
  activeFileId?: string | null;
}

export function ThumbnailSidebar({
  visible,
  onToggle,
  activeFileId,
}: ThumbnailSidebarProps) {
  const { getScrollState, scrollActions, getThumbnailAPI } = useViewer();
  const [thumbnails, setThumbnails] = useState<{ [key: number]: string }>({});

  const scrollState = getScrollState();
  const thumbnailAPI = getThumbnailAPI();

  // Clear thumbnails when active file changes
  useEffect(() => {
    // Revoke old blob URLs to prevent memory leaks
    Object.values(thumbnails).forEach((thumbUrl) => {
      if (typeof thumbUrl === "string" && thumbUrl.startsWith("blob:")) {
        URL.revokeObjectURL(thumbUrl);
      }
    });
    setThumbnails({});
  }, [activeFileId]);

  // Keep a ref to thumbnails for cleanup on unmount
  const thumbnailsRef = useRef(thumbnails);
  useEffect(() => {
    thumbnailsRef.current = thumbnails;
  }, [thumbnails]);

  // Clear thumbnails when sidebar closes and revoke blob URLs to prevent memory leaks
  useEffect(() => {
    if (!visible) {
      Object.values(thumbnailsRef.current).forEach((thumbUrl) => {
        // Only revoke if it's a blob URL (not 'error')
        if (typeof thumbUrl === "string" && thumbUrl.startsWith("blob:")) {
          URL.revokeObjectURL(thumbUrl);
        }
      });
      setThumbnails({});
    }
  }, [visible]);

  // Cleanup all blob URLs on unmount to prevent memory leaks
  useEffect(() => {
    return () => {
      Object.values(thumbnailsRef.current).forEach((thumbUrl) => {
        if (typeof thumbUrl === "string" && thumbUrl.startsWith("blob:")) {
          URL.revokeObjectURL(thumbUrl);
        }
      });
    };
  }, []);

  // Generate thumbnails when sidebar becomes visible
  useEffect(() => {
    if (!visible || scrollState.totalPages === 0) return;
    if (!thumbnailAPI) return;

    let isCancelled = false;

    const generateThumbnails = async () => {
      const allPages = Array.from(
        { length: scrollState.totalPages },
        (_, i) => i,
      );
      const currentPage = scrollState.currentPage - 1;

      // Group pages by priority:
      // 1. Current page
      // 2. Visible neighbors (current +/- 3)
      // 3. Everything else
      const prioritized = [
        ...allPages.filter((i) => i === currentPage),
        ...allPages.filter(
          (i) => i !== currentPage && Math.abs(i - currentPage) <= 3,
        ),
        ...allPages.filter((i) => Math.abs(i - currentPage) > 3),
      ];

      const CONCURRENCY_LIMIT = 3;
      const queue = [...prioritized];

      const processNext = async () => {
        if (queue.length === 0 || isCancelled) return;
        const pageIndex = queue.shift()!;

        if (thumbnailsRef.current[pageIndex]) {
          await processNext();
          return;
        }

        try {
          const thumbTask = thumbnailAPI.renderThumb(pageIndex, 1.0);
          const thumbBlob = await thumbTask.toPromise();
          if (isCancelled) {
            // If cancelled during generation, revoke the new URL
            return;
          }
          const thumbUrl = URL.createObjectURL(thumbBlob);

          setThumbnails((prev) => ({
            ...prev,
            [pageIndex]: thumbUrl,
          }));
        } catch (error) {
          console.error(
            "Failed to generate thumbnail for page",
            pageIndex + 1,
            error,
          );
          if (!isCancelled) {
            setThumbnails((prev) => ({
              ...prev,
              [pageIndex]: "error",
            }));
          }
        }

        await processNext();
      };

      // Start initial concurrent batch
      const workers = Array.from({ length: CONCURRENCY_LIMIT }, () =>
        processNext(),
      );
      await Promise.all(workers);
    };

    generateThumbnails();

    return () => {
      isCancelled = true;
    };
  }, [visible, scrollState.totalPages, thumbnailAPI, scrollState.currentPage]);

  const handlePageClick = (pageIndex: number) => {
    const pageNumber = pageIndex + 1; // Convert to 1-based
    scrollActions.scrollToPage(pageNumber);
  };

  return (
    <>
      {/* Thumbnail Sidebar */}
      {visible && (
        <Box
          className="sidebar-base"
          style={{
            position: "fixed",
            right: 0,
            top: 0,
            bottom: 0,
            width: "15rem",
            zIndex: 998,
          }}
        >
          <div className="sidebar-base__header">
            <div className="sidebar-base__header-title">
              <span className="sidebar-base__header-icon">
                <ViewListIcon fontSize="small" />
              </span>
              <Text
                fw={600}
                size="sm"
                tt="uppercase"
                lts={0.5}
                style={{ flex: 1 }}
              >
                Pages
              </Text>
            </div>
            <ActionIcon
              variant="subtle"
              size="sm"
              color="gray"
              onClick={onToggle}
              aria-label="Close thumbnails sidebar"
              title="Close thumbnails"
            >
              <LocalIcon icon="close-rounded" width="1.1rem" height="1.1rem" />
            </ActionIcon>
          </div>
          {/* Thumbnails Container */}
          <ScrollArea style={{ flex: 1 }}>
            <Box p="sm">
              <div
                style={{
                  display: "flex",
                  flexDirection: "column",
                  gap: "12px",
                }}
              >
                {Array.from(
                  { length: scrollState.totalPages },
                  (_, pageIndex) => (
                    <Box
                      key={pageIndex}
                      onClick={() => handlePageClick(pageIndex)}
                      style={{
                        cursor: "pointer",
                        borderRadius: "8px",
                        padding: "8px",
                        backgroundColor:
                          scrollState.currentPage === pageIndex + 1
                            ? "var(--color-primary-100)"
                            : "transparent",
                        border:
                          scrollState.currentPage === pageIndex + 1
                            ? "2px solid var(--color-primary-500)"
                            : "2px solid transparent",
                        transition: "all 0.2s ease",
                        display: "flex",
                        flexDirection: "column",
                        alignItems: "center",
                        gap: "8px",
                      }}
                      onMouseEnter={(e) => {
                        if (scrollState.currentPage !== pageIndex + 1) {
                          e.currentTarget.style.backgroundColor =
                            "var(--hover-bg)";
                        }
                      }}
                      onMouseLeave={(e) => {
                        if (scrollState.currentPage !== pageIndex + 1) {
                          e.currentTarget.style.backgroundColor = "transparent";
                        }
                      }}
                    >
                      {/* Thumbnail Image */}
                      {thumbnails[pageIndex] &&
                      thumbnails[pageIndex] !== "error" ? (
                        <PrivateContent>
                          <img
                            src={thumbnails[pageIndex]}
                            alt={`Page ${pageIndex + 1} thumbnail`}
                            style={{
                              maxWidth: "100%",
                              height: "auto",
                              borderRadius: "4px",
                              boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)",
                              border: "1px solid var(--border-subtle)",
                            }}
                          />
                        </PrivateContent>
                      ) : thumbnails[pageIndex] === "error" ? (
                        <div
                          style={{
                            width: "11.5rem",
                            height: "15rem",
                            backgroundColor: "var(--color-red-50)",
                            border: "1px solid var(--color-red-200)",
                            borderRadius: "4px",
                            display: "flex",
                            alignItems: "center",
                            justifyContent: "center",
                            color: "var(--color-red-500)",
                            fontSize: "12px",
                          }}
                        >
                          Failed
                        </div>
                      ) : (
                        <div
                          style={{
                            width: "11.5rem",
                            height: "15rem",
                            backgroundColor: "var(--bg-muted)",
                            border: "1px solid var(--border-subtle)",
                            borderRadius: "4px",
                            display: "flex",
                            alignItems: "center",
                            justifyContent: "center",
                            color: "var(--text-muted)",
                            fontSize: "12px",
                          }}
                        >
                          Loading...
                        </div>
                      )}

                      {/* Page Number */}
                      <div
                        style={{
                          fontSize: "12px",
                          fontWeight: 500,
                          color:
                            scrollState.currentPage === pageIndex + 1
                              ? "var(--color-primary-500)"
                              : "var(--text-muted)",
                        }}
                      >
                        Page {pageIndex + 1}
                      </div>
                    </Box>
                  ),
                )}
              </div>
            </Box>
          </ScrollArea>
        </Box>
      )}
    </>
  );
}
