import {useEffect, useState} from 'react';
import {Badge} from '@/components/ui/badge';
import {Button} from '@/components/ui/button';
import {Checkbox} from '@/components/ui/checkbox';
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from '@/components/ui/table';
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from '@/components/ui/tooltip';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import {ChevronLeft, ChevronRight, Download, FileIcon, FolderIcon, Loader2, MoreVertical, Trash2} from 'lucide-react';
import {Select, SelectOption} from '@/components/ui/select';
import {formatBytes} from '@/lib/utils';
import {formatRelativeTime, getFileType} from '@/lib/file-utils';
import type {S3Object} from '@/types';

interface ObjectsTableProps {
  objects: S3Object[];
  currentPath: string;
  searchQuery: string;
  selectedFileKeys: Set<string>;
  isDragActive: boolean;
  isLoading?: boolean;
  isTruncated?: boolean;
  nextContinuationToken?: string;
  itemsPerPage: number;
  onNavigateToFolder: (key: string) => void;
  onDeleteObject: (object: S3Object) => void;
  onToggleFileSelection: (key: string) => void;
  onSelectAllFiles: () => void;
  onPageChange: (token?: string) => void;
  onItemsPerPageChange: (count: number) => void;
  initialPageToken?: string;
  initialItemsPerPage?: number;
}

type SortColumn = 'name' | 'size' | 'modified';
type SortDirection = 'asc' | 'desc';

export function ObjectsTable({
  objects,
  currentPath,
  searchQuery,
  selectedFileKeys,
  isDragActive,
  isLoading = false,
  isTruncated = false,
  nextContinuationToken,
  itemsPerPage,
  onNavigateToFolder,
  onDeleteObject,
  onToggleFileSelection,
  onSelectAllFiles,
  onPageChange,
  onItemsPerPageChange,
  initialPageToken,
  initialItemsPerPage,
}: ObjectsTableProps) {
  const [sortColumn, setSortColumn] = useState<SortColumn>('name');
  const [sortDirection, setSortDirection] = useState<SortDirection>('asc');
  const [filteredObjects, setFilteredObjects] = useState<S3Object[]>([]);
  // Store tokens for each page: [undefined (page 1), token1 (page 2), token2 (page 3), ...]
  const [pageTokens, setPageTokens] = useState<(string | undefined)[]>([undefined]);
  const [currentPageIndex, setCurrentPageIndex] = useState(0);
  const [initialized, setInitialized] = useState(false);

  // Initialize from URL params on first load
  useEffect(() => {
    if (!initialized && initialItemsPerPage && initialItemsPerPage !== itemsPerPage) {
      onItemsPerPageChange(initialItemsPerPage);
      setInitialized(true);
    }
    if (!initialized && initialPageToken && initialPageToken !== nextContinuationToken) {
      // If we have an initial page token, trigger page change
      onPageChange(initialPageToken);
      setInitialized(true);
    }
    if (!initialized && !initialPageToken && !initialItemsPerPage) {
      setInitialized(true);
    }
  }, [initialized, initialPageToken, initialItemsPerPage, itemsPerPage, nextContinuationToken, onPageChange, onItemsPerPageChange]);

  const sortObjects = (objList: S3Object[]): S3Object[] => {
    const sorted = [...objList].sort((a, b) => {
      // Always put folders before files
      const aIsFolder = a.isFolder ? 1 : 0;
      const bIsFolder = b.isFolder ? 1 : 0;
      if (aIsFolder !== bIsFolder) {
        return bIsFolder - aIsFolder;
      }

      let compareValue = 0;
      switch (sortColumn) {
        case 'name': {
          const aName = a.key.replace(currentPath, '').replace('/', '').toLowerCase();
          const bName = b.key.replace(currentPath, '').replace('/', '').toLowerCase();
          compareValue = aName.localeCompare(bName);
          break;
        }
        case 'size':
          compareValue = a.size - b.size;
          break;
        case 'modified': {
          const aDate = new Date(a.lastModified).getTime();
          const bDate = new Date(b.lastModified).getTime();
          compareValue = aDate - bDate;
          break;
        }
      }

      return sortDirection === 'asc' ? compareValue : -compareValue;
    });

    return sorted;
  };

  useEffect(() => {
    const filtered = objects.filter((obj) =>
      obj.key.toLowerCase().includes(searchQuery.toLowerCase())
    );
    const sorted = sortObjects(filtered);
    setFilteredObjects(sorted);
    // Reset pagination when path/search changes
    setPageTokens([undefined]);
    setCurrentPageIndex(0);
  }, [searchQuery, objects, sortColumn, sortDirection, currentPath]);

  // Update page tokens when we get a new next token
  useEffect(() => {
    if (nextContinuationToken && isTruncated) {
      setPageTokens(prev => {
        const newTokens = [...prev];
        // Only add the token if we don't have it yet
        const nextIndex = currentPageIndex + 1;
        if (nextIndex >= newTokens.length) {
          newTokens[nextIndex] = nextContinuationToken;
        }
        return newTokens;
      });
    }
  }, [nextContinuationToken, isTruncated, currentPageIndex]);

  const hasPrevious = currentPageIndex > 0;
  const hasNext = isTruncated;

  const handleNextPage = () => {
    if (hasNext && nextContinuationToken) {
      const nextIndex = currentPageIndex + 1;
      setCurrentPageIndex(nextIndex);
      onPageChange(nextContinuationToken);
      window.scrollTo({ top: 0, behavior: 'smooth' });
    }
  };

  const handlePreviousPage = () => {
    if (hasPrevious) {
      const prevIndex = currentPageIndex - 1;
      setCurrentPageIndex(prevIndex);
      const previousToken = pageTokens[prevIndex];
      onPageChange(previousToken);
      window.scrollTo({ top: 0, behavior: 'smooth' });
    }
  };

  const handleItemsPerPageChange = (value: string) => {
    onItemsPerPageChange(Number(value));
    setPageTokens([undefined]); // Reset to first page
    setCurrentPageIndex(0);
  };

  const handleSort = (column: SortColumn) => {
    if (sortColumn === column) {
      setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc');
    } else {
      setSortColumn(column);
      setSortDirection('asc');
    }
  };

  return (
    <>
      <div className="overflow-x-auto">
        <Table>
          <TableHeader>
          <TableRow>
            <TableHead className="w-[50px]">
              <Checkbox
                checked={
                  filteredObjects.filter(obj => !obj.isFolder).length > 0 &&
                  selectedFileKeys.size === filteredObjects.filter(obj => !obj.isFolder).length
                }
                onCheckedChange={onSelectAllFiles}
                aria-label="Select all files"
              />
            </TableHead>
          <TableHead
            className="cursor-pointer hover:bg-muted/50"
            onClick={() => handleSort('name')}
          >
            Objects {sortColumn === 'name' && (sortDirection === 'asc' ? '↑' : '↓')}
          </TableHead>
          <TableHead className="hidden sm:table-cell">Type</TableHead>
          <TableHead className="hidden md:table-cell">Storage Class</TableHead>
          <TableHead
            className="cursor-pointer hover:bg-muted/50"
            onClick={() => handleSort('size')}
          >
            Size {sortColumn === 'size' && (sortDirection === 'asc' ? '↑' : '↓')}
          </TableHead>
          <TableHead
            className="cursor-pointer hover:bg-muted/50"
            onClick={() => handleSort('modified')}
          >
            Modified {sortColumn === 'modified' && (sortDirection === 'asc' ? '↑' : '↓')}
          </TableHead>
          <TableHead className="w-[50px]"></TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {isLoading ? (
          <TableRow>
            <TableCell colSpan={7} className="text-center py-12">
              <div className="flex items-center justify-center gap-2 text-muted-foreground">
                <Loader2 className="h-5 w-5 animate-spin" />
                <span>Loading objects...</span>
              </div>
            </TableCell>
          </TableRow>
        ) : filteredObjects.length === 0 ? (
          <TableRow>
            <TableCell colSpan={7} className="text-center py-12 text-muted-foreground">
              {searchQuery
                ? 'No objects found matching your search'
                : isDragActive
                ? 'Drop files or folders here'
                : 'No objects in this location'}
            </TableCell>
          </TableRow>
        ) : (
          filteredObjects.map((obj) => (
            <TableRow key={obj.key}>
              <TableCell className="w-[50px]">
                {obj.isFolder ? (
                  <Checkbox
                    disabled
                    checked={false}
                    className="opacity-50 cursor-not-allowed bg-muted"
                    aria-label="Folders cannot be selected"
                  />
                ) : (
                  <Checkbox
                    checked={selectedFileKeys.has(obj.key)}
                    onCheckedChange={() => onToggleFileSelection(obj.key)}
                    aria-label={`Select file ${obj.key}`}
                  />
                )}
              </TableCell>
              <TableCell>
                <div className="flex items-center gap-2">
                  {obj.isFolder ? (
                    <FolderIcon className="h-4 w-4 text-muted-foreground" />
                  ) : (
                    <FileIcon className="h-4 w-4 text-muted-foreground" />
                  )}
                  {obj.isFolder ? (
                    <button
                      onClick={() => onNavigateToFolder(obj.key)}
                      className="font-medium cursor-pointer underline hover:text-primary"
                    >
                      {obj.key.replace(currentPath, '').replace('/', '')}
                    </button>
                  ) : (
                    <span className="font-medium">
                      {obj.key.replace(currentPath, '')}
                    </span>
                  )}
                </div>
              </TableCell>
              <TableCell className="hidden sm:table-cell">
                {obj.isFolder ? 'Directory' : getFileType(obj.key.replace(currentPath, ''))}
              </TableCell>
              <TableCell className="hidden md:table-cell">
                {obj.storageClass && (
                  <Badge variant="secondary">{obj.storageClass}</Badge>
                )}
              </TableCell>
              <TableCell>{obj.isFolder ? null : formatBytes(obj.size)}</TableCell>
              <TableCell>
                {obj.lastModified ?
                <TooltipProvider>
                  <Tooltip>
                    <TooltipTrigger asChild>
                      <div className="decoration-dashed decoration-1 underline underline-offset-6 cursor-pointer text-muted-foreground hover:text-foreground transition-colors">
                        {new Date(obj.lastModified).toLocaleDateString('en-GB', {
                          day: '2-digit',
                          month: 'short',
                          year: 'numeric',
                        })} {new Date(obj.lastModified).toLocaleTimeString('en-GB', {
                          hour: '2-digit',
                          minute: '2-digit',
                          second: '2-digit',
                          hour12: false,
                        })} CET
                      </div>
                    </TooltipTrigger>
                    <TooltipContent>
                      <div className="space-y-1 min-w-max">
                        <div className="flex gap-3 items-center">
                          <span className="text-sm text-gray-400 w-20 text-right">UTC</span>
                          <span className="text-sm text-white">
                            {new Date(obj.lastModified).toLocaleString('en-GB', {
                              day: '2-digit',
                              month: 'short',
                              year: 'numeric',
                              hour: '2-digit',
                              minute: '2-digit',
                              second: '2-digit',
                              hour12: false,
                              timeZone: 'UTC',
                            })} UTC
                          </span>
                        </div>
                        <div className="flex gap-3 items-center">
                          <span className="text-sm text-gray-400 w-20 text-right">Relative</span>
                          <span className="text-sm text-white">
                            {formatRelativeTime(new Date(obj.lastModified))}
                          </span>
                        </div>
                        <div className="flex gap-3 items-center">
                          <span className="text-sm text-gray-400 w-20 text-right">Timestamp</span>
                          <span className="text-sm text-white font-mono">
                            {new Date(obj.lastModified).toISOString()}
                          </span>
                        </div>
                      </div>
                    </TooltipContent>
                  </Tooltip>
                </TooltipProvider>: null}
              </TableCell>
              <TableCell>
                {!obj.isFolder && (
                  <DropdownMenu>
                    <DropdownMenuTrigger>
                      <Button variant="ghost" size="icon" className="-m-6 top-1 relative">
                        <MoreVertical className="h-4 w-4" />
                      </Button>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent align="end">
                      <DropdownMenuItem>
                        <Download className="h-4 w-4" />
                        Download
                      </DropdownMenuItem>
                      <DropdownMenuSeparator />
                      <DropdownMenuItem
                        className="text-destructive"
                        onClick={() => onDeleteObject(obj)}
                      >
                        <Trash2 className="h-4 w-4" />
                        Delete
                      </DropdownMenuItem>
                    </DropdownMenuContent>
                  </DropdownMenu>
                )}
              </TableCell>
            </TableRow>
          ))
        )}
      </TableBody>
    </Table>
      </div>

    {/* Pagination Controls */}
    {(filteredObjects.length > 0 || hasPrevious) && (
      <div className="flex flex-col sm:flex-row items-center justify-between gap-4 px-4 py-4 border-t bg-background">
        {/* Items per page selector */}
        <div className="flex items-center gap-2 text-sm relative z-10">
          <span className="text-muted-foreground">Items per page:</span>
          <Select value={itemsPerPage.toString()} onChange={handleItemsPerPageChange}>
            <SelectOption value="10">10</SelectOption>
            <SelectOption value="25">25</SelectOption>
            <SelectOption value="50">50</SelectOption>
            <SelectOption value="100">100</SelectOption>
            <SelectOption value="200">200</SelectOption>
          </Select>
        </div>

        {/* Pagination info and controls */}
        <div className="flex items-center gap-4">
          <span className="text-sm text-muted-foreground">
            Page {currentPageIndex + 1} • Showing {filteredObjects.length} item{filteredObjects.length !== 1 ? 's' : ''}
          </span>

          <div className="flex items-center gap-2">
            <Button
              variant={hasPrevious ? "default": "default_disabled"}
              size="sm"
              onClick={handlePreviousPage}
              disabled={!hasPrevious}
              className="h-8"
            >
              <ChevronLeft className="h-4 w-4 mr-1" />
              Previous
            </Button>

            <Button
                variant={hasNext ? "default": "default_disabled"}
              size="sm"
              onClick={handleNextPage}
              disabled={!hasNext}
              className="h-8"
            >
              Next
              <ChevronRight className="h-4 w-4 ml-1" />
            </Button>
          </div>
        </div>
      </div>
    )}
    </>
  );
}
