import 'dart:io';

import 'package:flutter/material.dart';

import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:playlist_manager/playlist_manager.dart';

import 'package:namida/base/pull_to_refresh.dart';
import 'package:namida/class/count_per_row.dart';
import 'package:namida/class/route.dart';
import 'package:namida/class/track.dart';
import 'package:namida/controller/file_browser.dart';
import 'package:namida/controller/history_controller.dart';
import 'package:namida/controller/navigator_controller.dart';
import 'package:namida/controller/playlist_controller.dart';
import 'package:namida/controller/queue_controller.dart';
import 'package:namida/controller/scroll_search_controller.dart';
import 'package:namida/controller/search_sort_controller.dart';
import 'package:namida/controller/settings_controller.dart';
import 'package:namida/controller/smart_playlists/smart_playlists_controller.dart';
import 'package:namida/core/constants.dart';
import 'package:namida/core/dimensions.dart';
import 'package:namida/core/enums.dart';
import 'package:namida/core/extensions.dart';
import 'package:namida/core/functions.dart';
import 'package:namida/core/icon_fonts/broken_icons.dart';
import 'package:namida/core/namida_converter_ext.dart';
import 'package:namida/core/translations/language.dart';
import 'package:namida/core/utils.dart';
import 'package:namida/ui/dialogs/common_dialogs.dart';
import 'package:namida/ui/dialogs/create_smart_playlist_dialog.dart';
import 'package:namida/ui/pages/queues_page.dart';
import 'package:namida/ui/pages/subpages/playlist_tracks_subpage.dart';
import 'package:namida/ui/pages/subpages/smart_playlist_tracks_subpage.dart';
import 'package:namida/ui/widgets/artwork.dart';
import 'package:namida/ui/widgets/custom_widgets.dart';
import 'package:namida/ui/widgets/expandable_box.dart';
import 'package:namida/ui/widgets/library/multi_artwork_card.dart';
import 'package:namida/ui/widgets/library/playlist_tile.dart';
import 'package:namida/ui/widgets/sort_by_button.dart';

/// By Default, sending tracks to add (i.e: addToPlaylistDialog) will:
/// 1. Hide Default Playlists.
/// 2. Hide Grid Widget.
/// 3. Disable bottom padding.
/// 4. Disable Scroll Controller.
class PlaylistsPage extends StatefulWidget with NamidaRouteWidget {
  @override
  RouteType get route => RouteType.PAGE_playlists;

  final List<Track>? tracksToAdd;
  final CountPerRow countPerRow;
  final bool animateTiles;
  final bool enableHero;

  const PlaylistsPage({
    super.key,
    this.tracksToAdd,
    required this.countPerRow,
    this.animateTiles = true,
    required this.enableHero,
  });

  @override
  State<PlaylistsPage> createState() => _PlaylistsPageState();
}

class _PlaylistsPageState extends State<PlaylistsPage> with TickerProviderStateMixin, PullToRefreshMixin {
  bool get _shouldAnimate => widget.animateTiles && LibraryTab.playlists.shouldAnimateTiles;

  void _closeDialog() => NamidaNavigator.inst.closeDialog();

  Future<void> _importPlaylists({required bool keepSynced, required bool pickFolder}) async {
    Set<String> playlistsFilesPath;
    if (pickFolder) {
      final dirs = await NamidaFileBrowser.pickDirectories(note: "${lang.import} (${lang.folders})");
      playlistsFilesPath = {};
      for (final d in dirs) {
        final subfiles = await d.listAllIsolate(recursive: true);
        for (var f in subfiles) {
          if (f is File) {
            var path = f.path;
            if (NamidaFileExtensionsWrapper.m3u.isPathValid(path)) {
              playlistsFilesPath.add(path);
            }
          }
        }
      }
    } else {
      final playlistsFiles = await NamidaFileBrowser.pickFiles(note: lang.import, allowedExtensions: NamidaFileExtensionsWrapper.m3u);
      playlistsFilesPath = playlistsFiles.map((f) => f.path).toSet();
    }
    if (playlistsFilesPath.isNotEmpty) {
      final importedCount = await PlaylistController.inst.prepareM3UPlaylists(forPaths: playlistsFilesPath, addAsM3U: keepSynced);
      PlaylistController.inst.sortPlaylists();
      String countText;
      bool hadError;
      if (importedCount != null) {
        if (importedCount < playlistsFilesPath.length) {
          hadError = true;
          countText = '${importedCount.formatDecimal()}/${playlistsFilesPath.length.formatDecimal()}';
        } else {
          hadError = false;
          countText = importedCount.formatDecimal();
        }
        snackyy(
          message: lang.importedNPlaylistsSuccessfully(number: importedCount, numberText: countText),
          borderColor: (hadError ? Colors.orange : Colors.green).withOpacityExt(0.6),
        );
      } else {
        snackyy(
          message: lang.error,
          isError: true,
        );
      }
    }
  }

  void _onAddPlaylistsTap() {
    NamidaNavigator.inst.navigateDialog(
      dialogBuilder: (theme) => CustomBlurryDialog(
        theme: theme,
        normalTitleStyle: true,
        title: lang.choose,
        actions: const [
          CancelButton(addMargin: false),
        ],
        child: Column(
          children: [
            CustomListTile(
              icon: Broken.shuffle,
              title: lang.random,
              subtitle: lang.generateRandomPlaylist,
              onTap: () {
                _closeDialog();
                final numbers = PlaylistController.inst.generateRandomPlaylist();
                if (numbers == 0) {
                  snackyy(title: lang.error, message: lang.noEnoughTracks);
                }
              },
            ),
            CustomListTile(
              icon: Broken.import_1,
              title: lang.import,
              subtitle: lang.playlistsImportM3uNative,
              trailing: NamidaIconButton(
                tooltip: () => lang.folder,
                icon: Broken.folder_2,
                onPressed: () {
                  _closeDialog();
                  _importPlaylists(keepSynced: false, pickFolder: true);
                },
              ),
              onTap: () async {
                _closeDialog();
                _importPlaylists(keepSynced: false, pickFolder: false);
              },
            ),
            CustomListTile(
              icon: Broken.add_circle,
              title: lang.create,
              subtitle: lang.createNewPlaylist,
              onTap: () {
                _closeDialog();
                CreatePlaylistButton().promptCreate();
              },
            ),
            CustomListTile(
              icon: Broken.magicpen,
              title: lang.create,
              subtitle: lang.createNewSmartPlaylist,
              onTap: () {
                _closeDialog();
                NamidaNavigator.inst.navigateDialog(
                  dialog: const CreateSmartPlaylistDialog(),
                );
              },
            ),
          ],
        ),
      ),
    );
  }

  void _onPlaylistButtonConfigTap() {
    NamidaNavigator.inst.navigateDialog(
      dialogBuilder: (theme) => CustomBlurryDialog(
        theme: theme,
        normalTitleStyle: true,
        title: lang.configure,
        actions: const [
          CancelButton(addMargin: false),
        ],
        child: Column(
          children: [
            ObxO(
              rx: settings.enableM3USyncStartup,
              builder: (context, m3usyncstartup) => CustomSwitchListTile(
                leading: const StackedIcon(
                  baseIcon: Broken.music_library_2,
                  secondaryIcon: Broken.refresh_square_2,
                  secondaryIconSize: 12.0,
                ),
                title: lang.playlistsImportM3uSyncedAutoImport,
                subtitle: lang.playlistsImportM3uSynced,
                onChanged: (isTrue) => settings.save(enableM3USyncStartup: !isTrue),
                value: m3usyncstartup,
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _onAddToPlaylist({required LocalPlaylist playlist, required bool allTracksExist, required bool allowAddingEverything}) {
    if (allTracksExist == true) {
      final indexes = <int>[];
      playlist.tracks.loopAdv((e, index) {
        if (widget.tracksToAdd!.contains(e.track)) {
          indexes.add(index);
        }
      });
      NamidaNavigator.inst.navigateDialog(
        dialog: CustomBlurryDialog(
          isWarning: true,
          normalTitleStyle: true,
          bodyText: "${lang.removeFromPlaylist} ${playlist.name.translatePlaylistName().addDQuotation()}?",
          actions: [
            const CancelButton(),
            NamidaButton(
              colorScheme: Colors.red,
              text: lang.remove.toUpperCase(),
              onTap: () {
                NamidaNavigator.inst.closeDialog();
                PlaylistController.inst.removeTracksFromPlaylist(playlist, indexes);
              },
            ),
          ],
        ),
      );
    } else {
      final duplicateActions = allowAddingEverything ? PlaylistAddDuplicateAction.valuesForAdd : PlaylistAddDuplicateAction.valuesForAddExcludingAddEverything;
      PlaylistController.inst.addTracksToPlaylist(
        playlist,
        widget.tracksToAdd!,
        duplicationActions: duplicateActions,
      );
    }
  }

  bool _isReordering = false;

  void _toggleReordering() async {
    setState(() => _isReordering = !_isReordering);
    if (_isReordering) {
      await PlaylistController.inst.waitForPlaylistsLoad;
      PlaylistController.inst.ensureCustomOrderValid(removeNonExistent: true);
      if (settings.playlistSort.value != GroupSortType.custom || settings.playlistSortReversed.value) {
        // -- for consistent order while enabling/disabling
        settings.save(playlistSort: GroupSortType.custom, playlistSortReversed: false);
        PlaylistController.inst.sortPlaylists();
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final textTheme = context.textTheme;
    final tracksToAdd = widget.tracksToAdd;
    final isInsideDialog = tracksToAdd != null;
    final enableHero = !isInsideDialog;
    const libraryTab = LibraryTab.playlists;
    final scrollController = isInsideDialog ? null : libraryTab.scrollController;
    final defaultCardHorizontalPadding = Dimensions.inst.availableAppContentWidth * 0.045;
    final defaultCardHorizontalPaddingCenter = Dimensions.inst.availableAppContentWidth * 0.035;
    final countPerRowResolved = widget.countPerRow.resolve(context);

    const listHeader = ExpandableBoxEmptyAnimatedPadding(tab: libraryTab);

    return BackgroundWrapper(
      child: Listener(
        onPointerMove: (event) {
          final c = scrollController;
          if (c != null) onPointerMove(c, event);
        },
        onPointerUp: (event) => onRefresh(PlaylistController.inst.prepareM3UPlaylists),
        onPointerCancel: (event) => onVerticalDragFinish(),
        child: NamidaScrollbar(
          controller: scrollController,
          child: AnimationLimiter(
            child: ExpandableBoxColumn(
              tab: libraryTab,
              header: Obx(
                (context) {
                  final finalPlaylistsLength = SearchSortController.inst.playlistSearchList.valueR.length;
                  final totalPlaylistsLength = PlaylistController.inst.playlistsMap.valueR.length;
                  String leftText = finalPlaylistsLength != totalPlaylistsLength
                      ? '$finalPlaylistsLength/${totalPlaylistsLength.displayPlaylistKeyword}'
                      : finalPlaylistsLength.displayPlaylistKeyword;

                  return ExpandableBox(
                    enableHero: widget.enableHero && enableHero,
                    gridWidget: isInsideDialog
                        ? null
                        : const ChangeGridCountWidget(
                            tab: libraryTab,
                          ),
                    isBarVisible: libraryTab.isBarVisible.valueR,
                    leftText: leftText,
                    onSearchBoxVisibilityChange: (newShow) => ScrollSearchController.inst.onSearchBoxVisibiltyChange(libraryTab, newShow),
                    onCloseButtonPressed: () => ScrollSearchController.inst.clearSearchTextField(libraryTab),
                    disableSorting: tracksToAdd != null && tracksToAdd.isNotEmpty,
                    sortByMenuWidget: SortByMenu(
                      title: settings.playlistSort.valueR.toText(),
                      popupMenuChild: const SortByMenuPlaylist(),
                      isCurrentlyReversed: settings.playlistSortReversed.valueR,
                      onReverseIconTap: () => SearchSortController.inst.sortMedia(MediaType.playlist, reverse: !settings.playlistSortReversed.value),
                    ),
                    textField: CustomTextField(
                      textFieldController: libraryTab.textSearchControllerUI,
                      textFieldHintText: lang.filterPlaylists,
                      onTextFieldValueChanged: (value) => SearchSortController.inst.searchMedia(value, MediaType.playlist),
                    ),
                  );
                },
              ),
              page: Stack(
                children: [
                  SmoothCustomScrollView(
                    controller: scrollController,
                    slivers: [
                      SliverToBoxAdapter(child: listHeader),

                      if (!isInsideDialog)
                        SliverToBoxAdapter(
                          child: NamidaHero(
                            enabled: enableHero,
                            tag: 'PlaylistPage_TopRow',
                            child: Container(
                              padding: const EdgeInsets.symmetric(horizontal: 12.0),
                              child: Row(
                                mainAxisAlignment: MainAxisAlignment.end,
                                children: [
                                  const SizedBox(width: 12.0),

                                  // Expanded(
                                  //   child: ObxO(
                                  //     rx: PlaylistController.inst.playlistsMap,
                                  //     builder: (context, playlistsMap) => Text(
                                  //       playlistsMap.length.displayPlaylistKeyword,
                                  //       style: textTheme.displayLarge,
                                  //       maxLines: 2,
                                  //       overflow: TextOverflow.ellipsis,
                                  //     ),
                                  //   ),
                                  // ),
                                  // const SizedBox(width: 12.0),
                                  NamidaButton(
                                    icon: Broken.add,
                                    text: lang.add,
                                    iconSize: 20.0,
                                    onTap: _onAddPlaylistsTap,
                                  ),
                                  // const SizedBox(width: 8.0),
                                  // NamidaButton(
                                  //   icon: Broken.pen_add,
                                  //   text: lang.create,
                                  //   iconSize: 19.0,
                                  //   onTap: () {
                                  //     showSettingDialogWithTextField(
                                  //       title: lang.createNewPlaylist,
                                  //       addNewPlaylist: true,
                                  //     );
                                  //   },
                                  // ),
                                  const SizedBox(width: 8.0),
                                  NamidaButton(
                                    icon: Broken.edit_2,
                                    iconSize: 20.0,
                                    tooltip: () => _isReordering ? lang.disableReordering : lang.enableReordering,
                                    onTap: _toggleReordering,
                                    colorScheme: _isReordering ? context.theme.colorScheme.secondaryContainer : null,
                                  ),
                                  const SizedBox(width: 8.0),
                                  NamidaButton(
                                    icon: Broken.setting_4,
                                    iconSize: 20.0,
                                    onTap: _onPlaylistButtonConfigTap,
                                  ),
                                  const SizedBox(width: 8.0),
                                ],
                              ),
                            ),
                          ),
                        ),
                      const SliverPadding(padding: EdgeInsets.only(top: 6.0)),

                      /// Default Playlists.
                      if (!isInsideDialog)
                        SliverToBoxAdapter(
                          child: SizedBox(
                            width: context.width,
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                SizedBox(height: defaultCardHorizontalPadding * 0.5),
                                Row(
                                  children: [
                                    SizedBox(width: defaultCardHorizontalPadding),
                                    Expanded(
                                      child: NamidaHero(
                                        enabled: enableHero,
                                        tag: 'DPC_history',
                                        child: ObxO(
                                          rx: HistoryController.inst.totalHistoryItemsCount,
                                          builder: (context, count) => DefaultPlaylistCard(
                                            colorScheme: Colors.grey,
                                            icon: Broken.refresh,
                                            title: lang.history,
                                            displayLoadingIndicator: count == -1,
                                            text: count.formatDecimal(),
                                            onTap: NamidaOnTaps.inst.onHistoryPlaylistTap,
                                          ),
                                        ),
                                      ),
                                    ),
                                    SizedBox(width: defaultCardHorizontalPaddingCenter),
                                    Expanded(
                                      child: NamidaHero(
                                        enabled: enableHero,
                                        tag: 'DPC_mostplayed',
                                        child: Obx(
                                          (context) => DefaultPlaylistCard(
                                            colorScheme: Colors.green,
                                            icon: Broken.award,
                                            title: lang.mostPlayed,
                                            displayLoadingIndicator: HistoryController.inst.isLoadingHistoryR,
                                            text: HistoryController.inst.topTracksMapListens.valueR.length.formatDecimal(),
                                            onTap: () => NamidaOnTaps.inst.onMostPlayedPlaylistTap(),
                                          ),
                                        ),
                                      ),
                                    ),
                                    SizedBox(width: defaultCardHorizontalPadding),
                                  ],
                                ),
                                SizedBox(height: 12.0),
                                Row(
                                  children: [
                                    SizedBox(width: defaultCardHorizontalPadding),
                                    Expanded(
                                      child: NamidaHero(
                                        enabled: enableHero,
                                        tag: 'DPC_favs',
                                        child: ObxOClass(
                                          rx: PlaylistController.inst.favouritesPlaylist,
                                          builder: (context, favouritesPlaylist) => DefaultPlaylistCard(
                                            colorScheme: Colors.red,
                                            icon: Broken.heart,
                                            title: lang.favourites,
                                            text: favouritesPlaylist.value.tracks.length.formatDecimal(),
                                            onTap: () => NamidaOnTaps.inst.onNormalPlaylistTap(k_PLAYLIST_NAME_FAV),
                                          ),
                                        ),
                                      ),
                                    ),
                                    SizedBox(width: defaultCardHorizontalPaddingCenter),
                                    Expanded(
                                      child: NamidaHero(
                                        enabled: enableHero,
                                        tag: 'DPC_queues',
                                        child: Obx(
                                          (context) => DefaultPlaylistCard(
                                            colorScheme: Colors.blue,
                                            icon: Broken.driver,
                                            title: lang.queues,
                                            displayLoadingIndicator: !QueueController.inst.isQueuesLoaded,
                                            text: QueueController.inst.queuesMap.valueR.length.formatDecimal(),
                                            onTap: const QueuesPage().navigate,
                                          ),
                                        ),
                                      ),
                                    ),
                                    SizedBox(width: defaultCardHorizontalPadding),
                                  ],
                                ),
                                SizedBox(height: defaultCardHorizontalPadding * 0.5),
                              ],
                            ),
                          ),
                        ),
                      if (!isInsideDialog) ...[
                        const SliverPadding(padding: EdgeInsets.only(top: 10.0)),
                        SliverToBoxAdapter(
                          child: ObxO(
                            rx: SmartPlaylistsController.inst.smartPlaylistsMap,
                            builder: (context, smartPlaylistsMap) {
                              final smartPlaylists = smartPlaylistsMap.values.toFixedList();
                              if (smartPlaylists.isEmpty) return const SizedBox();
                              return SizedBox(
                                height: 48.0,
                                child: SuperSmoothListView.builder(
                                  padding: const EdgeInsets.symmetric(horizontal: 4.0),
                                  scrollDirection: Axis.horizontal,
                                  itemCount: smartPlaylists.length,
                                  itemBuilder: (context, index) {
                                    final smplWrapper = smartPlaylists[index];
                                    final imgFile = SmartPlaylistsController.inst.getArtworkFileForPlaylist(smplWrapper.value);
                                    return ConstrainedBox(
                                      constraints: BoxConstraints(maxWidth: context.width * 0.75),
                                      child: NamidaInkWell(
                                        margin: const EdgeInsets.symmetric(horizontal: 2.0),
                                        padding: const EdgeInsets.symmetric(vertical: 2.0),
                                        onTap: () {
                                          SmartPlaylistTracksPage(
                                            smartPlaylistWrapper: smplWrapper,
                                          ).navigate();
                                        },
                                        onLongPress: () => NamidaDialogs.inst.showSmartPlaylistDialog(smplWrapper),
                                        borderRadius: 8.0,
                                        bgColor: context.theme.colorScheme.secondary.withOpacityExt(0.12),
                                        child: Row(
                                          mainAxisSize: MainAxisSize.min,
                                          children: [
                                            const SizedBox(width: 4.0),
                                            ArtworkWidget(
                                              key: ValueKey(imgFile),
                                              track: null,
                                              thumbnailSize: 48.0,
                                              path: imgFile.path,
                                              forceSquared: true,
                                              icon: Broken.magicpen,
                                            ),
                                            const SizedBox(width: 6.0),
                                            Flexible(
                                              child: Text(
                                                smplWrapper.value.name,
                                                softWrap: false,
                                                overflow: TextOverflow.fade,
                                                style: textTheme.displayMedium,
                                              ),
                                            ),
                                            const SizedBox(width: 12.0),
                                          ],
                                        ),
                                      ),
                                    );
                                  },
                                ),
                              );
                            },
                          ),
                        ),
                      ],
                      const SliverPadding(padding: EdgeInsets.only(top: 10.0)),
                      if (isInsideDialog)
                        SliverToBoxAdapter(
                          child: ObxOClass(
                            rx: PlaylistController.inst.favouritesPlaylist,
                            builder: (context, favouritesPlaylist) {
                              bool? allTracksExist;
                              if (tracksToAdd.isNotEmpty) {
                                allTracksExist = tracksToAdd.every(favouritesPlaylist.isSubItemFavourite);
                              }
                              return PlaylistTile(
                                enableHero: enableHero,
                                playlistName: k_PLAYLIST_NAME_FAV,
                                onTap: () {
                                  _onAddToPlaylist(
                                    playlist: favouritesPlaylist.value,
                                    allTracksExist: allTracksExist == true,
                                    allowAddingEverything: false,
                                  );
                                },
                                checkmarkStatus: allTracksExist,
                              );
                            },
                          ),
                        ),
                      if (isInsideDialog)
                        const SliverToBoxAdapter(
                          child: NamidaContainerDivider(margin: EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0)),
                        ),
                      _isReordering
                          ? ObxO(
                              rx: PlaylistController.inst.getCustomIndicesOrderListRx(),
                              builder: (context, customIndicesOrderList) => NamidaSliverReorderableList(
                                itemExtent: Dimensions.playlistTileItemExtent,
                                onReorderStart: (index) => super.enablePullToRefresh = false,
                                onReorderEnd: (index) => super.enablePullToRefresh = true,
                                onReorder: (oldIndex, newIndex) async {
                                  if (settings.playlistSort.value != GroupSortType.custom) {
                                    settings.save(playlistSort: GroupSortType.custom);
                                  }
                                  PlaylistController.inst.onPlaylistReorder(oldIndex, newIndex);
                                },
                                itemCount: customIndicesOrderList!.length,
                                itemBuilder: (context, i) {
                                  final name = customIndicesOrderList[i];
                                  return NamidaReordererableListener(
                                    key: ValueKey(i),
                                    durationMs: 100,
                                    index: i,
                                    child: InkWell(
                                      onTap: () {},
                                      child: Row(
                                        children: [
                                          const ThreeLineSmallContainers(
                                            enabled: true,
                                          ),
                                          Expanded(
                                            child: AbsorbPointer(
                                              child: PlaylistTile(
                                                enableHero: enableHero,
                                                playlistName: name,
                                                onTap: null,
                                                checkmarkStatus: null,
                                              ),
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                  );
                                },
                              ),
                            )
                          : ObxO(
                              rx: settings.playlistSort,
                              builder: (context, sort) {
                                final sortTextIsUseless = sort == GroupSortType.title || sort == GroupSortType.numberOfTracks || sort == GroupSortType.duration;
                                final extraTextResolver = sortTextIsUseless ? null : SearchSortController.inst.getGroupSortExtraTextResolverPlaylist(sort);

                                late final existingStatus = <String, bool>{};
                                late final sortedIndices = <String, int>{};

                                return ObxPrefer(
                                  enabled: sort.requiresHistory,
                                  rx: HistoryController.inst.topTracksMapListens,
                                  builder: (context, _) => ObxO(
                                    rx: PlaylistController.inst.playlistsMap,
                                    builder: (context, playlistsMap) => ObxO(
                                      rx: SearchSortController.inst.playlistSearchList,
                                      builder: (context, playlistSearchListPre) {
                                        List<String> playlistSearchList;
                                        if (tracksToAdd != null && tracksToAdd.isNotEmpty) {
                                          // -- put playlists having the tracks at first
                                          final playlistSearchListSorted = <String>[];
                                          final shouldReSort = existingStatus.isEmpty; // sort only once, so that refresh won't make them jump around

                                          for (final key in playlistSearchListPre) {
                                            playlistSearchListSorted.add(key);
                                            final playlist = playlistsMap[key]!;
                                            final allTracksExist = tracksToAdd.every((trackToAdd) => playlist.tracks.firstWhereEff((e) => e.track == trackToAdd) != null);
                                            existingStatus[key] = allTracksExist;
                                          }
                                          playlistSearchListSorted.sortBy((key) => sortedIndices[key] ?? (existingStatus[key] == true ? -2 : -1));
                                          if (shouldReSort) {
                                            int index = 0;
                                            for (final p in playlistSearchListSorted) {
                                              sortedIndices[p] = index;
                                              index++;
                                            }
                                          }
                                          playlistSearchList = playlistSearchListSorted;
                                        } else {
                                          playlistSearchList = playlistSearchListPre;
                                        }
                                        return countPerRowResolved == 1
                                            ? SliverFixedExtentList.builder(
                                                itemCount: playlistSearchList.length,
                                                itemExtent: Dimensions.playlistTileItemExtent,
                                                itemBuilder: (context, i) {
                                                  final key = playlistSearchList[i];
                                                  final playlist = playlistsMap[key]!;
                                                  final allTracksExist = existingStatus[key];
                                                  final extraText = extraTextResolver?.call(playlist);
                                                  return AnimatingTile(
                                                    position: i,
                                                    shouldAnimate: _shouldAnimate,
                                                    allowTilting: true,
                                                    child: PlaylistTile(
                                                      enableHero: enableHero,
                                                      playlistName: key,
                                                      onTap: tracksToAdd != null
                                                          ? () {
                                                              _onAddToPlaylist(playlist: playlist, allTracksExist: allTracksExist == true, allowAddingEverything: true);
                                                            }
                                                          : () => NamidaOnTaps.inst.onNormalPlaylistTap(key),
                                                      checkmarkStatus: allTracksExist,
                                                      extraText: extraText, // dont fallback to prevent confusion
                                                    ),
                                                  );
                                                },
                                              )
                                            : countPerRowResolved > 1
                                            ? SliverGrid.builder(
                                                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                                                  crossAxisCount: countPerRowResolved,
                                                  childAspectRatio: 0.8,
                                                  mainAxisSpacing: 8.0,
                                                ),
                                                itemCount: playlistSearchList.length,
                                                itemBuilder: (context, i) {
                                                  final key = playlistSearchList[i];
                                                  final playlist = playlistsMap[key]!;
                                                  final extraText = extraTextResolver?.call(playlist);
                                                  return AnimatingGrid(
                                                    countPerRowResolved: countPerRowResolved,
                                                    columnCount: playlistSearchList.length,
                                                    position: i,
                                                    shouldAnimate: _shouldAnimate,
                                                    child: MultiArtworkCard(
                                                      enableHero: enableHero,
                                                      heroTag: 'playlist_${playlist.name}',
                                                      tracks: playlist.tracks.toTracks(),
                                                      name: playlist.name.translatePlaylistName(),
                                                      countPerRow: widget.countPerRow,
                                                      showMenuFunction: () => NamidaDialogs.inst.showPlaylistDialog(key),
                                                      onTap: () => NamidaOnTaps.inst.onNormalPlaylistTap(key),
                                                      artworkFile: PlaylistController.inst.getArtworkFileForPlaylist(playlist.name),
                                                      widgetsInStack: [
                                                        if (playlist.m3uPath != null)
                                                          Positioned(
                                                            bottom: 8.0,
                                                            right: 8.0,
                                                            child: NamidaTooltip(
                                                              message: () => "${lang.m3uPlaylist}\n${playlist.m3uPath?.formatPath()}",
                                                              child: const Icon(Broken.music_filter, size: 18.0),
                                                            ),
                                                          ),
                                                        if (extraText != null && extraText.isNotEmpty)
                                                          Positioned(
                                                            top: 0,
                                                            right: 0,
                                                            child: NamidaBlurryContainer(
                                                              child: Text(
                                                                extraText,
                                                                style: textTheme.displaySmall?.copyWith(
                                                                  fontSize: 12.0,
                                                                  fontWeight: FontWeight.bold,
                                                                ),
                                                                softWrap: false,
                                                                overflow: TextOverflow.fade,
                                                              ),
                                                            ),
                                                          ),
                                                      ],
                                                    ),
                                                  );
                                                },
                                              )
                                            : const SizedBox();
                                      },
                                    ),
                                  ),
                                );
                              },
                            ),
                      if (!isInsideDialog) kBottomPaddingWidgetSliver,
                    ],
                  ),
                  pullToRefreshWidget,
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}
