'use client';

import { useState, useEffect, useCallback, useRef } from 'react';
import { FixedSizeGrid } from 'react-window';
import { Card, CardContent } from '@/components/ui/card';
import { StarRating } from '@/components/star-rating';
import { Film, Image as ImageIcon, HardDrive, Search, Bookmark } from 'lucide-react';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';

interface MediaItem {
  id: number;
  title: string;
  path: string;
  size: number;
  thumbnail: string;
  type: string;
  bookmark_count: number;
  avg_rating: number;
  star_count: number;
}

interface PaginationInfo {
  total: number;
  limit: number;
  offset: number;
  hasMore: boolean;
}

interface VirtualizedMediaGridProps {
  type: 'video' | 'photo' | 'bookmark';
  onItemClick: (item: MediaItem) => void;
  onBookmark: (id: number) => Promise<void>;
  onUnbookmark: (id: number) => Promise<void>;
  onRate: (id: number, rating: number) => Promise<void>;
}

export default function VirtualizedMediaGrid({ 
  type, 
  onItemClick, 
  onBookmark, 
  onUnbookmark, 
  onRate 
}: VirtualizedMediaGridProps) {
  const [items, setItems] = useState<MediaItem[]>([]);
  const [loading, setLoading] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');
  const [pagination, setPagination] = useState<PaginationInfo>({
    total: 0,
    limit: 50,
    offset: 0,
    hasMore: true
  });
  const [isLoadingMore, setIsLoadingMore] = useState(false);
  const [containerWidth, setContainerWidth] = useState(0);
  
  const observerTarget = useRef<HTMLDivElement>(null);
  const loadingRef = useRef(false);
  const containerRef = useRef<HTMLDivElement>(null);

  const formatFileSize = (bytes: number) => {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  };

  const formatFilePath = (path: string) => {
    if (!path) return '';
    
    const lastSlashIndex = path.lastIndexOf('/');
    const lastBackslashIndex = path.lastIndexOf('\\');
    const lastSeparatorIndex = Math.max(lastSlashIndex, lastBackslashIndex);
    
    if (lastSeparatorIndex === -1) {
      return path;
    }
    
    const directory = path.substring(0, lastSeparatorIndex);
    const filename = path.substring(lastSeparatorIndex + 1);
    
    if (directory.length <= 40) {
      return `${directory}/${filename}`;
    }
    
    const maxDirLength = 35;
    const startLength = Math.floor(maxDirLength / 2);
    const endLength = maxDirLength - startLength - 3;
    
    const truncatedDir = directory.length > maxDirLength 
      ? `${directory.substring(0, startLength)}...${directory.substring(directory.length - endLength)}`
      : directory;
    
    return `${truncatedDir}/${filename}`;
  };

  const fetchItems = useCallback(async (offset: number, search?: string) => {
    if (loadingRef.current) return;
    
    loadingRef.current = true;
    setIsLoadingMore(offset > 0);
    
    try {
      const params = new URLSearchParams({
        limit: '50',
        offset: offset.toString(),
        ...(search && { search })
      });

      const endpoint = type === 'bookmark' ? 'bookmarks' : `${type}s`;
      const response = await fetch(`/api/${endpoint}?${params}`);
      const data = await response.json();
      
      const itemsKey = type === 'bookmark' ? 'bookmarks' : `${type}s`;
      
      if (offset === 0) {
        setItems(data[itemsKey] || []);
      } else {
        setItems(prev => [...prev, ...(data[itemsKey] || [])]);
      }
      
      setPagination(data.pagination);
    } catch (error) {
      console.error(`Error fetching ${type}s:`, error);
    } finally {
      setLoading(false);
      setIsLoadingMore(false);
      loadingRef.current = false;
    }
  }, [type]);

  const handleSearch = useCallback((term: string) => {
    setSearchTerm(term);
    setItems([]);
    setPagination({
      total: 0,
      limit: 50,
      offset: 0,
      hasMore: true
    });
    fetchItems(0, term);
  }, [fetchItems]);

  const loadMoreItems = useCallback(() => {
    if (pagination.hasMore && !loadingRef.current) {
      fetchItems(pagination.offset + pagination.limit, searchTerm);
    }
  }, [pagination, searchTerm, fetchItems]);

  // Calculate responsive column count and width
  const getColumnCount = useCallback(() => {
    if (containerWidth === 0) return 6;
    if (containerWidth < 640) return 2;
    if (containerWidth < 768) return 3;
    if (containerWidth < 1024) return 4;
    if (containerWidth < 1280) return 5;
    if (containerWidth < 1536) return 6;
    return 7;
  }, [containerWidth]);

  const getColumnWidth = useCallback(() => {
    const cols = getColumnCount();
    // Account for padding (16px on each side) and gaps between cards (16px total per row)
    const availableWidth = containerWidth - 32; // 16px padding on each side
    const gapWidth = (cols - 1) * 16; // 16px gap between each column
    return Math.floor((availableWidth - gapWidth) / cols);
  }, [containerWidth, getColumnCount]);

  // Update container width on resize
  useEffect(() => {
    const updateWidth = () => {
      if (containerRef.current) {
        setContainerWidth(containerRef.current.offsetWidth);
      }
    };

    updateWidth();
    window.addEventListener('resize', updateWidth);
    return () => window.removeEventListener('resize', updateWidth);
  }, []);

  useEffect(() => {
    setLoading(true);
    fetchItems(0, searchTerm);
  }, [type]);

  // Disabled automatic loading to prevent premature batch loading
  // Users will manually click "Load More" button when they want more content

  const Cell = ({ columnIndex, rowIndex, style }: any) => {
    const columnCount = getColumnCount();
    const index = rowIndex * columnCount + columnIndex;
    const item = items[index];

    if (!item) return null;

    return (
      <div style={style} className="p-2">
        <Card 
          className="group hover:shadow-lg transition-all duration-300 hover:-translate-y-1 cursor-pointer border-border overflow-hidden h-full"
          onClick={() => onItemClick(item)}
        >
          <div className={`relative overflow-hidden bg-muted ${type === 'video' ? 'aspect-video' : 'aspect-square'}`}>
            <img
              src={item.thumbnail || (type === 'video' ? "/placeholder-video.svg" : "/placeholder-photo.svg")}
              alt={item.title}
              className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105"
              onError={(e) => {
                (e.target as HTMLImageElement).src = type === 'video' ? "/placeholder-video.svg" : "/placeholder-photo.svg";
              }}
            />
            <div className="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
            
            <div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
              <div className="w-10 h-10 bg-white/90 backdrop-blur-sm rounded-full flex items-center justify-center shadow-lg">
                {type === 'video' ? 
                  <Film className="h-5 w-5 text-foreground" /> : 
                  <ImageIcon className="h-5 w-5 text-foreground" />
                }
              </div>
            </div>

            <div className="absolute top-2 right-2">
              <div className="bg-black/70 backdrop-blur-sm rounded-full px-2 py-1">
                {type === 'video' ? 
                  <Film className="h-3 w-3 text-white" /> : 
                  <ImageIcon className="h-3 w-3 text-white" />
                }
              </div>
            </div>
          </div>
          
          <CardContent className="p-2.5">
            <h3 className="font-medium text-foreground text-sm line-clamp-2 mb-1.5 group-hover:text-primary transition-colors">
              {item.title || item.path.split('/').pop()}
            </h3>
            
            {(item.avg_rating > 0 || item.star_count > 0) && (
              <div className="mb-1.5">
                <StarRating 
                  rating={item.avg_rating || 0} 
                  count={item.star_count}
                  size="sm"
                  showCount={true}
                />
              </div>
            )}
            
            <div className="flex items-center gap-2 text-xs text-muted-foreground">
              <div className="flex items-center gap-1">
                <HardDrive className="h-3 w-3" />
                <span>{formatFileSize(item.size)}</span>
              </div>
            </div>
            <p 
              className="text-xs text-muted-foreground mt-1 line-clamp-1 cursor-help"
              title={item.path}
            >
              {formatFilePath(item.path)}
            </p>
          </CardContent>
        </Card>
      </div>
    );
  };

  const columnCount = getColumnCount();
  const columnWidth = getColumnWidth();
  const rowCount = Math.ceil(items.length / columnCount);

  // Calculate available height for the grid more precisely
  const getAvailableHeight = useCallback(() => {
    if (typeof window === 'undefined') return 600;
    
    // Calculate the actual header height and other UI elements
    const headerHeight = 180; // Title, description, search bar
    const bottomPadding = 120; // Load more button area
    const availableHeight = window.innerHeight - headerHeight - bottomPadding;
    
    // Ensure minimum height and maximum height
    return Math.max(Math.min(availableHeight, window.innerHeight - 100), 400);
  }, []);

  if (loading && items.length === 0) {
    return (
      <div className="h-screen flex flex-col overflow-hidden">
        <div className="flex-1 flex items-center justify-center">
          <div className="text-center">
            <div className="w-16 h-16 bg-gradient-to-br from-primary to-primary/80 rounded-2xl flex items-center justify-center mx-auto mb-4 animate-pulse shadow-lg">
              {type === 'video' ? 
                <Film className="h-8 w-8 text-primary-foreground" /> : 
                <ImageIcon className="h-8 w-8 text-primary-foreground" />
              }
            </div>
            <p className="text-muted-foreground font-medium">Loading {type}s...</p>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="h-screen flex flex-col overflow-hidden">
      <div ref={containerRef} className="flex-1 flex flex-col max-w-7xl mx-auto w-full overflow-hidden">
        {/* Header */}
        <div className="flex-shrink-0 p-6 pb-4">
          <div className="flex items-center gap-4 mb-4">
            <div className={`w-12 h-12 bg-gradient-to-br rounded-xl flex items-center justify-center shadow-lg ${
              type === 'video' ? 'from-red-500 to-red-600' : 
              type === 'photo' ? 'from-green-500 to-green-600' :
              'from-blue-500 to-blue-600'
            }`}>
              {type === 'video' ? 
                <Film className="h-6 w-6 text-white" /> : 
                type === 'photo' ? 
                <ImageIcon className="h-6 w-6 text-white" /> :
                <Bookmark className="h-6 w-6 text-white" />
              }
            </div>
            <div>
              <h1 className="text-3xl font-bold text-foreground tracking-tight capitalize">
                {type === 'bookmark' ? 'Bookmarked Items' : `${type}s`}
              </h1>
              <p className="text-muted-foreground">
                {pagination.total.toLocaleString()} {type === 'bookmark' ? 'item' : type}{pagination.total === 1 ? '' : 's'} in your library
              </p>
            </div>
          </div>

          {/* Search */}
          <div className="relative max-w-md">
            <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
            <Input
              placeholder={`Search ${type}s...`}
              value={searchTerm}
              onChange={(e) => handleSearch(e.target.value)}
              className="pl-10 bg-background border-border"
            />
          </div>
        </div>

        {/* Media Grid Container */}
        <div className="flex-1 relative overflow-hidden">
          {items.length > 0 && containerWidth > 0 ? (
            <div className="h-full relative overflow-hidden">
              <FixedSizeGrid
                columnCount={columnCount}
                columnWidth={columnWidth}
                height={getAvailableHeight()}
                rowCount={rowCount}
                rowHeight={300}
                width={containerWidth}
                itemData={items}
                className="custom-scrollbar"
              >
                {Cell}
              </FixedSizeGrid>
              
              {/* Fancy scroll indicator */}
              <div className="absolute right-2 top-1/2 transform -translate-y-1/2 w-2 h-32 bg-gradient-to-b from-primary/20 via-primary/40 to-primary/20 rounded-full opacity-0 hover:opacity-100 transition-opacity duration-300 pointer-events-none">
                <div className="w-full h-full bg-gradient-to-b from-primary/60 via-primary to-primary/60 rounded-full scroll-indicator"></div>
              </div>
              
              {pagination.hasMore && (
                <div className="flex justify-center py-8">
                  {isLoadingMore ? (
                    <div className="flex items-center gap-3">
                      <div className="animate-spin rounded-full h-6 w-6 border-b-2 border-primary"></div>
                      <span className="text-sm text-muted-foreground">Loading more {type === 'bookmark' ? 'items' : `${type}s`}...</span>
                    </div>
                  ) : (
                    <Button 
                      onClick={loadMoreItems}
                      disabled={loadingRef.current}
                      className="px-6 py-2"
                    >
                      Load More {type === 'bookmark' ? 'Items' : `${type}s`}
                    </Button>
                  )}
                </div>
              )}
            </div>
          ) : items.length === 0 ? (
            <div className="flex items-center justify-center h-full">
              <div className="text-center max-w-sm">
                <div className="w-16 h-16 bg-muted rounded-2xl flex items-center justify-center mx-auto mb-4">
                  <Search className="h-8 w-8 text-muted-foreground" />
                </div>
                <h3 className="text-xl font-semibold text-foreground mb-2">
                  No {type === 'bookmark' ? 'bookmarked items' : `${type}s`} found
                </h3>
                <p className="text-muted-foreground">
                  {searchTerm ? 'Try adjusting your search terms' : 
                   type === 'bookmark' ? 'Start bookmarking videos and photos to see them here' :
                   'Add media libraries and scan for content to get started'}
                </p>
              </div>
            </div>
          ) : (
            <div className="flex items-center justify-center h-full">
              <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}