import 'package:flutter/material.dart';

import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';

import 'package:namida/class/count_per_row.dart';
import 'package:namida/class/route.dart';
import 'package:namida/controller/history_controller.dart';
import 'package:namida/controller/indexer_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/core/dimensions.dart';
import 'package:namida/core/enums.dart';
import 'package:namida/core/extensions.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/widgets/custom_widgets.dart';
import 'package:namida/ui/widgets/expandable_box.dart';
import 'package:namida/ui/widgets/library/artist_card.dart';
import 'package:namida/ui/widgets/library/artist_tile.dart';
import 'package:namida/ui/widgets/sort_by_button.dart';

class ArtistsPage extends StatelessWidget with NamidaRouteWidget {
  @override
  RouteType get route => RouteType.PAGE_artists;

  final RxList<String>? artists;
  final CountPerRow countPerRow;
  final bool enableGridIconButton;
  final bool animateTiles;
  final bool enableHero;
  final MediaType? customType;

  const ArtistsPage({
    super.key,
    this.artists,
    required this.countPerRow,
    this.enableGridIconButton = true,
    this.animateTiles = true,
    required this.enableHero,
    this.customType,
  });

  bool get _shouldAnimate => animateTiles && LibraryTab.artists.shouldAnimateTiles;

  List<NamidaPopupItem> _getTypeChooserChildren() {
    void onTap(MediaType type) {
      GroupSortType? newArtistSort;
      final currentArtistSort = settings.artistSort.value;
      // -- automatically resorting by the new type
      switch (currentArtistSort) {
        case GroupSortType.artistsList:
        case GroupSortType.albumArtist:
        case GroupSortType.composer:
          newArtistSort = switch (type) {
            MediaType.artist => GroupSortType.artistsList,
            MediaType.albumArtist => GroupSortType.albumArtist,
            MediaType.composer => GroupSortType.composer,
            _ => null,
          };
        default:
          null;
      }
      settings.save(activeArtistType: type);
      SearchSortController.inst.sortMedia(type, groupSortBy: newArtistSort, reverse: null);
    }

    return [
      NamidaPopupItem(
        icon: Broken.microphone,
        title: lang.artist,
        selected: MediaType.artist == settings.activeArtistType.value,
        onTap: () => onTap(MediaType.artist),
      ),
      NamidaPopupItem(
        icon: Broken.user,
        title: lang.albumArtist,
        selected: MediaType.albumArtist == settings.activeArtistType.value,
        onTap: () => onTap(MediaType.albumArtist),
      ),
      NamidaPopupItem(
        icon: Broken.profile_2user,
        title: lang.composer,
        selected: MediaType.composer == settings.activeArtistType.value,
        onTap: () => onTap(MediaType.composer),
      ),
    ];
  }

  @override
  Widget build(BuildContext context) {
    final textTheme = context.textTheme;
    const libraryTab = LibraryTab.artists;
    final scrollController = libraryTab.scrollController;
    final countPerRowResolved = countPerRow.resolve(context);
    final artistTypeColor = context.theme.colorScheme.onSecondaryContainer.withOpacityExt(0.8);
    final isCustomList = artists != null;

    const listHeader = ExpandableBoxEmptyAnimatedPadding(tab: libraryTab);

    return BackgroundWrapper(
      child: NamidaScrollbar(
        controller: scrollController,
        child: AnimationLimiter(
          child: ObxO(
            rx: artists ?? SearchSortController.inst.artistSearchList,
            builder: (context, finalArtists) => Obx(
              (context) {
                final artistTypeSettings = settings.activeArtistType.valueR;
                final artistType = customType ?? artistTypeSettings;
                final Function({required int count}) countToText = switch (artistType) {
                  MediaType.artist => lang.countArtists,
                  MediaType.albumArtist => lang.countAlbumArtists,
                  MediaType.composer => lang.countComposers,
                  _ => ({required int count}) => '',
                };
                final finalArtistsLength = finalArtists.length;
                final totalArtistsLength = Indexer.inst.getArtistMapFor(artistType).valueR.length;
                String artistLeftText = finalArtistsLength != totalArtistsLength
                    ? '$finalArtistsLength/${countToText(count: totalArtistsLength)}'
                    : countToText(count: finalArtistsLength);

                final sort = settings.artistSort.valueR;
                final sortReverse = settings.artistSortReversed.valueR;

                final sortTextIsUseless =
                    sort == GroupSortType.artistsList ||
                    (countPerRowResolved == 1 && (sort == GroupSortType.albumsCount || sort == GroupSortType.numberOfTracks || sort == GroupSortType.duration));
                final extraTextResolver = sortTextIsUseless ? null : SearchSortController.inst.getGroupSortExtraTextResolver(sort);

                return ExpandableBoxColumn(
                  tab: libraryTab,
                  header: ExpandableBox(
                    enableHero: enableHero,
                    gridWidget: enableGridIconButton
                        ? const ChangeGridCountWidget(
                            tab: libraryTab,
                          )
                        : null,
                    isBarVisible: libraryTab.isBarVisible.valueR,
                    leftText: customType != null ? artistLeftText : '',
                    leftWidgets: customType != null
                        ? null
                        : [
                            NamidaPopupWrapper(
                              childrenDefault: _getTypeChooserChildren,
                              child: Row(
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  Icon(
                                    Broken.arrange_circle,
                                    size: 14.0,
                                    color: artistTypeColor,
                                  ),
                                  const SizedBox(width: 4.0),
                                  Text(
                                    artistLeftText,
                                    style: textTheme.displayMedium?.copyWith(
                                      color: artistTypeColor,
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ],
                    onSearchBoxVisibilityChange: (newShow) => ScrollSearchController.inst.onSearchBoxVisibiltyChange(libraryTab, newShow),
                    onCloseButtonPressed: () => ScrollSearchController.inst.clearSearchTextField(libraryTab),
                    disableSorting: isCustomList,
                    sortByMenuWidget: SortByMenu(
                      title: sort.toText(),
                      popupMenuChild: const SortByMenuArtists(),
                      isCurrentlyReversed: sortReverse,
                      onReverseIconTap: () => SearchSortController.inst.sortMedia(settings.activeArtistType.value, reverse: !settings.artistSortReversed.value),
                    ),
                    textField: CustomTextField(
                      textFieldController: libraryTab.textSearchControllerUI,
                      textFieldHintText: lang.filterArtists,
                      onTextFieldValueChanged: (value) => SearchSortController.inst.searchMedia(value, settings.activeArtistType.value),
                    ),
                  ),
                  page: SmoothCustomScrollView(
                    controller: scrollController,
                    slivers: [
                      SliverToBoxAdapter(child: listHeader),
                      countPerRowResolved == 1
                          ? ObxPrefer(
                              enabled: sort.requiresHistory,
                              rx: HistoryController.inst.topTracksMapListens,
                              builder: (context, _) => SliverFixedExtentList.builder(
                                itemCount: finalArtists.length,
                                itemExtent: 65.0 + 2.0 * 9,
                                itemBuilder: (context, i) {
                                  final artist = finalArtists[i];
                                  final tracks = artist.getArtistTracksFor(artistType);
                                  return AnimatingTile(
                                    position: i,
                                    shouldAnimate: _shouldAnimate,
                                    allowTilting: true,
                                    child: ArtistTile(
                                      tracks: tracks,
                                      name: artist,
                                      albums: tracks.toUniqueAlbums(),
                                      type: artistType,
                                      extraText: extraTextResolver?.call(tracks),
                                    ),
                                  );
                                },
                              ),
                            )
                          : ObxPrefer(
                              enabled: sort.requiresHistory,
                              rx: HistoryController.inst.topTracksMapListens,
                              builder: (context, _) => SliverGrid.builder(
                                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                                  crossAxisCount: countPerRowResolved,
                                  childAspectRatio: 0.88,
                                  mainAxisSpacing: 8.0,
                                ),
                                itemCount: finalArtists.length,
                                itemBuilder: (context, i) {
                                  final artist = finalArtists[i];
                                  final tracks = artist.getArtistTracksFor(artistType);
                                  return AnimatingGrid(
                                    countPerRowResolved: countPerRowResolved,
                                    columnCount: finalArtists.length,
                                    position: i,
                                    shouldAnimate: _shouldAnimate,
                                    child: ArtistCard(
                                      name: artist,
                                      artist: tracks,
                                      type: artistType,
                                      bottomCenterText: extraTextResolver?.call(tracks),
                                    ),
                                  );
                                },
                              ),
                            ),
                      kBottomPaddingWidgetSliver,
                    ],
                  ),
                );
              },
            ),
          ),
        ),
      ),
    );
  }
}
