import 'dart:async';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

import 'package:super_sliver_list/super_sliver_list.dart';
import 'package:youtipie/class/channels/channel_info.dart';
import 'package:youtipie/class/stream_info_item/stream_info_item.dart';
import 'package:youtipie/class/stream_info_item/stream_info_item_short.dart';
import 'package:youtipie/class/streams/stream_segments.dart';
import 'package:youtipie/class/videos/video_info.dart';
import 'package:youtipie/class/youtipie_feed/playlist_info_item.dart';
import 'package:youtipie/core/enum.dart';
import 'package:youtipie/core/url_utils.dart';
import 'package:youtipie/youtipie.dart';

import 'package:namida/base/yt_video_like_manager.dart';
import 'package:namida/class/route.dart';
import 'package:namida/controller/current_color.dart';
import 'package:namida/controller/lyrics_controller.dart';
import 'package:namida/controller/miniplayer_controller.dart';
import 'package:namida/controller/navigator_controller.dart';
import 'package:namida/controller/player_controller.dart';
import 'package:namida/controller/settings_controller.dart';
import 'package:namida/controller/time_ago_controller.dart';
import 'package:namida/controller/video_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/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/packages/lyrics_lrc_parsed_view.dart';
import 'package:namida/packages/mp.dart';
import 'package:namida/packages/scroll_physics_modified.dart';
import 'package:namida/packages/three_arched_circle.dart';
import 'package:namida/ui/widgets/custom_widgets.dart';
import 'package:namida/ui/widgets/settings/extra_settings.dart';
import 'package:namida/youtube/class/download_task_base.dart';
import 'package:namida/youtube/class/youtube_id.dart';
import 'package:namida/youtube/controller/sponsorblock_controller.dart';
import 'package:namida/youtube/controller/youtube_controller.dart';
import 'package:namida/youtube/controller/youtube_history_controller.dart';
import 'package:namida/youtube/controller/youtube_info_controller.dart';
import 'package:namida/youtube/controller/yt_miniplayer_ui_controller.dart';
import 'package:namida/youtube/functions/add_to_playlist_sheet.dart';
import 'package:namida/youtube/functions/download_sheet.dart';
import 'package:namida/youtube/functions/video_listens_dialog.dart';
import 'package:namida/youtube/pages/yt_channel_subpage.dart';
import 'package:namida/youtube/seek_ready_widget.dart';
import 'package:namida/youtube/widgets/yt_action_button.dart';
import 'package:namida/youtube/widgets/yt_comment_card.dart';
import 'package:namida/youtube/widgets/yt_description_widget.dart';
import 'package:namida/youtube/widgets/yt_history_video_card.dart';
import 'package:namida/youtube/widgets/yt_playlist_card.dart';
import 'package:namida/youtube/widgets/yt_queue_chip.dart';
import 'package:namida/youtube/widgets/yt_shimmer.dart';
import 'package:namida/youtube/widgets/yt_subscribe_buttons.dart';
import 'package:namida/youtube/widgets/yt_thumbnail.dart';
import 'package:namida/youtube/widgets/yt_video_card.dart';
import 'package:namida/youtube/yt_miniplayer_comments_subpage.dart';
import 'package:namida/youtube/yt_utils.dart';

const _space2ForThumbnail = 90.0;
const _extraPaddingForYTMiniplayer = 12.0;
const kYoutubeMiniplayerHeight = _extraPaddingForYTMiniplayer + _space2ForThumbnail * 9 / 16;

class YoutubeMiniPlayer extends StatefulWidget {
  const YoutubeMiniPlayer({super.key});

  @override
  State<YoutubeMiniPlayer> createState() => YoutubeMiniPlayerState();
}

class YoutubeMiniPlayerState extends State<YoutubeMiniPlayer> {
  final _numberOfRepeats = 1.obs;
  final _isQueueFullyExpanded = false.obs;
  bool _canScrollQueue = true;

  NamidaYTMiniplayerState? get _mpState => MiniPlayerController.inst.ytMiniplayerKey.currentState;

  final _velocity = VelocityTracker.withKind(PointerDeviceKind.touch);

  void _updateCanScrollQueue(bool can) {
    if (_canScrollQueue == can) return;
    setState(() => _canScrollQueue = can);
  }

  final _scrollController = NamidaScrollController.create();

  void resetGlowUnderVideo() => _shouldShowGlowUnderVideo.value = false;

  final _shouldShowGlowUnderVideo = false.obs;
  final _isTitleExpanded = false.obs;
  final _canDimMiniplayer = false.obs;
  Timer? _dimTimer;

  void cancelDimTimer() {
    _dimTimer?.cancel();
    _dimTimer = null;
    final bool defaultKeepActive = settings.youtube.ytMiniplayerDimAfterSeconds.value == 0;
    if (!defaultKeepActive) _canDimMiniplayer.value = false;
  }

  void startDimTimer({Brightness? brightness}) {
    _dimTimer?.cancel();
    if (settings.youtube.enableDimInLightMode == false && (brightness ?? namida.context?.brightness) != Brightness.dark) {
      _canDimMiniplayer.value = false;
      return;
    }
    final double defaultMiniplayerOpacity = settings.youtube.ytMiniplayerDimOpacity.value;
    if (defaultMiniplayerOpacity <= 0) return;
    final int defaultMiniplayerDimSeconds = settings.youtube.ytMiniplayerDimAfterSeconds.value;
    if (defaultMiniplayerDimSeconds <= -1) return; // dont dim
    final bool defaultKeepActive = defaultMiniplayerDimSeconds == 0;
    if (defaultKeepActive) {
      _canDimMiniplayer.value = true;
    } else {
      _dimTimer = Timer(Duration(seconds: defaultMiniplayerDimSeconds), () {
        _canDimMiniplayer.value = true;
      });
    }
  }

  void _onVideoPageReset() {
    try {
      _scrollController.jumpTo(0);
    } catch (_) {}
    resetGlowUnderVideo();
    startDimTimer();
    // _expansibleController.collapse();
  }

  final _expansibleController = ExpansibleController();

  void openDescription() {
    _expansibleController.expand();
  }

  final _videoLikeManager = YtVideoLikeManager(pageRx: YoutubeInfoController.current.currentVideoPage);

  @override
  void initState() {
    super.initState();
    startDimTimer();
    _scrollController.addListener(() {
      final pixels = _scrollController.positions.lastOrNull?.pixels;
      final hasScrolledEnough = pixels != null && pixels > 40;
      _shouldShowGlowUnderVideo.value = hasScrolledEnough;
    });
    YoutubeInfoController.current.onVideoPageReset = _onVideoPageReset;
    _videoLikeManager.init();
  }

  @override
  void dispose() {
    YoutubeInfoController.current.onVideoPageReset = null;
    _scrollController.dispose();
    _numberOfRepeats.close();
    _isTitleExpanded.close();
    _shouldShowGlowUnderVideo.close();
    _isQueueFullyExpanded.close();
    _videoLikeManager.dispose();
    _expansibleController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    const space1sb = 8.0;
    const space2ForThumbnail = _space2ForThumbnail;
    const space3sb = 8.0;
    const space4 = 38.0 * 2;
    const space5sb = 8.0;
    const miniplayerHeight = kYoutubeMiniplayerHeight;

    const relatedThumbnailHeight = Dimensions.youtubeThumbnailHeight;
    const relatedThumbnailWidth = Dimensions.youtubeThumbnailWidth;
    const relatedThumbnailItemExtent = relatedThumbnailHeight + 8.0 * 2;

    const dummyVideoCard = YoutubeVideoCardDummy(
      shimmerEnabled: true, // this actually just to display dummy boxes
      thumbnailHeight: relatedThumbnailHeight,
      thumbnailWidth: relatedThumbnailWidth,
      displaythirdLineText: false,
    );

    final seekReadyWidget = SeekReadyWidget(key: SeekReadyWidget.normalKey);

    final maxWidth = Dimensions.inst.miniplayerMaxWidth;

    final mainTheme = context.theme;
    final mainTextTheme = context.textTheme;

    final miniplayerBGColor = Color.alphaBlend(mainTheme.secondaryHeaderColor.withOpacityExt(0.25), mainTheme.scaffoldBackgroundColor);

    final miniplayerDimWidget = IgnorePointer(
      key: const Key('dimmie'),
      child: ObxO(
        rx: _canDimMiniplayer,
        builder: (context, canDimMiniplayer) => CustomAnimatedSwitcher(
          duration: const Duration(milliseconds: 600),
          reverseDuration: const Duration(milliseconds: 200),
          child: canDimMiniplayer
              ? ObxO(
                  rx: settings.youtube.ytMiniplayerDimOpacity,
                  builder: (context, dimOpacity) => ConstrainedBox(
                    constraints: const BoxConstraints.expand(),
                    child: ColoredBox(
                      color: Colors.black.withOpacityExt(dimOpacity),
                    ),
                  ),
                )
              : null,
        ),
      ),
    );
    final ytMiniplayerQueueChip = YTMiniplayerQueueChip(
      key: NamidaNavigator.inst.ytQueueSheetKey,
      onExpandedStateChange: (isFullyExpanded) {
        _isQueueFullyExpanded.value = isFullyExpanded;
      },
      // -- we can no longer apply it on top sadly, lrc view can be in middle and it shouldn't be dimmed
      overlay: miniplayerDimWidget,
    );

    final rightDragAbsorberWidget = Align(
      alignment: Alignment.centerRight,
      child: SizedBox(
        height: context.height,
        width: (maxWidth * 0.25).withMaximum(324.0),
        child: Listener(
          behavior: HitTestBehavior.translucent,
          onPointerDown: (event) {
            if (NamidaNavigator.inst.isInYTCommentsSubpage || NamidaNavigator.inst.isInYTCommentRepliesSubpage) return;
            _mpState?.setDragExternally(true);
            _mpState?.saveDragHeightStart();
            _velocity.addPosition(event.timeStamp, event.position);
          },
          onPointerMove: (event) {
            if (NamidaNavigator.inst.isInYTCommentsSubpage || NamidaNavigator.inst.isInYTCommentRepliesSubpage) return;
            if (!_canScrollQueue) {
              _mpState?.onVerticalDragUpdate(event.delta.dy);
              _velocity.addPosition(event.timeStamp, event.position);
            }
          },
          onPointerCancel: (event) {
            WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
              _mpState?.setDragExternally(false);
            });
          },
          onPointerUp: (event) {
            if (!NamidaNavigator.inst.isInYTCommentsSubpage && !NamidaNavigator.inst.isInYTCommentRepliesSubpage) {
              if (_scrollController.hasClients && _scrollController.position.pixels <= 0) {
                _mpState?.onVerticalDragEnd(_velocity.getVelocity().pixelsPerSecond.dy);
              }
            }
            // thats because the internal GestureDetector executes drag end after Listener's onPointerUp
            WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
              _mpState?.setDragExternally(false);
            });
          },
        ),
      ),
    );

    return SafeArea(
      top: false,
      child: DefaultTextStyle(
        style: mainTextTheme.displayMedium!,
        child: ObxO(
          rx: settings.youtube.topComments,
          builder: (context, ytTopComments) => ObxO(
            rx: Player.inst.currentItem,
            builder: (context, currentItem) {
              if (currentItem is! YoutubeID) return const SizedBox();

              final currentId = currentItem.id;
              final currentIdTask = DownloadTaskVideoId(videoId: currentItem.id);

              return ObxO(
                rx: YoutubeController.inst.downloadedFilesMap,
                builder: (context, _) {
                  final downloadedFileExists = YoutubeController.inst.doesIDHasFileDownloaded(currentId) != null;
                  return ObxO(
                    rx: YoutubeInfoController.current.currentYTStreams,
                    builder: (context, streams) => ObxO(
                      rx: YoutubeInfoController.current.currentStreamInfo,
                      builder: (context, streamInfo) => ObxO(
                        rx: YoutubeInfoController.current.isLoadingVideoPage,
                        builder: (context, isLoadingVideoPage) => ObxO(
                          rx: YoutubeInfoController.current.currentVideoPage,
                          builder: (context, page) {
                            final shimmerEnabledDummyContainer = page == null;
                            final shimmerEnabled = isLoadingVideoPage && page == null;
                            final videoInfo = page?.videoInfo;
                            final videoInfoStream = streams?.info ?? streamInfo;
                            final channel = page?.channelInfo;

                            String? uploadDate;
                            String? uploadDateAgo;

                            DateTime? parsedDate =
                                videoInfoStream?.publishedAt.date ??
                                videoInfoStream?.publishDate.date ??
                                videoInfo?.publishedAt.accurateDate; // videoInfo?.publishedAt.date aint no way near accurate
                            bool accurateDate = true;
                            if (parsedDate == null) {
                              parsedDate = videoInfo?.publishedAt.date;
                              accurateDate = false;
                            }
                            if (parsedDate != null) {
                              if (accurateDate) uploadDate = parsedDate.dateFormattedOriginal;
                              uploadDateAgo = TimeAgoController.dateFromNow(parsedDate);
                            } else {
                              // uploadDateAgo = videoInfo?.publishedFromText; // warcrime
                            }
                            final videoTitle = videoInfo?.title ?? videoInfoStream?.title;
                            final channelName = channel?.title ?? videoInfoStream?.channelName;

                            final channelThumbnail = channel?.thumbnails.pick()?.url;
                            final channelIsVerified = channel?.isVerified ?? false;
                            final channelSubs = channel?.subscribersCount;
                            String? channelID = channel?.id ?? videoInfoStream?.channelId;
                            if (channelID == null || channelID.isEmpty) channelID = YoutubeInfoController.utils.getVideoChannelIDSync(currentId, checkFromStorage: false);

                            final videoViewCount = videoInfo?.viewsCount;

                            final description = videoInfo?.description;
                            final descriptionWidget = description == null
                                ? null
                                : Padding(
                                    padding: const EdgeInsets.symmetric(horizontal: 18.0),
                                    child: YoutubeDescriptionWidget(
                                      videoId: currentId,
                                      content: description,
                                    ),
                                  );

                            final segments = page?.streamSegments;
                            final segmentsRow = segments != null && segments.isNotEmpty
                                ? _StreamSegmentsRow(
                                    videoId: currentId,
                                    segments: segments,
                                  )
                                : null;
                            final epansionTileChildren = descriptionWidget != null || segmentsRow != null
                                ? [
                                    const SizedBox(height: 12.0),
                                    ?segmentsRow,
                                    if (segmentsRow != null && descriptionWidget != null) const SizedBox(height: 12.0),
                                    ?descriptionWidget,
                                    const SizedBox(height: 12.0),
                                  ]
                                : null;

                            final defaultIconColor = context.defaultIconColor(CurrentColor.inst.miniplayerColor);

                            // ====  MiniPlayer Body, contains title, description, comments, ..etc. ====
                            final miniplayerBody = Obx(
                              (context) {
                                final showLyrics =
                                    settings.enableLyrics.valueR && (Lyrics.inst.currentLyricsLRC.valueR != null || Lyrics.inst.currentLyricsText.valueR.text.isNotEmpty);
                                return Stack(
                                  alignment: Alignment.bottomCenter, // bottom alignment is for touch absorber
                                  children: [
                                    // opacity: (percentage * 4 - 3).withMinimum(0),
                                    CustomAnimatedSwitcher(
                                      duration: const Duration(milliseconds: 300),
                                      child: showLyrics
                                          ? LongPressDetector(
                                              key: const ValueKey('lyrics_on'),
                                              onLongPress: () => Lyrics.inst.lrcViewKey.currentState?.enterFullScreen(),
                                              child: LyricsLRCParsedView(
                                                key: Lyrics.inst.lrcViewKey,
                                                videoOrImage: const SizedBox(),
                                                allowOverflow: false,
                                                blurColorMaskOpacity: 0.75,
                                                useSafeArea: false,
                                                isFullScreenView: true,
                                                canShowToggleFullscreenButton: false,
                                                verticalPadding: 64.0,
                                                bottomPadding: const SizedBox(height: kYTQueueSheetMinHeight),
                                                onCloseFullscreenButtonTap: () {
                                                  settings.save(enableLyrics: false);
                                                  Lyrics.inst.resetLyrics();
                                                },
                                              ),
                                            )
                                          : KeyedSubtree(
                                              key: const ValueKey('lyrics_off'),
                                              child: Stack(
                                                children: [
                                                  ObxO(
                                                    rx: _isQueueFullyExpanded,
                                                    builder: (context, isQueueFullyExpanded) => Visibility(
                                                      maintainState: true,
                                                      visible: !isQueueFullyExpanded,
                                                      child: Listener(
                                                        key: Key("${currentId}_body_listener"),
                                                        onPointerMove: (event) {
                                                          if (event.delta.dy > 0) {
                                                            if (_scrollController.hasClients) {
                                                              if (_scrollController.position.pixels <= 0) {
                                                                _updateCanScrollQueue(false);
                                                              }
                                                            }
                                                          } else {
                                                            if (_mpState == null || _mpState?.controller.value == 1) _updateCanScrollQueue(true);
                                                          }
                                                        },
                                                        onPointerDown: (_) {
                                                          cancelDimTimer();
                                                          _updateCanScrollQueue(true);
                                                        },
                                                        onPointerUp: (_) {
                                                          startDimTimer();
                                                          _updateCanScrollQueue(true);
                                                        },
                                                        child: NamidaNavigatorWidget(
                                                          navKey: NamidaNavigator.inst.ytMiniplayerCommentsPageKey,
                                                          allowPop: false,
                                                          restorationScopeId: currentId,
                                                          pages: [
                                                            MaterialPage(
                                                              maintainState: true,
                                                              child: _YTPlayerInnerPage(
                                                                canScrollQueue: _canScrollQueue,
                                                                currentId: currentId,
                                                                scrollController: _scrollController,
                                                                shimmerEnabled: shimmerEnabled,
                                                                shimmerEnabledDummyContainer: shimmerEnabledDummyContainer,
                                                                ytTopComments: ytTopComments,
                                                                videoTitle: videoTitle,
                                                                mainTheme: mainTheme,
                                                                isTitleExpanded: _isTitleExpanded,
                                                                mainTextTheme: mainTextTheme,
                                                                numberOfRepeats: _numberOfRepeats,
                                                                uploadDate: uploadDate,
                                                                uploadDateAgo: uploadDateAgo,
                                                                maxWidth: maxWidth,
                                                                videoViewCount: videoViewCount,
                                                                expansibleController: _expansibleController,
                                                                epansionTileChildren: epansionTileChildren,
                                                                videoLikeManager: _videoLikeManager,
                                                                videoInfo: videoInfo,
                                                                currentIdTask: currentIdTask,
                                                                downloadedFileExists: downloadedFileExists,
                                                                channelName: channelName,
                                                                channelThumbnail: channelThumbnail,
                                                                channelSubs: channelSubs,
                                                                channel: channel,
                                                                channelID: channelID,
                                                                channelIsVerified: channelIsVerified,
                                                                defaultIconColor: defaultIconColor,
                                                                dummyVideoCard: dummyVideoCard,
                                                                relatedThumbnailItemExtent: relatedThumbnailItemExtent,
                                                                relatedThumbnailHeight: relatedThumbnailHeight,
                                                                relatedThumbnailWidth: relatedThumbnailWidth,
                                                                shouldShowGlowUnderVideo: _shouldShowGlowUnderVideo,
                                                              ),
                                                            ),
                                                          ],
                                                        ),
                                                      ),
                                                    ),
                                                  ),
                                                  Positioned.fill(
                                                    child: miniplayerDimWidget, // -- dimming
                                                  ),
                                                ],
                                              ),
                                            ),
                                    ),
                                    rightDragAbsorberWidget,
                                    ytMiniplayerQueueChip,
                                  ],
                                );
                              },
                            );

                            final titleChild = Column(
                              key: Key("${currentId}_title_button1_child"),
                              mainAxisAlignment: MainAxisAlignment.center,
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                NamidaDummyContainer(
                                  borderRadius: 4.0,
                                  height: 16.0,
                                  shimmerEnabled: shimmerEnabledDummyContainer && videoTitle == null,
                                  width: maxWidth - 24.0,
                                  child: Text(
                                    videoTitle ?? '',
                                    maxLines: 1,
                                    overflow: TextOverflow.ellipsis,
                                    style: mainTextTheme.displayMedium?.copyWith(
                                      fontWeight: FontWeight.w600,
                                      fontSize: 13.5,
                                    ),
                                  ),
                                ),
                                const SizedBox(height: 4.0),
                                NamidaDummyContainer(
                                  borderRadius: 4.0,
                                  height: 10.0,
                                  shimmerEnabled: shimmerEnabledDummyContainer && channelName == null,
                                  width: maxWidth - 24.0 * 2,
                                  child: Text(
                                    channelName ?? '',
                                    style: mainTextTheme.displaySmall?.copyWith(
                                      fontWeight: FontWeight.w500,
                                      fontSize: 13.0,
                                    ),
                                    maxLines: 1,
                                    overflow: TextOverflow.ellipsis,
                                  ),
                                ),
                              ],
                            );

                            final playPauseButtonChild = ObxO(
                              rx: Player.inst.playWhenReady,
                              builder: (context, playWhenReady) => Obx(
                                (context) {
                                  final isLoading = Player.inst.shouldShowLoadingIndicatorR;
                                  return Stack(
                                    alignment: Alignment.center,
                                    children: [
                                      if (isLoading)
                                        IgnorePointer(
                                          child: ThreeArchedCircle(
                                            key: Key("${currentId}_button_loading_child"),
                                            color: defaultIconColor.withOpacityExt(0.3),
                                            size: 36.0,
                                          ),
                                        ),
                                      NamidaIconButton(
                                        verticalPadding: 4.0,
                                        horizontalPadding: 4.0,
                                        onPressed: Player.inst.togglePlayPause,
                                        icon: null,
                                        child: CustomAnimatedSwitcher(
                                          duration: const Duration(milliseconds: 200),
                                          child: playWhenReady
                                              ? Icon(
                                                  Broken.pause,
                                                  color: defaultIconColor,
                                                  key: const Key('pause'),
                                                )
                                              : Icon(
                                                  Broken.play,
                                                  color: defaultIconColor,
                                                  key: const Key('play'),
                                                ),
                                        ),
                                      ),
                                    ],
                                  );
                                },
                              ),
                            );
                            final nextButton = NamidaIconButton(
                              verticalPadding: 4.0,
                              horizontalPadding: 4.0,
                              icon: Broken.next,
                              iconColor: defaultIconColor,
                              onPressed: () {
                                Player.inst.next();
                              },
                            );

                            final videoWidget = NamidaVideoWidget(
                              key: const ValueKey('nvw'),
                              isLocal: false,
                              disableControlsUnderPercentage: 0.5,
                              onMinimizeTap: Dimensions.inst.miniplayerIsWideScreen ? null : () => MiniPlayerController.inst.ytMiniplayerKey.currentState?.animateToState(false),
                              swipeUpToFullscreen: true,
                            );

                            return ObxO(
                              rx: settings.enableBottomNavBar,
                              builder: (context, enableBottomNavBar) => ObxO(
                                rx: settings.dismissibleMiniplayer,
                                builder: (context, dismissibleMiniplayer) => NamidaYTMiniplayer(
                                  key: MiniPlayerController.inst.ytMiniplayerKey,
                                  enforceExpanded: Dimensions.inst.miniplayerIsWideScreen,
                                  duration: const Duration(milliseconds: 1000),
                                  curve: Curves.easeOutExpo,
                                  bottomMargin: 8.0 + (enableBottomNavBar ? kBottomNavigationBarHeight : 0.0) - 1.0, // -1 is just a clip ensurer.
                                  minHeight: miniplayerHeight,
                                  maxHeight: context.height,
                                  bgColor: miniplayerBGColor,
                                  displayBottomBGLayer: !enableBottomNavBar,
                                  onDismiss: dismissibleMiniplayer ? Player.inst.clearQueue : null,
                                  onDismissing: (dismissPercentage) {
                                    if (Player.inst.isPlaying.value) {
                                      final maxVolume = Player.inst.userPlayerVolumeForItem;
                                      Player.inst.setVolume((dismissPercentage * maxVolume).clampDouble(0.0, maxVolume));
                                    }
                                  },
                                  onHeightChange: (percentage) {
                                    MiniPlayerController.inst.animateMiniplayer(percentage);
                                  },
                                  onExpandedStateChange: (isExpanded) {
                                    MiniPlayerController.inst.setImmersiveMode(null);
                                    HeatMapListener.onMiniplayerExpandedStateChange(isExpanded);
                                  },
                                  onAlternativePercentageExecute: () {
                                    VideoController.inst.toggleFullScreenVideoView(
                                      isLocal: false,
                                      setOrientations: false,
                                    );
                                  },
                                  builder: (double height, double p, Animation<double> reverseOpacityAnimation) {
                                    final percentage = (p * 2.8).clampDouble(0.0, 1.0);
                                    final percentageFast = (p * 1.5 - 0.5).clampDouble(0.0, 1.0);
                                    final inversePerc = 1 - percentage;
                                    final finalspace1sb = space1sb * inversePerc;
                                    final finalspace3sb = space3sb * inversePerc;
                                    final finalspace4buttons = space4 * inversePerc;
                                    final finalspace5sb = space5sb * inversePerc;
                                    final finalpadding = 4.0 * inversePerc;
                                    final finalbr = (8.0 * inversePerc).multipliedRadius;
                                    final double finalthumbnailWidth = (space2ForThumbnail + maxWidth * percentage).clampDouble(
                                      space2ForThumbnail,
                                      (maxWidth - finalspace1sb - finalspace3sb).toDouble(),
                                    );
                                    final finalthumbnailHeight = finalthumbnailWidth * 9 / 16;

                                    return Stack(
                                      children: [
                                        Column(
                                          crossAxisAlignment: CrossAxisAlignment.start,
                                          children: [
                                            Row(
                                              children: [
                                                SizedBox(width: finalspace1sb),
                                                Container(
                                                  clipBehavior: Clip.antiAlias,
                                                  margin: EdgeInsets.symmetric(vertical: finalpadding),
                                                  decoration: BoxDecoration(
                                                    color: Colors.black,
                                                    borderRadius: BorderRadius.circular(finalbr),
                                                  ),
                                                  width: finalthumbnailWidth,
                                                  height: finalthumbnailHeight,
                                                  child: videoWidget,
                                                ),
                                                FadeIgnoreTransition(
                                                  completelyKillWhenPossible: true,
                                                  opacity: reverseOpacityAnimation,
                                                  child: Row(
                                                    children: [
                                                      SizedBox(width: finalspace3sb),
                                                      SizedBox(
                                                        width: (maxWidth - finalthumbnailWidth - finalspace1sb - finalspace3sb - finalspace4buttons - finalspace5sb).clampDouble(
                                                          0,
                                                          maxWidth,
                                                        ),
                                                        child: titleChild,
                                                      ),
                                                      SizedBox(
                                                        key: Key("${currentId}_title_button2_child"),
                                                        width: finalspace4buttons / 2,
                                                        height: miniplayerHeight,
                                                        child: playPauseButtonChild,
                                                      ),
                                                      SizedBox(
                                                        key: Key("${currentId}_title_button3_child"),
                                                        width: finalspace4buttons / 2,
                                                        height: miniplayerHeight,
                                                        child: nextButton,
                                                      ),
                                                      SizedBox(width: finalspace5sb),
                                                    ],
                                                  ),
                                                ),
                                              ],
                                            ),

                                            // ---- if was in comments subpage, and this gets hidden, the route is popped
                                            // ---- same with [isQueueSheetOpen]
                                            if (NamidaNavigator.inst.isInYTCommentsSubpage ||
                                                    NamidaNavigator.inst.isInYTCommentRepliesSubpage ||
                                                    NamidaNavigator.inst.isQueueSheetOpen
                                                ? true
                                                : percentage > 0)
                                              Expanded(
                                                child: Stack(
                                                  fit: StackFit.expand,
                                                  children: [
                                                    miniplayerBody,
                                                    IgnorePointer(
                                                      child: ColoredBox(
                                                        color: miniplayerBGColor.withOpacityExt(1 - percentageFast),
                                                      ),
                                                    ),
                                                  ],
                                                ),
                                              ),
                                          ],
                                        ),
                                        Positioned(
                                          top:
                                              finalthumbnailHeight -
                                              (_extraPaddingForYTMiniplayer / 2 * inversePerc) -
                                              SeekReadyDimensions.barHeight +
                                              (SeekReadyDimensions.barHeight * (0.5 * inversePerc)) +
                                              (SeekReadyDimensions.progressBarHeight / 2),
                                          left: 0,
                                          right: 0,
                                          child: seekReadyWidget,
                                        ),
                                      ],
                                    );
                                  },
                                ),
                              ),
                            );
                          },
                        ),
                      ),
                    ),
                  );
                },
              );
            },
          ),
        ),
      ),
    );
  }
}

class _YTPlayerInnerPage extends StatelessWidget {
  final bool _canScrollQueue;
  final String currentId;
  final ScrollController _scrollController;
  final bool shimmerEnabled;
  final bool shimmerEnabledDummyContainer;
  final bool ytTopComments;
  final String? videoTitle;
  final ThemeData mainTheme;
  final Rx<bool> _isTitleExpanded;
  final TextTheme mainTextTheme;
  final Rx<int> _numberOfRepeats;
  final String? uploadDate;
  final String? uploadDateAgo;
  final double maxWidth;
  final int? videoViewCount;
  final ExpansibleController? expansibleController;
  final List<Widget>? epansionTileChildren;
  final YtVideoLikeManager _videoLikeManager;
  final YoutiPieVideoInfo? videoInfo;
  final DownloadTaskVideoId currentIdTask;
  final bool downloadedFileExists;
  final String? channelName;
  final String? channelThumbnail;
  final int? channelSubs;
  final YoutiPieChannelInfo? channel;
  final String? channelID;
  final bool channelIsVerified;
  final Color defaultIconColor;
  final YoutubeVideoCardDummy dummyVideoCard;
  final double relatedThumbnailItemExtent;
  final double relatedThumbnailHeight;
  final double relatedThumbnailWidth;
  final Rx<bool> _shouldShowGlowUnderVideo;

  const _YTPlayerInnerPage({
    required this._canScrollQueue,
    required this.currentId,
    required this._scrollController,
    required this.shimmerEnabled,
    required this.videoTitle,
    required this.mainTheme,
    required this._isTitleExpanded,
    required this.mainTextTheme,
    required this._numberOfRepeats,
    required this.uploadDate,
    required this.uploadDateAgo,
    required this.maxWidth,
    required this.shimmerEnabledDummyContainer,
    required this.videoViewCount,
    required this.expansibleController,
    required this.epansionTileChildren,
    required this._videoLikeManager,
    required this.videoInfo,
    required this.currentIdTask,
    required this.downloadedFileExists,
    required this.channelName,
    required this.channelThumbnail,
    required this.channelSubs,
    required this.channel,
    required this.channelID,
    required this.channelIsVerified,
    required this.defaultIconColor,
    required this.dummyVideoCard,
    required this.relatedThumbnailItemExtent,
    required this.ytTopComments,
    required this.relatedThumbnailHeight,
    required this.relatedThumbnailWidth,
    required this._shouldShowGlowUnderVideo,
  });

  Future<bool> _onLikeTap({
    required bool isLiked,
    required NamidaLoadingController loadingController,
  }) {
    return _videoLikeManager.onLikeClicked(
      YTVideoLikeParamters(
        isActive: isLiked,
        action: isLiked ? LikeAction.removeLike : LikeAction.addLike,
        onStart: loadingController.startLoading,
        onEnd: loadingController.stopLoading,
      ),
    );
  }

  Future<bool> _onDislikeTap({
    required bool isDisLiked,
    required NamidaLoadingController loadingController,
  }) {
    return _videoLikeManager.onDisLikeClicked(
      YTVideoLikeParamters(
        isActive: isDisLiked,
        action: isDisLiked ? LikeAction.removeDislike : LikeAction.addDislike,
        onStart: loadingController.startLoading,
        onEnd: loadingController.stopLoading,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final videoViewCount = this.videoViewCount;
    final channelSubs = this.channelSubs;
    final channelID = this.channelID;
    return IgnorePointer(
      ignoring: !_canScrollQueue,
      child: VideoTilePropertiesProvider(
        configs: VideoTilePropertiesConfigs(
          queueSource: QueueSourceYoutubeID.ytRelatedVideos,
          showMoreIcon: true,
        ),
        builder: (properties) => LazyLoadListView(
          key: Key("${currentId}_body_lazy_load_list"),
          onReachingEnd: ytTopComments ? () => false : () => YoutubeInfoController.current.updateCurrentComments(currentId),
          extend: 400,
          scrollController: _scrollController,
          listview: (controller) => Stack(
            key: Key("${currentId}_body_stack"),
            children: [
              SmoothCustomScrollView(
                // key: PageStorageKey(currentId), // duplicate errors
                physics: _canScrollQueue ? const ClampingScrollPhysicsModified() : const NeverScrollableScrollPhysics(),
                controller: controller,
                slivers: [
                  // --START-- title & subtitle
                  SliverToBoxAdapter(
                    key: Key("${currentId}_title"),
                    child: ShimmerWrapper(
                      shimmerDurationMS: 550,
                      shimmerDelayMS: 250,
                      shimmerEnabled: shimmerEnabled && videoTitle == null,
                      child: ExpansionTile(
                        controller: expansibleController,
                        // key: Key(currentId),
                        backgroundColor: Colors.transparent,
                        collapsedShape: const Border(),
                        shape: const Border(),
                        initiallyExpanded: false,
                        maintainState: false,
                        expandedAlignment: Alignment.centerLeft,
                        expandedCrossAxisAlignment: CrossAxisAlignment.start,
                        tilePadding: const EdgeInsets.symmetric(vertical: 6.0, horizontal: 14.0),
                        textColor: Color.alphaBlend(CurrentColor.inst.miniplayerColor.withAlpha(40), mainTheme.colorScheme.onSurface),
                        collapsedTextColor: mainTheme.colorScheme.onSurface,
                        iconColor: Color.alphaBlend(CurrentColor.inst.miniplayerColor.withAlpha(40), mainTheme.colorScheme.onSurface),
                        collapsedIconColor: mainTheme.colorScheme.onSurface,
                        childrenPadding: EdgeInsets.zero,
                        onExpansionChanged: (value) => _isTitleExpanded.value = value,
                        trailing: Row(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            ObxO(
                              rx: YoutubeHistoryController.inst.topTracksMapListens,
                              builder: (context, topTracksMapListens) {
                                final videoListens = topTracksMapListens[currentId] ?? [];
                                if (videoListens.isEmpty) return const SizedBox();
                                return NamidaInkWell(
                                  borderRadius: 6.0,
                                  bgColor: CurrentColor.inst.miniplayerColor.withOpacityExt(0.7),
                                  onTap: () {
                                    showVideoListensDialog(currentId);
                                  },
                                  padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 2.0),
                                  child: Text(
                                    videoListens.length.formatDecimal(),
                                    style: mainTextTheme.displaySmall?.copyWith(
                                      color: Colors.white.withOpacityExt(0.6),
                                    ),
                                  ),
                                );
                              },
                            ),
                            const SizedBox(width: 8.0),
                            NamidaPopupWrapper(
                              onPop: () {
                                _numberOfRepeats.value = 1;
                              },
                              childrenDefault: () => YTUtils.getVideoCardMenuItemsForCurrentlyPlaying(
                                queueSource: QueueSourceYoutubeID.ytPlayerQueue,
                                numberOfRepeats: _numberOfRepeats,
                                videoId: currentId,
                                videoTitle: videoTitle,
                                channelID: null,
                                displayGoToChannel: false,
                                displayCopyUrl: false,
                              ),
                              child: const Icon(
                                Broken.arrow_down_2,
                                size: 20.0,
                              ),
                            ),
                          ],
                        ),
                        title: ObxO(
                          rx: _isTitleExpanded,
                          builder: (context, isTitleExpanded) {
                            // String? dateToShow;
                            // if (isTitleExpanded) {
                            //   dateToShow = uploadDate ?? uploadDateAgo;
                            // } else {
                            //   dateToShow = uploadDateAgo ?? uploadDate;
                            // }
                            return Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                NamidaDummyContainer(
                                  width: maxWidth * 0.8,
                                  height: 24.0,
                                  borderRadius: 6.0,
                                  shimmerEnabled: shimmerEnabledDummyContainer && videoTitle == null,
                                  child: Text(
                                    videoTitle ?? '',
                                    maxLines: isTitleExpanded ? 6 : 2,
                                    overflow: TextOverflow.ellipsis,
                                    style: mainTextTheme.displayLarge,
                                  ),
                                ),
                                const SizedBox(height: 6.0),
                                NamidaDummyContainer(
                                  width: maxWidth * 0.4,
                                  height: 12.0,
                                  shimmerEnabled: shimmerEnabledDummyContainer && videoViewCount == null && uploadDateAgo == null && uploadDate == null,
                                  child: IgnorePointer(
                                    child: Row(
                                      mainAxisSize: .min,
                                      children:
                                          [
                                                if (videoViewCount != null) (videoViewCount.formatDecimalShort(), Broken.eye),
                                                if (uploadDate != null) (uploadDate!, Broken.calendar),
                                                if (uploadDateAgo != null) (uploadDateAgo!, Broken.clock),
                                              ]
                                              .map(
                                                (info) => Flexible(
                                                  child: FittedBox(
                                                    fit: .scaleDown,
                                                    child: NamidaInkWell(
                                                      borderRadius: 6.0,
                                                      bgColor: context.theme.cardColor.withOpacityExt(0.5),
                                                      padding: const EdgeInsetsGeometry.symmetric(horizontal: 6.0, vertical: 4.0),
                                                      onTap: null,
                                                      child: Row(
                                                        mainAxisSize: .min,
                                                        children: [
                                                          Icon(
                                                            info.$2,
                                                            size: 12.0,
                                                            color: mainTextTheme.displaySmall?.color,
                                                          ),
                                                          const SizedBox(width: 4.0),
                                                          Text(
                                                            info.$1,
                                                            style: mainTextTheme.displaySmall?.copyWith(
                                                              fontWeight: FontWeight.w500,
                                                              fontSize: 12.0,
                                                            ),
                                                            softWrap: false,
                                                          ),
                                                        ],
                                                      ),
                                                    ),
                                                  ),
                                                ),
                                              )
                                              .addSeparators(separator: const SizedBox(width: 4.0), skipFirst: 1)
                                              .toFixedList(),
                                    ),
                                  ),
                                ),
                              ],
                            );
                          },
                        ),
                        children: epansionTileChildren ?? const <Widget>[],
                      ),
                    ),
                  ),

                  // --END-- title & subtitle

                  // --START-- buttons
                  SliverToBoxAdapter(
                    key: Key("${currentId}_buttons"),
                    child: ShimmerWrapper(
                      shimmerDurationMS: 550,
                      shimmerDelayMS: 250,
                      shimmerEnabled: shimmerEnabled,
                      child: SizedBox(
                        width: maxWidth,
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Flexible(
                              flex: 1,
                              fit: FlexFit.tight,
                              child: const SizedBox(),
                            ),
                            Flexible(
                              flex: 4,
                              fit: FlexFit.tight, // -- imp
                              child: NamidaLoadingControllerProvider(
                                builder: (likeLoadingController) => ObxO(
                                  rx: _videoLikeManager.currentVideoLikeStatus,
                                  builder: (context, currentLikeStatus) {
                                    final isUserLiked = currentLikeStatus == LikeStatus.liked;
                                    final videoLikeCount = (isUserLiked ? 1 : 0) + (videoInfo?.engagement?.likesCount ?? 0);
                                    return ObxO(
                                      rx: _isTitleExpanded,
                                      builder: (context, isTitleExpanded) => SmallYTActionButton(
                                        title: shimmerEnabled
                                            ? null
                                            : videoLikeCount < 1
                                            ? lang.like
                                            : videoLikeCount.formatDecimalShort(isTitleExpanded),
                                        icon: Broken.like_1,
                                        smallIconWidget: NamidaLoadingSwitcher(
                                          size: 24.0,
                                          controller: likeLoadingController,
                                          builder: (likeLoadingController) => NamidaRawLikeButton(
                                            isLiked: isUserLiked,
                                            likedIcon: Broken.like_filled,
                                            normalIcon: Broken.like_1,
                                            disabledColor: mainTheme.iconTheme.color,
                                            size: 24.0,
                                            removeConfirmationAction: null, // manually managed
                                            onTap: (isLiked) => _onLikeTap(
                                              isLiked: isLiked,
                                              loadingController: likeLoadingController,
                                            ),
                                          ),
                                        ),
                                        onPressed: () => _onLikeTap(
                                          isLiked: isUserLiked,
                                          loadingController: likeLoadingController,
                                        ),
                                      ),
                                    );
                                  },
                                ),
                              ),
                            ),
                            const SizedBox(width: 2.0),
                            Flexible(
                              flex: 4,
                              fit: FlexFit.tight,
                              child: NamidaLoadingControllerProvider(
                                builder: (dislikeLoadingController) => ObxO(
                                  rx: YoutubeInfoController.current.currentDislikeCount,
                                  builder: (context, videoDislikeCount) => ObxO(
                                    rx: _videoLikeManager.currentVideoLikeStatus,
                                    builder: (context, currentLikeStatus) {
                                      final isUserDisLiked = currentLikeStatus == LikeStatus.disliked;
                                      return ObxO(
                                        rx: _isTitleExpanded,
                                        builder: (context, isTitleExpanded) => SmallYTActionButton(
                                          title: (videoDislikeCount ?? 0) < 1 ? lang.dislike : videoDislikeCount?.formatDecimalShort(isTitleExpanded) ?? '?',
                                          icon: Broken.dislike,
                                          smallIconWidget: NamidaLoadingSwitcher(
                                            size: 24.0,
                                            controller: dislikeLoadingController,
                                            builder: (dislikeLoadingController) => NamidaRawLikeButton(
                                              isLiked: isUserDisLiked,
                                              likedIcon: Broken.dislike_filled,
                                              normalIcon: Broken.dislike,
                                              disabledColor: mainTheme.iconTheme.color,
                                              size: 24.0,
                                              removeConfirmationAction: null, // manually managed
                                              onTap: (isDisLiked) => _onDislikeTap(
                                                isDisLiked: isDisLiked,
                                                loadingController: dislikeLoadingController,
                                              ),
                                            ),
                                          ),
                                          onPressed: () => _onDislikeTap(
                                            isDisLiked: isUserDisLiked,
                                            loadingController: dislikeLoadingController,
                                          ),
                                        ),
                                      );
                                    },
                                  ),
                                ),
                              ),
                            ),
                            const SizedBox(width: 2.0),
                            Flexible(
                              flex: 4,
                              fit: FlexFit.tight,
                              child: SmallYTActionButton(
                                title: lang.share,
                                icon: Broken.share,
                                onPressed: () {
                                  final url = videoInfo?.buildUrl() ?? YTUrlUtils.buildVideoUrl(currentId);
                                  NamidaUtils.shareUri(url);
                                },
                              ),
                            ),
                            const SizedBox(width: 2.0),
                            Flexible(
                              flex: 4,
                              fit: FlexFit.tight,
                              child: SmallYTActionButton(
                                title: lang.refresh,
                                icon: Broken.refresh,
                                onPressed: () async {
                                  await YoutubeInfoController.current.updateVideoPage(
                                    currentId,
                                    requestPage: true,
                                    requestComments: true,
                                  );
                                  if (settings.youtube.sponsorBlockSettings.value.enabled) {
                                    await SponsorBlockController.inst.updateSegments(
                                      currentId,
                                      forceRequest: true,
                                    );
                                  }
                                },
                              ),
                            ),
                            const SizedBox(width: 2.0),
                            Flexible(
                              flex: 4,
                              fit: FlexFit.tight,
                              child: Obx(
                                (context) {
                                  final audioProgress = YoutubeController.inst.downloadsAudioProgressMap[currentIdTask]?.values.firstOrNull;
                                  final audioPercText = audioProgress?.percentageText(prefix: lang.audio);
                                  final videoProgress = YoutubeController.inst.downloadsVideoProgressMap[currentIdTask]?.values.firstOrNull;
                                  final videoPercText = videoProgress?.percentageText(prefix: lang.video);

                                  final isDownloading = YoutubeController.inst.isDownloading[currentIdTask]?.values.any((element) => element) == true;

                                  final wasDownloading = videoProgress != null || audioProgress != null;
                                  final icon = (wasDownloading && !isDownloading)
                                      ? Broken.play_circle
                                      : wasDownloading
                                      ? Broken.pause_circle
                                      : downloadedFileExists
                                      ? Broken.tick_circle
                                      : Broken.import;
                                  return SmallYTActionButton(
                                    titleWidget: videoPercText == null && audioPercText == null && isDownloading ? const LoadingIndicator() : null,
                                    title: videoPercText ?? audioPercText ?? lang.download,
                                    icon: icon,
                                    onLongPress: () async =>
                                        await showDownloadVideoBottomSheet(videoId: currentId, originalIndex: null, totalLength: null, playlistId: null, streamInfoItem: null),
                                    onPressed: () async {
                                      if (isDownloading) {
                                        YoutubeController.inst.pauseDownloadTask(
                                          itemsConfig: [],
                                          videosIds: [currentIdTask],
                                          groupName: const DownloadTaskGroupName.defaulty(),
                                        );
                                      } else if (wasDownloading) {
                                        YoutubeController.inst.resumeDownloadTaskForIDs(
                                          videosIds: [currentIdTask],
                                          groupName: const DownloadTaskGroupName.defaulty(),
                                        );
                                      } else {
                                        await showDownloadVideoBottomSheet(videoId: currentId, originalIndex: null, totalLength: null, playlistId: null, streamInfoItem: null);
                                      }
                                    },
                                  );
                                },
                              ),
                            ),
                            const SizedBox(width: 2.0),
                            Flexible(
                              flex: 4,
                              fit: FlexFit.tight,
                              child: SmallYTActionButton(
                                title: lang.save,
                                icon: Broken.music_playlist,
                                onPressed: () => showAddToPlaylistSheet(
                                  ids: [currentId],
                                  idsNamesLookup: {
                                    currentId: videoTitle ?? '',
                                  },
                                ),
                              ),
                            ),
                            Flexible(
                              flex: 1,
                              fit: FlexFit.tight,
                              child: const SizedBox(),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                  const SliverPadding(padding: EdgeInsets.only(top: 24.0)),
                  // --END- buttons

                  // --START- channel
                  SliverToBoxAdapter(
                    key: Key("${currentId}_channel"),
                    child: ShimmerWrapper(
                      shimmerDurationMS: 550,
                      shimmerDelayMS: 250,
                      shimmerEnabled: shimmerEnabled && (channelName == null || channelThumbnail == null || channelSubs == null),
                      child: Material(
                        type: MaterialType.transparency,
                        child: InkWell(
                          onTap: () async {
                            final channelInfo = channel ?? YoutubeInfoController.current.currentVideoPage.value?.channelInfo;
                            String? chid = channel?.id ?? YoutubeInfoController.current.currentVideoPage.value?.channelInfo?.id;
                            if (chid == null || chid.isEmpty) {
                              chid = await YoutubeInfoController.utils.getVideoChannelID(currentId);
                            }
                            if (chid != null) {
                              YTChannelSubpage(channelID: chid, channel: channelInfo).navigate();
                            }
                          },
                          child: LayoutWidthProvider(
                            builder: (context, maxWidth) {
                              final partThumbMaxWidth = maxWidth * 0.15;
                              final partTextMaxWidth = maxWidth * 0.62 - (partThumbMaxWidth / 2);
                              final partButtonMaxWidth = maxWidth * 0.38 - (partThumbMaxWidth / 2);

                              final channelThumbSize = 42.0.withMaximum(partThumbMaxWidth);
                              return Row(
                                children: [
                                  const SizedBox(width: 16.0),
                                  NamidaDummyContainer(
                                    width: channelThumbSize,
                                    height: channelThumbSize,
                                    borderRadius: 100.0,
                                    shimmerEnabled: channelThumbnail == null && (channelID == null || channelID.isEmpty),
                                    child: YoutubeThumbnail(
                                      type: ThumbnailType.channel,
                                      key: Key("${channelThumbnail}_$channelID"),
                                      isImportantInCache: true,
                                      customUrl: channelThumbnail,
                                      width: channelThumbSize,
                                      height: channelThumbSize,
                                      isCircle: true,
                                    ),
                                  ),
                                  const SizedBox(width: 8.0),
                                  Expanded(
                                    child: ConstrainedBox(
                                      constraints: BoxConstraints(maxWidth: partTextMaxWidth),
                                      child: FittedBox(
                                        alignment: Alignment.centerLeft,
                                        fit: BoxFit.scaleDown,
                                        child: Column(
                                          mainAxisSize: MainAxisSize.min,
                                          mainAxisAlignment: MainAxisAlignment.center,
                                          crossAxisAlignment: CrossAxisAlignment.start,
                                          children: [
                                            Row(
                                              mainAxisSize: MainAxisSize.min,
                                              children: [
                                                NamidaDummyContainer(
                                                  width: 114.0,
                                                  height: 12.0,
                                                  borderRadius: 4.0,
                                                  shimmerEnabled: channelName == null,
                                                  child: Text(
                                                    channelName ?? '',
                                                    style: mainTextTheme.displayMedium?.copyWith(
                                                      fontSize: 13.5,
                                                    ),
                                                    maxLines: 1,
                                                    overflow: TextOverflow.ellipsis,
                                                    textAlign: TextAlign.start,
                                                  ),
                                                ),
                                                if (channelIsVerified) ...[
                                                  const SizedBox(width: 4.0),
                                                  const Icon(
                                                    Broken.shield_tick,
                                                    size: 12.0,
                                                  ),
                                                ],
                                              ],
                                            ),
                                            const SizedBox(height: 2.0),
                                            NamidaDummyContainer(
                                              width: 92.0,
                                              height: 10.0,
                                              borderRadius: 4.0,
                                              shimmerEnabled: channelSubs == null,
                                              child: ObxO(
                                                rx: _isTitleExpanded,
                                                builder: (context, isTitleExpanded) => Text(
                                                  channelSubs == null ? '? ${lang.subscribers}' : channelSubs.displaySubscribersKeywordShort,
                                                  style: mainTextTheme.displaySmall?.copyWith(
                                                    fontSize: 12.0,
                                                  ),
                                                  maxLines: 1,
                                                  overflow: TextOverflow.ellipsis,
                                                ),
                                              ),
                                            ),
                                          ],
                                        ),
                                      ),
                                    ),
                                  ),
                                  const SizedBox(width: 12.0),
                                  ConstrainedBox(
                                    constraints: BoxConstraints(maxWidth: partButtonMaxWidth),
                                    child: FittedBox(
                                      alignment: Alignment.centerRight,
                                      fit: BoxFit.scaleDown,
                                      child: YTSubscribeButton(
                                        channelID: channelID,
                                        mainChannelInfo: YoutubeInfoController.current.currentChannelPage,
                                      ),
                                    ),
                                  ),
                                  const SizedBox(width: 12.0),
                                  const SizedBox(width: 6.0),
                                ],
                              );
                            },
                          ),
                        ),
                      ),
                    ),
                  ),
                  const SliverPadding(padding: EdgeInsets.only(top: 4.0)),
                  // --END-- channel

                  // --SRART-- top comments
                  const SliverPadding(padding: EdgeInsets.only(top: 4.0)),

                  if (ytTopComments)
                    SliverToBoxAdapter(
                      child: Padding(
                        padding: const EdgeInsets.only(top: 8.0),
                        child: ObxO(
                          rx: YoutubeInfoController.current.currentComments,
                          builder: (context, comments) => ShimmerWrapper(
                            shimmerEnabled: shimmerEnabled && (comments == null || comments.isEmpty),
                            child: NamidaInkWell(
                              key: Key("${currentId}_top_comments_highlight"),
                              bgColor: Color.alphaBlend(mainTheme.scaffoldBackgroundColor.withOpacityExt(0.4), mainTheme.cardColor),
                              margin: const EdgeInsets.symmetric(horizontal: 18.0),
                              padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
                              onTap: () {
                                NamidaNavigator.inst.isInYTCommentsSubpage = true;
                                NamidaNavigator.inst.ytMiniplayerCommentsPageKey.currentState?.pushPage(
                                  const YTMiniplayerCommentsSubpage(),
                                  params: const NamPackPushPageParams(
                                    maintainState: true, // vip to maintain scroll offset
                                  ),
                                );
                              },
                              child: Column(
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  Row(
                                    mainAxisAlignment: MainAxisAlignment.start,
                                    children: [
                                      const Icon(
                                        Broken.document,
                                        size: 16.0,
                                      ),
                                      const SizedBox(width: 8.0),
                                      Expanded(
                                        child: Text(
                                          [
                                            lang.comments,
                                            if (comments?.commentsCount != null) comments!.commentsCount!.formatDecimalShort(),
                                          ].join(' • '),
                                          style: mainTextTheme.displaySmall,
                                          textAlign: TextAlign.start,
                                        ),
                                      ),
                                      ObxO(
                                        rx: YoutubeInfoController.current.isCurrentCommentsFromCache,
                                        builder: (context, commFromCache) {
                                          commFromCache ??= false;
                                          return NamidaIconButton(
                                            horizontalPadding: 0.0,
                                            tooltip: commFromCache ? () => lang.cache : null,
                                            icon: Broken.refresh,
                                            iconSize: 22.0,
                                            onPressed: () async => await YoutubeInfoController.current.updateCurrentComments(
                                              currentId,
                                              newSortType: YoutubeMiniplayerUiController.inst.currentCommentSort.value,
                                              initial: true,
                                            ),
                                            child: commFromCache
                                                ? StackedIcon(
                                                    baseIcon: Broken.refresh,
                                                    secondaryIcon: Broken.global,
                                                    iconSize: 20.0,
                                                    secondaryIconSize: 12.0,
                                                    baseIconColor: defaultIconColor,
                                                    secondaryIconColor: defaultIconColor,
                                                  )
                                                : Icon(
                                                    Broken.refresh,
                                                    color: defaultIconColor,
                                                    size: 20.0,
                                                  ),
                                          );
                                        },
                                      ),
                                    ],
                                  ),
                                  const NamidaContainerDivider(margin: EdgeInsets.symmetric(vertical: 4.0)),
                                  ObxO(
                                    rx: YoutubeInfoController.current.isLoadingInitialComments,
                                    builder: (context, loading) => ShimmerWrapper(
                                      shimmerEnabled: loading,
                                      child: YTCommentCardCompact(comment: loading ? null : comments?.items.firstOrNull),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),

                  const SliverPadding(padding: EdgeInsets.only(top: 8.0)),

                  ObxO(
                    rx: YoutubeInfoController.current.currentRelatedVideos,
                    builder: (context, currentRelatedVideos) =>
                        currentRelatedVideos ==
                            null // we display dummy boxes but shimmer would be disabled
                        ? SliverToBoxAdapter(
                            key: Key("${currentId}_feed_shimmer"),
                            child: ShimmerWrapper(
                              transparent: false,
                              shimmerEnabled: shimmerEnabled,
                              child: SuperSmoothListView.builder(
                                padding: EdgeInsets.zero,
                                key: Key("${currentId}_feedlist_shimmer"),
                                physics: const NeverScrollableScrollPhysics(),
                                itemCount: 15,
                                shrinkWrap: true,
                                itemBuilder: (_, _) => dummyVideoCard,
                              ),
                            ),
                          )
                        : ObxO(
                            rx: settings.youtube.ytVisibleShorts,
                            builder: (context, visibleShorts) {
                              final isShortsVisible = visibleShorts[YTVisibleShortPlaces.relatedVideos] ?? true;
                              return ObxO(
                                rx: settings.youtube.ytVisibleMixes,
                                builder: (context, visibleMixes) {
                                  final isMixesVisible = visibleMixes[YTVisibleMixesPlaces.relatedVideos] ?? true;
                                  return SliverVariedExtentList.builder(
                                    key: Key("${currentId}_feedlist"),
                                    itemExtentBuilder: (index, dimensions) {
                                      if (isShortsVisible) {
                                        if (currentRelatedVideos.shortsSection.relatedItemsShortsData[index] != null) {
                                          return 64.0 * 3;
                                        } else if (currentRelatedVideos.shortsSection.shortsIndicesLookup[index] == true) {
                                          return 0;
                                        }
                                      }

                                      final item = currentRelatedVideos.items[index];
                                      if (!isShortsVisible && item.isShortContent) return 0;
                                      if (!isMixesVisible && item.isMixPlaylist) return 0;
                                      return relatedThumbnailItemExtent;
                                    },
                                    itemCount: currentRelatedVideos.items.length,
                                    itemBuilder: (context, index) {
                                      final shortsData = currentRelatedVideos.shortsSection;

                                      final shortSection = shortsData.relatedItemsShortsData[index];
                                      if (shortSection != null) {
                                        if (isShortsVisible == false) return const SizedBox();
                                        const height = 64.0 * 3;
                                        const width = height * (9 / 16 * 1.2);
                                        const hPadding = 4.0;
                                        return SizedBox(
                                          height: height,
                                          child: SuperSmoothListView.builder(
                                            padding: const EdgeInsets.symmetric(vertical: 24.0 / 6, horizontal: 4.0),
                                            scrollDirection: Axis.horizontal,
                                            itemExtent: width + hPadding * 2,
                                            itemCount: shortSection.length,
                                            itemBuilder: (context, index) {
                                              final shortIndex = shortSection[index];
                                              final short = shortsData.getAsShort(currentRelatedVideos.items[shortIndex]);
                                              return Padding(
                                                padding: const EdgeInsets.symmetric(horizontal: hPadding),
                                                child: YoutubeShortVideoTallCard(
                                                  queueSource: QueueSourceYoutubeID.ytRelatedVideos,
                                                  index: index,
                                                  short: short,
                                                  thumbnailWidth: width,
                                                  thumbnailHeight: height,
                                                ),
                                              );
                                            },
                                          ),
                                        );
                                      }
                                      if (shortsData.shortsIndicesLookup[index] == true) {
                                        return const SizedBox.shrink();
                                      }

                                      final item = currentRelatedVideos.items[index];
                                      if (!isShortsVisible && item.isShortContent) return const SizedBox.shrink();
                                      if (!isMixesVisible && item.isMixPlaylist) return const SizedBox.shrink();

                                      return switch (item.runtimeType) {
                                        const (StreamInfoItem) => YoutubeVideoCard(
                                          properties: properties,
                                          key: Key((item as StreamInfoItem).id),
                                          thumbnailHeight: relatedThumbnailHeight,
                                          thumbnailWidth: relatedThumbnailWidth,
                                          isImageImportantInCache: false,
                                          video: item,
                                          playlistID: null,
                                        ),
                                        const (StreamInfoItemShort) => YoutubeShortVideoCard(
                                          queueSource: QueueSourceYoutubeID.ytRelatedVideos,
                                          key: Key("${(item as StreamInfoItemShort?)?.id}"),
                                          thumbnailHeight: relatedThumbnailHeight,
                                          thumbnailWidth: relatedThumbnailWidth,
                                          short: item as StreamInfoItemShort,
                                          playlistID: null,
                                        ),
                                        const (PlaylistInfoItem) => YoutubePlaylistCard(
                                          queueSource: QueueSourceYoutubeID.ytRelatedVideos,
                                          key: Key((item as PlaylistInfoItem).id),
                                          thumbnailHeight: relatedThumbnailHeight,
                                          thumbnailWidth: relatedThumbnailWidth,
                                          playlist: item,
                                          subtitle: item.subtitle,
                                          playOnTap: true,
                                          firstVideoID: item.initialVideos.firstOrNull?.id,
                                          isMixPlaylist: item.isMix,
                                        ),
                                        _ => dummyVideoCard,
                                      };
                                    },
                                  );
                                },
                              );
                            },
                          ),
                  ),

                  const SliverPadding(padding: EdgeInsets.only(top: 12.0)),

                  // --START-- Comments
                  if (!ytTopComments)
                    SliverToBoxAdapter(
                      key: Key("${currentId}_comments_header"),
                      child: const Padding(
                        padding: EdgeInsets.symmetric(vertical: 8.0),
                        child: YoutubeCommentsHeader(
                          displayBackButton: false,
                        ),
                      ),
                    ),
                  if (!ytTopComments)
                    ObxO(
                      rx: YoutubeInfoController.current.isLoadingInitialComments,
                      builder: (context, loadingInitial) => loadingInitial
                          ? SliverToBoxAdapter(
                              key: Key("${currentId}_comments_shimmer"),
                              child: ShimmerWrapper(
                                transparent: false,
                                shimmerEnabled: true,
                                child: SuperSmoothListView.builder(
                                  padding: EdgeInsets.zero,
                                  // key: Key(currentId),
                                  physics: const NeverScrollableScrollPhysics(),
                                  itemCount: 10,
                                  shrinkWrap: true,
                                  itemBuilder: (context, index) {
                                    return const YTCommentCard(
                                      margin: EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0),
                                      comment: null,
                                      mainList: null,
                                      videoId: null,
                                    );
                                  },
                                ),
                              ),
                            )
                          : ObxO(
                              rx: YoutubeInfoController.current.currentComments,
                              builder: (context, comments) => comments == null
                                  ? const SliverToBoxAdapter()
                                  : SuperSliverList.builder(
                                      key: Key("${currentId}_comments"),
                                      itemCount: comments.length,
                                      itemBuilder: (context, i) {
                                        final comment = comments[i];
                                        return YTCommentCard(
                                          key: Key("${comment == null}_${comment?.commentId}"),
                                          margin: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0),
                                          comment: comment,
                                          mainList: () => comments,
                                          videoId: currentId,
                                        );
                                      },
                                    ),
                            ),
                    ),
                  if (!ytTopComments)
                    ObxO(
                      rx: YoutubeInfoController.current.isLoadingMoreComments,
                      builder: (context, loadingMoreComments) => loadingMoreComments
                          ? const SliverToBoxAdapter(
                              child: Padding(
                                padding: EdgeInsets.all(12.0),
                                child: Center(
                                  child: LoadingIndicator(),
                                ),
                              ),
                            )
                          : const SliverToBoxAdapter(),
                    ),

                  const SliverPadding(padding: EdgeInsets.only(bottom: kYTQueueSheetMinHeight)),
                ],
              ),
              ObxO(
                rx: _shouldShowGlowUnderVideo,
                builder: (context, shouldShowGlowUnderVideo) {
                  const containerHeight = 12.0;
                  return CustomAnimatedSwitcher(
                    duration: const Duration(milliseconds: 300),
                    child: shouldShowGlowUnderVideo
                        ? Stack(
                            key: const Key('actual_glow'),
                            children: [
                              Container(
                                height: containerHeight,
                                color: mainTheme.scaffoldBackgroundColor,
                              ),
                              Container(
                                height: containerHeight,
                                transform: Matrix4.translationValues(0, containerHeight / 2, 0),
                                decoration: BoxDecoration(
                                  boxShadow: [
                                    BoxShadow(
                                      color: mainTheme.scaffoldBackgroundColor,
                                      spreadRadius: containerHeight * 0.25,
                                      offset: const Offset(0, 0),
                                      blurRadius: 8.0,
                                    ),
                                  ],
                                ),
                              ),
                            ],
                          )
                        : const SizedBox(key: Key('empty_glow')),
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class _StreamSegmentsRow extends StatefulWidget {
  final String videoId;
  final List<StreamSegment> segments;
  const _StreamSegmentsRow({required this.segments, required this.videoId});

  @override
  State<_StreamSegmentsRow> createState() => _StreamSegmentsRowState();
}

class _StreamSegmentsRowState extends State<_StreamSegmentsRow> {
  StreamSegment? _currentSegment;
  late final _controller = NamidaScrollController.create();

  final _segmentKeys = <StreamSegment, GlobalKey>{};

  @override
  void initState() {
    for (final s in widget.segments) {
      _segmentKeys[s] = GlobalKey();
    }
    _onPlayerPositionChange();
    Player.inst.nowPlayingPosition.addListener(_onPlayerPositionChange);
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    Player.inst.nowPlayingPosition.removeListener(_onPlayerPositionChange);
    super.dispose();
  }

  void _onPlayerPositionChange() {
    final currentPositionMS = Player.inst.nowPlayingPosition.value;
    final currentSegment = widget.segments.findByMillisecond(currentPositionMS);

    if (_currentSegment != currentSegment) {
      if (mounted) {
        setState(() => _currentSegment = currentSegment);
        if (currentSegment != null) {
          WidgetsBinding.instance.addPostFrameCallback(
            (_) {
              final context = _segmentKeys[currentSegment]?.currentContext;
              if (context != null) {
                _controller.position.ensureVisible(
                  context.findRenderObject()!,
                  duration: const Duration(milliseconds: 200),
                  curve: Curves.fastEaseInToSlowEaseOut,
                  alignment: 0.4,
                );
              }
            },
          );
        }
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final thumbWidth = (context.width * 0.2).withMaximum(128.0);
    const thumbHorizontalPadding = 1.0;
    final currentSegment = _currentSegment;
    return SmoothSingleChildScrollView(
      controller: _controller,
      padding: EdgeInsets.symmetric(horizontal: 8.0),
      scrollDirection: Axis.horizontal,
      child: Row(
        children: widget.segments.map(
          (e) {
            final url = e.thumbnail?.url;
            final isCurrentSegment = e == currentSegment;
            return NamidaInkWell(
              key: _segmentKeys[e],
              animationDurationMS: 200,
              borderRadius: 6.0,
              width: thumbWidth + thumbHorizontalPadding * 2,
              bgColor: isCurrentSegment ? context.theme.colorScheme.secondaryContainer : context.theme.cardColor.withOpacityExt(0.4),
              onTap: () {
                final startSeconds = e.startSeconds;
                if (startSeconds != null) {
                  Player.inst.seek(Duration(milliseconds: (startSeconds * 1000) + 1));
                }
              },
              margin: const EdgeInsets.symmetric(horizontal: 2.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  Padding(
                    padding: const EdgeInsets.all(thumbHorizontalPadding),
                    child: YoutubeThumbnail(
                      type: ThumbnailType.video,
                      key: Key('${widget.videoId}_$url'),
                      borderRadius: 6.0,
                      isImportantInCache: false,
                      width: thumbWidth,
                      height: thumbWidth * 9 / 16,
                      videoId: widget.videoId,
                      preferLowerRes: true,
                      customUrl: url,
                      smallBoxText: e.startSeconds?.secondsLabel,
                      smallBoxIcon: isCurrentSegment ? Broken.play : null,
                      forceSquared: true,
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 1.0, left: 4.0, bottom: 3.0),
                    child: Text(
                      e.title,
                      style: context.textTheme.displaySmall?.copyWith(
                        fontSize: 11.0,
                        fontWeight: FontWeight.w500,
                      ),
                      softWrap: false,
                      overflow: TextOverflow.fade,
                    ),
                  ),
                ],
              ),
            );
          },
        ).toFixedList(),
      ),
    );
  }
}
