import 'package:flutter/material.dart';
import '../../services/settings_service.dart';
import '../../widgets/settings_builder.dart';
import '../../utils/grid_size_calculator.dart';
import '../../utils/layout_constants.dart';
import '../main_screen.dart';

/// Context passed to the item builder with navigation information.
class GridItemContext {
  /// Whether this item is in the first row of the grid.
  final bool isFirstRow;

  /// Whether this item is in the first column of the grid.
  final bool isFirstColumn;

  /// Whether items are displayed in list mode (single column).
  final bool isListMode;

  /// Callback to navigate to the sidebar (for first-column items).
  final VoidCallback? navigateToSidebar;

  const GridItemContext({
    required this.isFirstRow,
    required this.isFirstColumn,
    this.isListMode = false,
    this.navigateToSidebar,
  });
}

/// A widget that automatically switches between grid and list view
/// based on user settings, providing a consistent layout pattern
/// across all library screens.
///
/// Generic type T: The type of items being displayed
class AdaptiveMediaGrid<T> extends StatelessWidget {
  /// The list of items to display
  final List<T> items;

  /// Builder function for each item in the grid/list.
  /// Receives the item, index, and optional grid context with navigation info.
  final Widget Function(BuildContext context, T item, int index, [GridItemContext? gridContext]) itemBuilder;

  /// Callback when the list needs to be refreshed
  final VoidCallback? onRefresh;

  /// Optional padding around the grid/list
  final EdgeInsets? padding;

  /// Child aspect ratio for grid items (width / height)
  final double? childAspectRatio;

  /// Optional focus node for the first item (for programmatic focus)
  final FocusNode? firstItemFocusNode;

  /// Callback when back button is pressed (for hierarchical navigation)
  final VoidCallback? onBack;

  /// Whether to enable sidebar navigation for first-column items.
  final bool enableSidebarNavigation;

  const AdaptiveMediaGrid({
    super.key,
    required this.items,
    required this.itemBuilder,
    this.onRefresh,
    this.padding,
    this.childAspectRatio,
    this.firstItemFocusNode,
    this.onBack,
    this.enableSidebarNavigation = false,
  });

  @override
  Widget build(BuildContext context) {
    return SettingsBuilder(
      prefs: const [SettingsService.viewMode, SettingsService.libraryDensity],
      builder: (context) {
        final svc = SettingsService.instanceOrNull!;
        return _buildItemsView(context, svc.read(SettingsService.viewMode), svc.read(SettingsService.libraryDensity));
      },
    );
  }

  // Extra top padding for focus decoration (scale + border extends beyond item bounds)
  static const double _focusDecorationPadding = 3.0;

  /// Navigate focus to the sidebar
  void _navigateToSidebar(BuildContext context) {
    MainScreenFocusScope.of(context)?.focusSidebar();
  }

  /// Builds either a list or grid view based on the view mode
  Widget _buildItemsView(BuildContext context, ViewMode viewMode, int density) {
    final basePadding = padding ?? GridLayoutConstants.gridPadding;
    // Add extra top padding for focus decoration of first row items
    final effectivePadding = basePadding.copyWith(top: basePadding.top + _focusDecorationPadding);
    final effectiveAspectRatio = childAspectRatio ?? GridLayoutConstants.posterAspectRatio;

    return CustomScrollView(
      // Allow focus decoration to render outside scroll bounds
      clipBehavior: Clip.none,
      slivers: [
        SliverOverlapInjector(handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context)),
        if (viewMode == ViewMode.list)
          SliverPadding(
            padding: effectivePadding,
            sliver: SliverList.builder(
              itemCount: items.length,
              itemBuilder: (ctx, index) {
                final gridContext = enableSidebarNavigation
                    ? GridItemContext(
                        isFirstRow: index == 0,
                        isFirstColumn: true, // List view = single column
                        isListMode: true,
                        navigateToSidebar: () => _navigateToSidebar(context),
                      )
                    : null;
                return itemBuilder(ctx, items[index], index, gridContext);
              },
            ),
          )
        else
          _buildGridSliver(context, density, effectivePadding, effectiveAspectRatio),
      ],
    );
  }

  Widget _buildGridSliver(BuildContext context, int density, EdgeInsets effectivePadding, double effectiveAspectRatio) {
    final maxCrossAxisExtent = GridSizeCalculator.getMaxCrossAxisExtent(context, density);

    return SliverPadding(
      padding: effectivePadding,
      sliver: SliverLayoutBuilder(
        builder: (context, constraints) {
          // crossAxisExtent is the post-padding inner width.
          final columnCount = GridSizeCalculator.getColumnCount(constraints.crossAxisExtent, maxCrossAxisExtent);

          return SliverGrid.builder(
            gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
              maxCrossAxisExtent: maxCrossAxisExtent,
              childAspectRatio: effectiveAspectRatio,
              crossAxisSpacing: GridLayoutConstants.crossAxisSpacing,
              mainAxisSpacing: GridLayoutConstants.mainAxisSpacing,
            ),
            itemCount: items.length,
            itemBuilder: (ctx, index) {
              final gridContext = enableSidebarNavigation
                  ? GridItemContext(
                      isFirstRow: GridSizeCalculator.isFirstRow(index, columnCount),
                      isFirstColumn: GridSizeCalculator.isFirstColumn(index, columnCount),
                      navigateToSidebar: () => _navigateToSidebar(context),
                    )
                  : null;
              return itemBuilder(ctx, items[index], index, gridContext);
            },
          );
        },
      ),
    );
  }
}
