"use client";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { Checkbox } from "@/components/ui/checkbox";
import { Button } from "@/components/ui/button";
import { Download, LoaderCircle, LoaderPinwheel } from "lucide-react";
import { useFiles } from "@/hooks/use-files";
import { FileFilters } from "@/components/file-filters";
import {
  getRowHeightPX,
  useRowHeightLocalStorage,
} from "@/components/table-row-height-switch";
import { type Column } from "@/components/table-column-filter";
import { cn } from "@/lib/utils";
import FileNotFount from "@/components/file-not-found";
import useSWRMutation from "swr/mutation";
import { POST } from "@/lib/api";
import FileRow from "@/components/file-row";
import { useVirtualizer } from "@tanstack/react-virtual";
import { type TelegramFile } from "@/lib/types";
import FileViewer from "@/components/file-viewer";

const COLUMNS: Column[] = [
  {
    id: "content",
    label: "Content",
    isVisible: true,
    className: "text-center",
  },
  { id: "type", label: "Type", isVisible: true, className: "w-16 text-center" },
  {
    id: "size",
    label: "Size",
    isVisible: true,
    className: "w-20 text-center",
  },
  {
    id: "status",
    label: "Status",
    isVisible: true,
    className: "w-32 text-center",
  },
  { id: "extra", label: "Extra", isVisible: true, className: "flex-1" },
  {
    id: "actions",
    label: "Actions",
    isVisible: true,
    className: "text-center w-40 min-w-40",
  },
];

interface FileTableProps {
  accountId: string;
  chatId: string;
}

export function FileTable({ accountId, chatId }: FileTableProps) {
  const [selectedFiles, setSelectedFiles] = useState<Set<number>>(new Set());
  const tableParentRef = useRef(null);
  const [columns, setColumns] = useState<Column[]>(COLUMNS);
  const [rowHeight, setRowHeight] = useRowHeightLocalStorage(
    "telegramFileList",
    "m",
  );
  const useFilesProps = useFiles(accountId, chatId);
  const { filters, handleFilterChange, isLoading, files, handleLoadMore } =
    useFilesProps;
  const [currentViewFile, setCurrentViewFile] = useState<TelegramFile | undefined>();
  const [viewerOpen, setViewerOpen] = useState(false);
  const {
    trigger: startDownloadMultiple,
    isMutating: startDownloadMultipleMutating,
  } = useSWRMutation(
    `/${accountId}/file/start-download-multiple`,
    (
      key,
      {
        arg,
      }: {
        arg: {
          chatId: number;
          files: Array<{ messageId: number; fileId: number }>;
        };
      },
    ) => POST(key, arg),
    {
      onSuccess: () => {
        setSelectedFiles(new Set());
      },
    },
  );
  const rowVirtual = useVirtualizer({
    count: files.length,
    getScrollElement: () => tableParentRef.current,
    estimateSize: (index) => {
      const file = files[index]!;
      const height = getRowHeightPX(rowHeight);

      if (
        file.downloadStatus === "idle" ||
        file.downloadStatus === "completed" ||
        file.size === 0
      ) {
        return height;
      }
      return height + 8;
    },
    paddingStart: 1,
    paddingEnd: 1,
  });

  useEffect(() => {
    rowVirtual.measure();
  }, [rowHeight, rowVirtual]);

  useEffect(() => {
    const [lastItem] = [...rowVirtual.getVirtualItems()].reverse();
    if (!lastItem) {
      return;
    }

    if (lastItem.index >= files.length - 1) {
      void handleLoadMore();
    }
    //eslint-disable-next-line
  }, [files.length, handleLoadMore, rowVirtual.getVirtualItems()]);

  useEffect(() => {
    if (files.length === 0 || !currentViewFile) {
      return;
    }
    const index = files.findIndex((f) => f.id === currentViewFile.id);
    if (index === -1) {
      setCurrentViewFile(undefined);
      return;
    }
    const file = files[index]!;
    if (currentViewFile.next === undefined && file.next !== undefined) {
      setCurrentViewFile(file);
    }
  }, [currentViewFile, files]);

  const dynamicClass = useMemo(() => {
    switch (rowHeight) {
      case "s":
        return {
          content: "h-6 w-6",
          contentCell: "w-16",
        };
      case "m":
        return {
          content: "h-20 w-20",
          contentCell: "w-24",
        };
      case "l":
        return {
          content: "h-60 w-60",
          contentCell: "w-64",
        };
    }
  }, [rowHeight]);

  const handleSelectAll = () => {
    if (selectedFiles.size === files.length) {
      setSelectedFiles(new Set());
    } else {
      setSelectedFiles(
        new Set(
          files
            .filter((file) => file.downloadStatus === "idle")
            .map((file) => file.id),
        ),
      );
    }
  };

  const handleSelectFile = (fileId: number) => {
    const newSelected = new Set(selectedFiles);
    if (newSelected.has(fileId)) {
      newSelected.delete(fileId);
    } else {
      newSelected.add(fileId);
    }
    setSelectedFiles(newSelected);
  };

  return (
    <>
      <FileFilters
        telegramId={accountId}
        chatId={chatId}
        filters={filters}
        onFiltersChange={handleFilterChange}
        columns={columns}
        onColumnConfigChange={setColumns}
        rowHeight={rowHeight}
        setRowHeight={setRowHeight}
      />
      {currentViewFile && (
        <FileViewer
          open={viewerOpen}
          onOpenChange={setViewerOpen}
          file={currentViewFile}
          onFileChange={setCurrentViewFile}
          {...useFilesProps}
        />
      )}
      <div className="h-[calc(100vh-13rem)] space-y-4 overflow-hidden">
        {selectedFiles.size > 0 && (
          <div className="flex items-center justify-between rounded-lg bg-muted/50 p-4">
            <span className="text-sm">
              {selectedFiles.size} {selectedFiles.size === 1 ? "file" : "files"}{" "}
              selected
            </span>
            <Button
              size="sm"
              onClick={() => {
                void startDownloadMultiple({
                  chatId: Number(chatId),
                  files: Array.from(selectedFiles).map((id) => {
                    const file = files.find((f) => f.id === id);
                    return {
                      messageId: file?.messageId ?? 0,
                      fileId: file?.id ?? 0,
                    };
                  }),
                });
              }}
              disabled={
                selectedFiles.size === 0 || startDownloadMultipleMutating
              }
            >
              {startDownloadMultipleMutating ? (
                <LoaderCircle
                  className="mr-2 h-4 w-4 animate-spin"
                  style={{ strokeWidth: "0.8px" }}
                />
              ) : (
                <>
                  <Download className="mr-2 h-4 w-4" />
                  Download Selected
                </>
              )}
            </Button>
          </div>
        )}

        <div
          className="relative h-full overflow-auto rounded-md border"
          ref={tableParentRef}
        >
          <div className="sticky top-0 z-20 flex h-10 items-center border-b bg-background/90 text-sm text-muted-foreground backdrop-blur-sm">
            <div className="w-[30px] text-center">
              <Checkbox
                checked={selectedFiles.size === files.length}
                onCheckedChange={handleSelectAll}
              />
            </div>
            {columns.map((col) =>
              col.isVisible ? (
                <div
                  key={col.id}
                  suppressHydrationWarning
                  className={cn(
                    col.className ?? "",
                    col.id === "content" ? dynamicClass.contentCell : "",
                  )}
                >
                  {col.label}
                </div>
              ) : null,
            )}
          </div>
          {files.length === 0 && isLoading && (
            <div className="sticky left-1/2 top-0 z-10 flex h-full w-full items-center justify-center bg-accent">
              <LoaderPinwheel
                className="h-8 w-8 animate-spin"
                style={{ strokeWidth: "0.8px" }}
              />
            </div>
          )}
          <div className="h-full">
            <div
              className={cn("relative w-full")}
              style={{ height: `${rowVirtual.getTotalSize()}px` }}
            >
              {files.length !== 0 &&
                rowVirtual.getVirtualItems().map((virtualRow) => {
                  const file = files[virtualRow.index]!;
                  return (
                    <FileRow
                      index={virtualRow.index}
                      className={cn(
                        "absolute left-0 top-0 flex w-full items-center",
                      )}
                      style={{
                        height: `${virtualRow.size}px`,
                        transform: `translateY(${virtualRow.start}px)`,
                      }}
                      ref={rowVirtual.measureElement}
                      file={file}
                      checked={selectedFiles.has(file.id)}
                      onCheckedChange={() => handleSelectFile(file.id)}
                      onFileClick={() => {
                        setCurrentViewFile(file);
                        setViewerOpen(true);
                      }}
                      properties={{
                        rowHeight: rowHeight,
                        dynamicClass,
                        columns,
                      }}
                      key={`${file.messageId}-${file.uniqueId}-${virtualRow.index}`}
                    />
                  );
                })}
            </div>
            {!isLoading && files.length === 0 && <FileNotFount />}
          </div>
        </div>
      </div>
    </>
  );
}
