import 'dart:async';

import 'package:aves/app_mode.dart';
import 'package:aves/model/app/permissions.dart';
import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/favourites.dart';
import 'package:aves/model/filters/favourite.dart';
import 'package:aves/model/filters/mime.dart';
import 'package:aves/model/selection.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/model/source/collection_source.dart';
import 'package:aves/model/source/section_keys.dart';
import 'package:aves/ref/mime_types.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/time_utils.dart';
import 'package:aves/widgets/collection/app_bar/collection_app_bar.dart';
import 'package:aves/widgets/collection/draggable_thumb_label.dart';
import 'package:aves/widgets/collection/grid/list_details_theme.dart';
import 'package:aves/widgets/collection/grid/section_layout.dart';
import 'package:aves/widgets/collection/grid/tile.dart';
import 'package:aves/widgets/collection/loading.dart';
import 'package:aves/widgets/common/basic/draggable_scrollbar/scrollbar.dart';
import 'package:aves/widgets/common/basic/insets.dart';
import 'package:aves/widgets/common/behaviour/routes.dart';
import 'package:aves/widgets/common/behaviour/sloppy_scroll_physics.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/extensions/media_query.dart';
import 'package:aves/widgets/common/grid/draggable_thumb_label.dart';
import 'package:aves/widgets/common/grid/item_tracker.dart';
import 'package:aves/widgets/common/grid/scaling.dart';
import 'package:aves/widgets/common/grid/sections/fixed/scale_grid.dart';
import 'package:aves/widgets/common/grid/sections/list_layout.dart';
import 'package:aves/widgets/common/grid/sections/section_layout.dart';
import 'package:aves/widgets/common/grid/selector.dart';
import 'package:aves/widgets/common/grid/sliver.dart';
import 'package:aves/widgets/common/grid/theme.dart';
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
import 'package:aves/widgets/common/identity/empty.dart';
import 'package:aves/widgets/common/identity/scroll_thumb.dart';
import 'package:aves/widgets/common/providers/tile_extent_controller_provider.dart';
import 'package:aves/widgets/common/providers/viewer_entry_provider.dart';
import 'package:aves/widgets/common/thumbnail/decorated.dart';
import 'package:aves/widgets/common/thumbnail/image.dart';
import 'package:aves/widgets/common/thumbnail/notifications.dart';
import 'package:aves/widgets/common/tile_extent_controller.dart';
import 'package:aves/widgets/navigation/nav_bar/nav_bar.dart';
import 'package:aves/widgets/viewer/entry_viewer_page.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:intl/intl.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';

// ✅ accesso al DB per capire se esiste cache (evita "scanner" alle riaperture)
import 'package:aves/services/common/services.dart';

// REMOTE: import per le thumb di rete
import 'package:aves/remote/remote_image_tile.dart';

// ✅ Remote origin costante
import 'package:aves/remote/remote_origin.dart';

// ✅ Flag remoti (locale+remoto)
import 'package:aves/model/entry/extensions/remote_flags.dart';

// ✅ Cornice ibrida (rettangolare + smussata)
import 'package:aves/widgets/common/hybrid_frame.dart';

class CollectionGrid extends StatefulWidget {
  final String settingsRouteKey;

  static const double extentMin = 46;
  static const double extentMax = 300;
  static const double fixedExtentLayoutSpacing = 2;
  static const double mosaicLayoutSpacing = 4;

  static int get columnCountDefault => settings.useTvLayout ? 6 : 4;

  const CollectionGrid({
    super.key,
    required this.settingsRouteKey,
  });

  @override
  State<CollectionGrid> createState() => _CollectionGridState();
}

class _CollectionGridState extends State<CollectionGrid> {
  TileExtentController? _tileExtentController;

  String get settingsRouteKey => widget.settingsRouteKey;

  @override
  void dispose() {
    _tileExtentController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final spacing = context.select<Settings, double>((v) =>
        v.getTileLayout(settingsRouteKey) == TileLayout.mosaic
            ? CollectionGrid.mosaicLayoutSpacing
            : CollectionGrid.fixedExtentLayoutSpacing);

    if (_tileExtentController?.spacing != spacing) {
      _tileExtentController = TileExtentController(
        settingsRouteKey: settingsRouteKey,
        columnCountDefault: CollectionGrid.columnCountDefault,
        extentMin: CollectionGrid.extentMin,
        extentMax: CollectionGrid.extentMax,
        spacing: spacing,
        horizontalPadding: 2,
      );
    }

    return TileExtentControllerProvider(
      controller: _tileExtentController!,
      child: const _CollectionGridContent(),
    );
  }
}

class _CollectionGridContent extends StatefulWidget {
  const _CollectionGridContent();

  @override
  State<_CollectionGridContent> createState() => _CollectionGridContentState();
}

class _CollectionGridContentState extends State<_CollectionGridContent> {
  final ValueNotifier<AvesEntry?> _focusedItemNotifier = ValueNotifier(null);
  final ValueNotifier<bool> _isScrollingNotifier = ValueNotifier(false);
  final ValueNotifier<AppMode> _selectingAppModeNotifier =
      ValueNotifier(AppMode.pickFilteredMediaInternal);

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => context.read<ViewerEntryNotifier>().value = null);
  }

  @override
  void dispose() {
    _focusedItemNotifier.dispose();
    _isScrollingNotifier.dispose();
    _selectingAppModeNotifier.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final selectable =
        context.select<ValueNotifier<AppMode>, bool>((v) => v.value.canSelectMedia);
    final settingsRouteKey = context.read<TileExtentController>().settingsRouteKey;
    final tileLayout =
        context.select<Settings, TileLayout>((v) => v.getTileLayout(settingsRouteKey));

    return Consumer<CollectionLens>(
      builder: (context, collection, child) {
        final sectionedListLayoutProvider = ValueListenableBuilder<double>(
          valueListenable: context.select<TileExtentController, ValueNotifier<double>>(
              (controller) => controller.extentNotifier),
          builder: (context, thumbnailExtent, child) {
            assert(thumbnailExtent > 0);
            return Selector<TileExtentController, (double, int, double, double)>(
              selector: (context, c) =>
                  (c.viewportSize.width, c.columnCount, c.spacing, c.horizontalPadding),
              builder: (context, c, child) {
                final (scrollableWidth, columnCount, tileSpacing, horizontalPadding) = c;
                final source = collection.source;

                return GridTheme(
                  extent: thumbnailExtent,
                  child: EntryListDetailsTheme(
                    extent: thumbnailExtent,
                    child: ValueListenableBuilder<SourceState>(
                      valueListenable: source.stateNotifier,
                      builder: (context, sourceState, child) {
                        late final Duration tileAnimationDelay;
                        if (sourceState == SourceState.ready) {
                          final target = context.read<DurationsData>().staggeredAnimationPageTarget;
                          tileAnimationDelay = context
                              .read<TileExtentController>()
                              .getTileAnimationDelay(target);
                        } else {
                          tileAnimationDelay = Duration.zero;
                        }

                        return NotificationListener<OpenViewerNotification>(
                          onNotification: (notification) {
                            _goToViewer(collection, notification.entry);
                            return true;
                          },
                          child: StreamBuilder(
                            stream: source.eventBus.on<AspectRatioChangedEvent>(),
                            builder: (context, snapshot) => SectionedEntryListLayoutProvider(
                              collection: collection,
                              selectable: selectable,
                              scrollableWidth: scrollableWidth,
                              tileLayout: tileLayout,
                              columnCount: columnCount,
                              spacing: tileSpacing,
                              horizontalPadding: horizontalPadding,
                              tileExtent: thumbnailExtent,
                              tileBuilder: (entry, tileSize) {
                                final extent = tileSize.shortestSide;

                                // REMOTE: ramo dedicato per le entry remote (origin==RemoteOrigin.value)
                                if (entry.origin == RemoteOrigin.value) {
                                  return RemoteInteractiveTile(
                                    key: ValueKey('remote_${entry.id}'),
                                    entry: entry,
                                    thumbnailExtent: extent,
                                  );
                                }

                                // Locale: flusso preesistente (ma con cornice ibrida se locale+remote)
                                return AnimatedBuilder(
                                  animation: favourites,
                                  builder: (context, child) {
                                    Widget tile = InteractiveTile(
                                      key: ValueKey(entry.id),
                                      collection: collection,
                                      entry: entry,
                                      thumbnailExtent: extent,
                                      tileLayout: tileLayout,
                                      isScrollingNotifier: _isScrollingNotifier,
                                    );

                                    // ✅ Cornice speciale SOLO per locali che hanno anche remote link
                                    if (entry.isLocalAndRemote) {
                                      tile = HybridFrame(child: tile);
                                    }

                                    if (!settings.useTvLayout) return tile;

                                    return Focus(
                                      onFocusChange: (focused) {
                                        if (focused) {
                                          _focusedItemNotifier.value = entry;
                                        } else if (_focusedItemNotifier.value == entry) {
                                          _focusedItemNotifier.value = null;
                                        }
                                      },
                                      child: ValueListenableBuilder<AvesEntry?>(
                                        valueListenable: _focusedItemNotifier,
                                        builder: (context, focusedItem, child) {
                                          return AnimatedScale(
                                            scale: focusedItem == entry ? 1 : .9,
                                            curve: Curves.fastOutSlowIn,
                                            duration: context.select<DurationsData, Duration>(
                                                (v) => v.tvImageFocusAnimation),
                                            child: child!,
                                          );
                                        },
                                        child: tile,
                                      ),
                                    );
                                  },
                                );
                              },
                              tileAnimationDelay: tileAnimationDelay,
                              child: child!,
                            ),
                          ),
                        );
                      },
                      child: child,
                    ),
                  ),
                );
              },
              child: child,
            );
          },
          child: _CollectionSectionedContent(
            collection: collection,
            isScrollingNotifier: _isScrollingNotifier,
            scrollController: PrimaryScrollController.of(context),
            tileLayout: tileLayout,
            selectable: selectable,
          ),
        );
        return sectionedListLayoutProvider;
      },
    );
  }

  Future<void> _goToViewer(CollectionLens collection, AvesEntry entry) async {
    final viewerEntryNotifier = context.read<ViewerEntryNotifier>();

    if (viewerEntryNotifier.value == entry) return;
    WidgetsBinding.instance.addPostFrameCallback((_) => viewerEntryNotifier.value = entry);

    final selection = context.read<Selection<AvesEntry>>();
    await Navigator.maybeOf(context)?.push(
      TransparentMaterialPageRoute(
        settings: const RouteSettings(name: EntryViewerPage.routeName),
        pageBuilder: (context, a, sa) {
          final viewerCollection = collection.copyWith(
            listenToSource: false,
          );
          Widget child = EntryViewerPage(
            collection: viewerCollection,
            initialEntry: entry,
          );

          if (selection.isSelecting) {
            child = MultiProvider(
              providers: [
                ListenableProvider<ValueNotifier<AppMode>>.value(value: _selectingAppModeNotifier),
                ChangeNotifierProvider<Selection<AvesEntry>>.value(value: selection),
              ],
              child: child,
            );
          }

          return child;
        },
      ),
    );

    final animate = context.read<Settings>().animate;
    if (animate) {
      await Future.delayed(ADurations.pageTransitionExact * timeDilation);
    }
    viewerEntryNotifier.value = null;
  }
}

class _CollectionSectionedContent extends StatefulWidget {
  final CollectionLens collection;
  final ValueNotifier<bool> isScrollingNotifier;
  final ScrollController scrollController;
  final TileLayout tileLayout;
  final bool selectable;

  const _CollectionSectionedContent({
    required this.collection,
    required this.isScrollingNotifier,
    required this.scrollController,
    required this.tileLayout,
    required this.selectable,
  });

  @override
  State<_CollectionSectionedContent> createState() => _CollectionSectionedContentState();
}

class _CollectionSectionedContentState extends State<_CollectionSectionedContent> {
  final ValueNotifier<double> _appBarHeightNotifier = ValueNotifier(0);
  final GlobalKey _scrollableKey = GlobalKey(debugLabel: 'thumbnail-collection-scrollable');

  CollectionLens get collection => widget.collection;
  TileLayout get tileLayout => widget.tileLayout;
  ScrollController get scrollController => widget.scrollController;

  @override
  void initState() {
    super.initState();
    _appBarHeightNotifier.addListener(_onAppBarHeightChanged);
  }

  @override
  void dispose() {
    _appBarHeightNotifier.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final scrollView = AnimationLimiter(
      child: _CollectionScrollView(
        scrollableKey: _scrollableKey,
        collection: collection,
        appBar: CollectionAppBar(
          appBarHeightNotifier: _appBarHeightNotifier,
          scrollController: scrollController,
          collection: collection,
        ),
        appBarHeightNotifier: _appBarHeightNotifier,
        isScrollingNotifier: widget.isScrollingNotifier,
        scrollController: scrollController,
      ),
    );

    final scaler = _CollectionScaler(
      scrollableKey: _scrollableKey,
      appBarHeightNotifier: _appBarHeightNotifier,
      tileLayout: tileLayout,
      child: scrollView,
    );

    final selector = GridSelectionGestureDetector<AvesEntry>(
      scrollableKey: _scrollableKey,
      selectable: widget.selectable,
      items: collection.sortedEntries,
      scrollController: scrollController,
      appBarHeightNotifier: _appBarHeightNotifier,
      child: scaler,
    );

    return GridItemTracker<AvesEntry>(
      scrollableKey: _scrollableKey,
      tileLayout: tileLayout,
      appBarHeightNotifier: _appBarHeightNotifier,
      scrollController: scrollController,
      child: selector,
    );
  }

  void _onAppBarHeightChanged() => setState(() {});
}

class _CollectionScaler extends StatelessWidget {
  final GlobalKey scrollableKey;
  final ValueNotifier<double> appBarHeightNotifier;
  final TileLayout tileLayout;
  final Widget child;

  const _CollectionScaler({
    required this.scrollableKey,
    required this.appBarHeightNotifier,
    required this.tileLayout,
    required this.child,
  });

  @override
  Widget build(BuildContext context) {
    final (tileSpacing, horizontalPadding) =
        context.select<TileExtentController, (double, double)>((v) => (v.spacing, v.horizontalPadding));
    final brightness = Theme.of(context).brightness;
    final borderColor = DecoratedThumbnail.borderColor(context);
    final borderWidth = DecoratedThumbnail.borderWidth(context);

    return GridScaleGestureDetector<AvesEntry>(
      scrollableKey: scrollableKey,
      tileLayout: tileLayout,
      heightForWidth: (width) => width,
      gridBuilder: (center, tileSize, child) => CustomPaint(
        painter: FixedExtentGridPainter(
          tileLayout: tileLayout,
          tileCenter: center,
          tileSize: tileSize,
          spacing: tileSpacing,
          horizontalPadding: horizontalPadding,
          borderWidth: borderWidth,
          borderRadius: Radius.zero,
          color: borderColor,
          textDirection: Directionality.of(context),
        ),
        child: child,
      ),
      scaledItemBuilder: (entry, tileSize) => EntryListDetailsTheme(
        extent: tileSize.height,
        child: Builder(
          builder: (_) {
            if (entry.origin == RemoteOrigin.value) {
              return RemoteInteractiveTile(
                key: ValueKey('remote_scaled_${entry.id}'),
                entry: entry,
                thumbnailExtent: context.read<TileExtentController>().effectiveExtentMax,
              );
            }

            Widget tile = Tile(
              entry: entry,
              thumbnailExtent: context.read<TileExtentController>().effectiveExtentMax,
              tileLayout: tileLayout,
            );

            if (entry.isLocalAndRemote) {
              tile = HybridFrame(child: tile);
            }

            return tile;
          },
        ),
      ),
      mosaicItemBuilder: (index, targetExtent) => DecoratedBox(
        decoration: BoxDecoration(
          color: ThumbnailImage.computeLoadingBackgroundColor(index * 10, brightness).withValues(alpha: .9),
          border: Border.all(
            color: borderColor,
            width: borderWidth,
          ),
        ),
      ),
      child: child,
    );
  }
}

class _CollectionScrollView extends StatefulWidget {
  final GlobalKey scrollableKey;
  final CollectionLens collection;
  final Widget appBar;
  final ValueNotifier<double> appBarHeightNotifier;
  final ValueNotifier<bool> isScrollingNotifier;
  final ScrollController scrollController;

  const _CollectionScrollView({
    required this.scrollableKey,
    required this.collection,
    required this.appBar,
    required this.appBarHeightNotifier,
    required this.isScrollingNotifier,
    required this.scrollController,
  });

  @override
  State<_CollectionScrollView> createState() => _CollectionScrollViewState();
}

class _CollectionScrollViewState extends State<_CollectionScrollView> with WidgetsBindingObserver {
  Timer? _scrollMonitoringTimer;
  bool _checkingStoragePermission = false;

  late final Future<bool> _hasAnyDbCacheFuture;

  @override
  void initState() {
    super.initState();
    _hasAnyDbCacheFuture = _hasAnyDbCache();
    _registerWidget(widget);
    WidgetsBinding.instance.addObserver(this);
  }

  Future<bool> _hasAnyDbCache() async {
    try {
      final rows = await localMediaDb.rawDb.rawQuery(
        'SELECT 1 FROM entry WHERE trashed=0 LIMIT 1',
      );
      return rows.isNotEmpty;
    } catch (_) {
      return false;
    }
  }

  @override
  void didUpdateWidget(covariant _CollectionScrollView oldWidget) {
    super.didUpdateWidget(oldWidget);
    _unregisterWidget(oldWidget);
    _registerWidget(widget);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    _unregisterWidget(widget);
    _stopScrollMonitoringTimer();
    super.dispose();
  }

  void _registerWidget(_CollectionScrollView widget) {
    widget.collection.filterChangeNotifier.addListener(_scrollToTop);
    widget.collection.sortSectionChangeNotifier.addListener(_scrollToTop);
    widget.scrollController.addListener(_onScrollChanged);
  }

  void _unregisterWidget(_CollectionScrollView widget) {
    widget.collection.filterChangeNotifier.removeListener(_scrollToTop);
    widget.collection.sortSectionChangeNotifier.removeListener(_scrollToTop);
    widget.scrollController.removeListener(_onScrollChanged);
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed && _checkingStoragePermission) {
      _checkingStoragePermission = false;
      _isStoragePermissionGranted.then((granted) {
        if (granted) {
          widget.collection.source.init(scope: CollectionSource.fullScope);
        }
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final scrollView = _buildScrollView(widget.appBar, widget.collection);
    return settings.useTvLayout ? scrollView : _buildDraggableScrollView(scrollView, widget.collection);
  }

  Widget _buildDraggableScrollView(Widget scrollView, CollectionLens collection) {
    return ValueListenableBuilder<double>(
      valueListenable: widget.appBarHeightNotifier,
      builder: (context, appBarHeight, child) {
        return Selector<MediaQueryData, double>(
          selector: (context, mq) => mq.effectiveBottomPadding,
          builder: (context, mqPaddingBottom, child) {
            return Selector<Settings, bool>(
              selector: (context, s) => s.enableBottomNavigationBar,
              builder: (context, enableBottomNavigationBar, child) {
                final canNavigate =
                    context.select<ValueNotifier<AppMode>, bool>((v) => v.value.canNavigate);
                final showBottomNavigationBar = canNavigate && enableBottomNavigationBar;
                final navBarHeight = showBottomNavigationBar ? AppBottomNavBar.height : 0;
                return Selector<SectionedListLayout<AvesEntry>, List<SectionLayout>>(
                  selector: (context, layout) => layout.sectionLayouts,
                  builder: (context, sectionLayouts, child) {
                    final scrollController = widget.scrollController;
                    final offsetIncrementSnapThreshold =
                        context.select<TileExtentController, double>((v) => (v.extentNotifier.value + v.spacing) / 4);
                    return DraggableScrollbar(
                      backgroundColor: Colors.white,
                      scrollThumbSize: Size(avesScrollThumbWidth, avesScrollThumbHeight),
                      scrollThumbBuilder: avesScrollThumbBuilder(
                        height: avesScrollThumbHeight,
                        backgroundColor: Colors.white,
                      ),
                      controller: scrollController,
                      dragOffsetSnapper: (scrollOffset, offsetIncrement) {
                        if (offsetIncrement > offsetIncrementSnapThreshold &&
                            scrollOffset < scrollController.position.maxScrollExtent) {
                          final section =
                              sectionLayouts.firstWhereOrNull((section) => section.hasChildAtOffset(scrollOffset));
                          if (section != null) {
                            if (section.maxOffset - section.minOffset <
                                scrollController.position.viewportDimension) {
                              return section.minOffset;
                            } else {
                              final index = section.getMinChildIndexForScrollOffset(scrollOffset);
                              return section.indexToLayoutOffset(index);
                            }
                          }
                        }
                        return scrollOffset;
                      },
                      crumbsBuilder: () => _getCrumbs(sectionLayouts),
                      padding: EdgeInsets.only(
                        top: appBarHeight,
                        bottom: navBarHeight + mqPaddingBottom,
                      ),
                      labelTextBuilder: (offsetY) => CollectionDraggableThumbLabel(
                        collection: collection,
                        offsetY: offsetY,
                      ),
                      crumbTextBuilder: (label) => DraggableCrumbLabel(label: label),
                      child: scrollView,
                    );
                  },
                );
              },
            );
          },
        );
      },
    );
  }

  Widget _buildScrollView(Widget appBar, CollectionLens collection) {
    return CustomScrollView(
      key: widget.scrollableKey,
      primary: true,
      physics: collection.isEmpty
          ? const NeverScrollableScrollPhysics()
          : SloppyScrollPhysics(
              gestureSettings: MediaQuery.gestureSettingsOf(context),
              parent: const AlwaysScrollableScrollPhysics(),
            ),
      cacheExtent: (() {
        final base = context.select<TileExtentController, double>((c) => c.effectiveExtentMax);
        final h = MediaQuery.of(context).size.height;
        final target = h * 2;
        return target < base ? base : target;
      })(),
      slivers: [
        appBar,
        collection.isEmpty
            ? SliverFillRemaining(
                hasScrollBody: false,
                child: _buildEmptyContent(collection),
              )
            : const SectionedListSliver<AvesEntry>(),
        const NavBarPaddingSliver(),
        const BottomPaddingSliver(),
        const TvTileGridBottomPaddingSliver(),
      ],
    );
  }

  Widget _buildEmptyContent(CollectionLens collection) {
    final source = collection.source;
    return ValueListenableBuilder<SourceState>(
      valueListenable: source.stateNotifier,
      builder: (context, sourceState, child) {
        if (sourceState == SourceState.loading) {
          return FutureBuilder<bool>(
            future: _hasAnyDbCacheFuture,
            builder: (context, snapshot) {
              final hasCache = snapshot.data ?? false;
              if (hasCache) {
                return const Center(
                  child: SizedBox(
                    width: 18,
                    height: 18,
                    child: CircularProgressIndicator(strokeWidth: 1.6),
                  ),
                );
              }
              return LoadingEmptyContent(source: source);
            },
          );
        }

        return FutureBuilder<bool>(
          future: _isStoragePermissionGranted,
          builder: (context, snapshot) {
            final granted = snapshot.data ?? true;
            Widget? bottom = granted
                ? null
                : Padding(
                    padding: const EdgeInsets.only(top: 16),
                    child: AvesOutlinedButton(
                      label: context.l10n.collectionEmptyGrantAccessButtonLabel,
                      onPressed: () async {
                        if (await openAppSettings()) {
                          _checkingStoragePermission = true;
                        }
                      },
                    ),
                  );

            if (collection.filters.any((filter) => filter is FavouriteFilter)) {
              return EmptyContent(
                icon: AIcons.favourite,
                text: context.l10n.collectionEmptyFavourites,
                bottom: bottom,
              );
            }
            if (collection.filters.any((filter) =>
                filter is MimeFilter && filter.mime == MimeTypes.anyVideo)) {
              return EmptyContent(
                icon: AIcons.video,
                text: context.l10n.collectionEmptyVideos,
                bottom: bottom,
              );
            }
            return EmptyContent(
              icon: AIcons.image,
              text: context.l10n.collectionEmptyImages,
              bottom: bottom,
            );
          },
        );
      },
    );
  }

  void _scrollToTop() => widget.scrollController.jumpTo(0);

  void _onScrollChanged() {
    widget.isScrollingNotifier.value = true;
    _stopScrollMonitoringTimer();
    _scrollMonitoringTimer = Timer(ADurations.collectionScrollMonitoringTimerDelay, () {
      widget.isScrollingNotifier.value = false;
    });
  }

  void _stopScrollMonitoringTimer() => _scrollMonitoringTimer?.cancel();

  Map<double, String> _getCrumbs(List<SectionLayout> sectionLayouts) {
    final crumbs = <double, String>{};
    if (sectionLayouts.length <= 1) return crumbs;

    final maxOffset = sectionLayouts.last.maxOffset;
    void addAlbums(CollectionLens collection, List<SectionLayout> sectionLayouts, Map<double, String> crumbs) {
      final source = collection.source;
      sectionLayouts.forEach((section) {
        final directory = (section.sectionKey as EntryAlbumSectionKey).directory;
        if (directory != null) {
          final label = source.getStoredAlbumDisplayName(context, directory);
          crumbs[section.minOffset / maxOffset] = label;
        }
      });
    }

    final collection = widget.collection;
    switch (collection.sortFactor) {
      case EntrySortFactor.date:
        switch (collection.sectionFactor) {
          case EntrySectionFactor.album:
            addAlbums(collection, sectionLayouts, crumbs);
          case EntrySectionFactor.month:
          case EntrySectionFactor.day:
            final firstKey = sectionLayouts.first.sectionKey;
            final lastKey = sectionLayouts.last.sectionKey;
            if (firstKey is EntryDateSectionKey && lastKey is EntryDateSectionKey) {
              final newest = firstKey.date;
              final oldest = lastKey.date;
              if (newest != null && oldest != null) {
                final locale = context.locale;
                final dateFormat = (newest.difference(oldest).inHumanDays).abs() > 365
                    ? DateFormat.y(locale)
                    : DateFormat.MMM(locale);
                String? lastLabel;
                sectionLayouts.forEach((section) {
                  final date = (section.sectionKey as EntryDateSectionKey).date;
                  if (date != null) {
                    final label = dateFormat.format(date);
                    if (label != lastLabel) {
                      crumbs[section.minOffset / maxOffset] = label;
                      lastLabel = label;
                    }
                  }
                });
              }
            }
          case EntrySectionFactor.none:
            break;
        }
      case EntrySortFactor.name:
      case EntrySortFactor.path:
        addAlbums(collection, sectionLayouts, crumbs);
      case EntrySortFactor.rating:
      case EntrySortFactor.size:
      case EntrySortFactor.duration:
        break;
    }
    return crumbs;
  }

  Future<bool> get _isStoragePermissionGranted =>
      Future.wait(Permissions.storage.map((v) => v.status))
          .then((v) => v.any((status) => status.isGranted));
}

// ✅ REMOTE: Tile remota con supporto selezione (check + highlight) come Aves
class RemoteInteractiveTile extends StatelessWidget {
  final AvesEntry entry;
  final double thumbnailExtent;

  const RemoteInteractiveTile({
    super.key,
    required this.entry,
    required this.thumbnailExtent,
  });

  @override
  Widget build(BuildContext context) {
    final selection = context.watch<Selection<AvesEntry>>();
    final isSelecting = selection.isSelecting;
    final isSelected = selection.selectedItems.contains(entry);

    final cs = Theme.of(context).colorScheme;
    final highlight = cs.secondary.withOpacity(.28);
    final border = cs.secondary.withOpacity(.95);

    final VoidCallback? onTap =
        isSelecting ? null : () => OpenViewerNotification(entry).dispatch(context);

    return GestureDetector(
      onTap: onTap,
      child: ClipRRect(
        borderRadius: BorderRadius.zero,
        child: Stack(
          fit: StackFit.expand,
          children: [
            SizedBox(
              width: thumbnailExtent,
              height: thumbnailExtent,
              child: RemoteImageTile(entry: entry),
            ),

            // ✅ FIX: overlay viola + bordo SOLO durante selection mode
            if (isSelecting && isSelected) ...[
              Positioned.fill(
                child: ColoredBox(color: highlight),
              ),
              Positioned.fill(
                child: DecoratedBox(
                  decoration: BoxDecoration(
                    border: Border.all(color: border, width: 2),
                  ),
                ),
              ),
            ],

            // badge selezione (cerchio/check) in alto a destra durante selection mode
            if (isSelecting) ...[
              Positioned(
                top: 6,
                right: 6,
                child: _SelectionBadge(
                  selected: isSelected,
                  color: cs.secondary,
                ),
              ),
            ],
          ],
        ),
      ),
    );
  }
}

class _SelectionBadge extends StatelessWidget {
  final bool selected;
  final Color color;

  const _SelectionBadge({
    required this.selected,
    required this.color,
  });

  @override
  Widget build(BuildContext context) {
    final borderColor = Colors.white.withOpacity(.95);
    return Container(
      width: 20,
      height: 20,
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        color: selected ? color : Colors.black.withOpacity(.25),
        border: Border.all(
          color: selected ? Colors.transparent : borderColor,
          width: 1.5,
        ),
      ),
      child: selected ? const Icon(Icons.check, size: 14, color: Colors.white) : null,
    );
  }
}
