import 'package:flutter/material.dart';

import '../services/thumbnail_service.dart';

/// Vertical sidebar showing page thumbnails for quick navigation.
///
/// Thumbnails are lazily generated and cached on disk. The current page is
/// highlighted with a blue border, and bookmarked pages show a colored dot.
class PageThumbnailSidebar extends StatefulWidget {
  final String documentId;
  final String filePath;
  final int pageCount;
  final int currentPage;
  final ValueChanged<int> onPageTap;
  final Set<int> bookmarkedPages;

  const PageThumbnailSidebar({
    super.key,
    required this.documentId,
    required this.filePath,
    required this.pageCount,
    required this.currentPage,
    required this.onPageTap,
    this.bookmarkedPages = const {},
  });

  @override
  State<PageThumbnailSidebar> createState() => _PageThumbnailSidebarState();
}

class _PageThumbnailSidebarState extends State<PageThumbnailSidebar> {
  /// Cached thumbnail image data keyed by page index.
  final Map<int, ImageProvider> _cache = {};

  /// Pages currently being generated (to avoid duplicate work).
  final Set<int> _loading = {};

  /// Pages that permanently failed thumbnail generation (null result or throw).
  /// Skipped on subsequent rebuilds to avoid a retry storm.
  final Set<int> _failed = {};

  @override
  void didUpdateWidget(PageThumbnailSidebar oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.documentId != widget.documentId) {
      _cache.clear();
      _loading.clear();
      _failed.clear();
    }
  }

  Future<void> _loadThumbnail(int pageIndex) async {
    if (_cache.containsKey(pageIndex) ||
        _loading.contains(pageIndex) ||
        _failed.contains(pageIndex)) {
      return;
    }
    _loading.add(pageIndex);

    try {
      // Check disk cache first.
      final cached = await ThumbnailService.getCached(
        widget.documentId,
        pageIndex,
      );
      if (cached != null && mounted) {
        setState(() {
          _cache[pageIndex] = FileImage(cached);
        });
        _loading.remove(pageIndex);
        return;
      }

      // Generate from the PDF.
      final bytes = await ThumbnailService.generate(
        widget.filePath,
        pageIndex,
        maxWidth: 160,
      );
      if (bytes != null) {
        await ThumbnailService.cacheThumbnail(
          widget.documentId,
          pageIndex,
          bytes,
        );
        if (mounted) {
          setState(() {
            _cache[pageIndex] = MemoryImage(bytes);
          });
        }
      } else {
        // Null result means generation failed permanently for this page.
        _failed.add(pageIndex);
      }
    } catch (_) {
      // Any exception is treated as a permanent failure to avoid retry storms.
      _failed.add(pageIndex);
    } finally {
      _loading.remove(pageIndex);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 120,
      decoration: BoxDecoration(
        color: Theme.of(context).colorScheme.surfaceContainerHighest,
        border: Border(
          right: BorderSide(color: Theme.of(context).dividerColor, width: 1),
        ),
      ),
      child: ListView.builder(
        padding: const EdgeInsets.symmetric(vertical: 8),
        itemCount: widget.pageCount,
        itemBuilder: (context, index) {
          _loadThumbnail(index);
          final isCurrentPage = index == widget.currentPage;
          final isBookmarked = widget.bookmarkedPages.contains(index);

          return GestureDetector(
            onTap: () => widget.onPageTap(index),
            child: Container(
              margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
              decoration: BoxDecoration(
                border: Border.all(
                  color: isCurrentPage
                      ? Theme.of(context).colorScheme.primary
                      : Colors.grey.shade400,
                  width: isCurrentPage ? 2.5 : 1.0,
                ),
                borderRadius: BorderRadius.circular(4),
              ),
              child: Stack(
                children: [
                  // Thumbnail image or placeholder.
                  AspectRatio(
                    aspectRatio: 8.5 / 11, // US Letter-ish ratio
                    child: ClipRRect(
                      borderRadius: BorderRadius.circular(3),
                      child: _cache.containsKey(index)
                          ? Image(image: _cache[index]!, fit: BoxFit.cover)
                          : Container(
                              color: Theme.of(
                                context,
                              ).colorScheme.surfaceContainerLow,
                              child: Center(
                                child: Text(
                                  '${index + 1}',
                                  style: TextStyle(
                                    fontSize: 18,
                                    fontWeight: FontWeight.w600,
                                    color: Theme.of(
                                      context,
                                    ).colorScheme.onSurfaceVariant,
                                  ),
                                ),
                              ),
                            ),
                    ),
                  ),
                  // Page number overlay.
                  Positioned(
                    bottom: 2,
                    right: 2,
                    child: Container(
                      padding: const EdgeInsets.symmetric(
                        horizontal: 4,
                        vertical: 1,
                      ),
                      decoration: BoxDecoration(
                        color: Colors.black54,
                        borderRadius: BorderRadius.circular(3),
                      ),
                      child: Text(
                        '${index + 1}',
                        style: const TextStyle(
                          color: Colors.white,
                          fontSize: 10,
                        ),
                      ),
                    ),
                  ),
                  // Bookmark indicator.
                  if (isBookmarked)
                    Positioned(
                      top: 2,
                      left: 2,
                      child: Container(
                        width: 8,
                        height: 8,
                        decoration: BoxDecoration(
                          color: Theme.of(context).colorScheme.primary,
                          shape: BoxShape.circle,
                        ),
                      ),
                    ),
                ],
              ),
            ),
          );
        },
      ),
    );
  }
}
