import 'dart:math';

import 'package:audio_service/audio_service.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:text_scroll/text_scroll.dart';

import '../../cache/image_cache.dart';
import '../../models/support.dart';
import '../../services/audio_service.dart';
import '../../state/audio.dart';
import '../../state/theme.dart';
import '../context_menus.dart';
import '../gradient.dart';
import '../images.dart';
import '../now_playing_bar.dart';

class NowPlayingPage extends HookConsumerWidget {
  const NowPlayingPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final colors = ref.watch(mediaItemThemeProvider).valueOrNull;
    final itemData = ref.watch(mediaItemDataProvider);

    final theme = Theme.of(context);

    final scaffold = AnnotatedRegion<SystemUiOverlayStyle>(
      value: SystemUiOverlayStyle.light.copyWith(
        systemNavigationBarColor: colors?.gradientLow,
        statusBarColor: Colors.transparent,
      ),
      child: Scaffold(
        appBar: AppBar(
          title: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                itemData?.contextType.value ?? '',
                style: theme.textTheme.labelMedium,
                maxLines: 1,
                softWrap: false,
                overflow: TextOverflow.fade,
              ),
              // Text(
              //   itemData?.contextTitle ?? '',
              //   style: theme.textTheme.titleMedium,
              //   maxLines: 1,
              //   softWrap: false,
              //   overflow: TextOverflow.fade,
              // ),
            ],
          ),
        ),
        body: Stack(
          children: [
            const MediaItemGradient(),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
              child: Column(
                children: const [
                  Expanded(
                    child: Padding(
                      padding: EdgeInsets.symmetric(horizontal: 16),
                      child: _Art(),
                    ),
                  ),
                  SizedBox(height: 24),
                  Padding(
                    padding: EdgeInsets.symmetric(horizontal: 16),
                    child: _TrackInfo(),
                  ),
                  SizedBox(height: 8),
                  _Progress(),
                  Padding(
                    padding: EdgeInsets.symmetric(horizontal: 16),
                    child: _Controls(),
                  ),
                  SizedBox(height: 64),
                ],
              ),
            ),
          ],
        ),
      ),
    );

    if (colors != null) {
      return Theme(data: colors.theme, child: scaffold);
    } else {
      return scaffold;
    }
  }
}

class _Art extends HookConsumerWidget {
  const _Art();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final itemData = ref.watch(mediaItemDataProvider);
    final imageCache = ref.watch(imageCacheProvider);

    UriCacheInfo? cacheInfo;
    if (itemData?.artCache != null) {
      cacheInfo = UriCacheInfo(
        uri: itemData!.artCache!.fullArtUri,
        cacheKey: itemData.artCache!.fullArtCacheKey,
        cacheManager: imageCache,
      );
    }

    return AnimatedSwitcher(
      duration: const Duration(milliseconds: 150),
      child: CardClip(
        key: ValueKey(cacheInfo?.cacheKey ?? 'default'),
        child: cacheInfo != null
            ? CardClip(
                square: false,
                child: UriCacheInfoImage(
                  // height: 300,
                  fit: BoxFit.contain,
                  placeholderStyle: PlaceholderStyle.spinner,
                  cache: cacheInfo,
                ),
              )
            : const PlaceholderImage(thumbnail: false),
      ),
    );
  }
}

class _TrackInfo extends HookConsumerWidget {
  const _TrackInfo();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final item = ref.watch(mediaItemProvider).valueOrNull;
    final theme = Theme.of(context);

    return Row(
      children: [
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              ScrollableText(
                item?.title ?? '',
                style: theme.textTheme.headlineSmall,
                speed: 50,
              ),
              Text(
                item?.artist ?? '',
                style: theme.textTheme.titleMedium!,
                maxLines: 1,
                softWrap: false,
                overflow: TextOverflow.fade,
              ),
            ],
          ),
        ),
        IconButton(
          icon: const Icon(
            Icons.star_outline_rounded,
            size: 36,
          ),
          onPressed: () {},
        ),
      ],
    );
  }
}

class ScrollableText extends StatelessWidget {
  final String text;
  final TextStyle? style;
  final double speed;

  const ScrollableText(
    this.text, {
    super.key,
    this.style,
    this.speed = 35,
  });

  @override
  Widget build(BuildContext context) {
    final defaultStyle = DefaultTextStyle.of(context);

    return AutoSizeText(
      text,
      presetFontSizes: style != null && style?.fontSize != null
          ? [style!.fontSize!]
          : [defaultStyle.style.fontSize ?? 12],
      style: style,
      maxLines: 1,
      // softWrap: false,
      overflowReplacement: TextScroll(
        '$text     ',
        style: style,
        delayBefore: const Duration(seconds: 3),
        pauseBetween: const Duration(seconds: 4),
        mode: TextScrollMode.endless,
        velocity: Velocity(pixelsPerSecond: Offset(speed, 0)),
      ),
    );
  }
}

class _Progress extends HookConsumerWidget {
  const _Progress();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final colors = ref.watch(mediaItemThemeProvider).valueOrNull;
    final position = ref.watch(positionProvider);
    final duration = ref.watch(durationProvider);
    final audio = ref.watch(audioControlProvider);

    final changeValue = useState(position.toDouble());
    final changing = useState(false);

    return Column(
      children: [
        Slider(
          value: changing.value ? changeValue.value : position.toDouble(),
          min: 0,
          max: max(duration.toDouble(), position.toDouble()),
          thumbColor: colors?.theme.colorScheme.onBackground,
          activeColor: colors?.theme.colorScheme.onBackground,
          inactiveColor: colors?.theme.colorScheme.surface,
          onChanged: (value) {
            changeValue.value = value;
          },
          onChangeStart: (value) {
            changing.value = true;
          },
          onChangeEnd: (value) {
            changing.value = false;
            audio.seek(Duration(seconds: value.toInt()));
          },
        ),
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 24),
          child: DefaultTextStyle(
            style: Theme.of(context).textTheme.titleMedium!,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text(Duration(
                        seconds: changing.value
                            ? changeValue.value.toInt()
                            : position)
                    .toString()
                    .substring(2, 7)),
                Text(Duration(seconds: duration).toString().substring(2, 7)),
              ],
            ),
          ),
        )
      ],
    );
  }
}

class RepeatButton extends HookConsumerWidget {
  final double size;

  const RepeatButton({
    super.key,
    required this.size,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final audio = ref.watch(audioControlProvider);
    final repeat = ref.watch(repeatModeProvider);

    IconData icon;
    void Function() action;

    switch (repeat) {
      case AudioServiceRepeatMode.all:
      case AudioServiceRepeatMode.group:
        icon = Icons.repeat_on_rounded;
        action = () => audio.setRepeatMode(AudioServiceRepeatMode.one);
        break;
      case AudioServiceRepeatMode.one:
        icon = Icons.repeat_one_on_rounded;
        action = () => audio.setRepeatMode(AudioServiceRepeatMode.none);
        break;
      default:
        icon = Icons.repeat_rounded;
        action = () => audio.setRepeatMode(AudioServiceRepeatMode.all);
        break;
    }

    return IconButton(
      icon: Icon(icon),
      padding: EdgeInsets.zero,
      iconSize: 30,
      onPressed: action,
    );
  }
}

class ShuffleButton extends HookConsumerWidget {
  final double size;

  const ShuffleButton({
    super.key,
    required this.size,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final audio = ref.watch(audioControlProvider);
    final shuffle = ref.watch(shuffleModeProvider);
    final queueMode = ref.watch(queueModeProvider).valueOrNull;

    IconData icon;
    void Function() action;

    switch (shuffle) {
      case AudioServiceShuffleMode.all:
      case AudioServiceShuffleMode.group:
        icon = Icons.shuffle_on_rounded;
        action = () => audio.setShuffleMode(AudioServiceShuffleMode.none);
        break;
      default:
        icon = Icons.shuffle_rounded;
        action = () => audio.setShuffleMode(AudioServiceShuffleMode.all);
        break;
    }

    return IconButton(
      icon: Icon(queueMode == QueueMode.radio ? Icons.radio_rounded : icon),
      padding: EdgeInsets.zero,
      iconSize: 30,
      onPressed: queueMode == QueueMode.radio ? null : action,
    );
  }
}

class _Controls extends HookConsumerWidget {
  const _Controls();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final base = ref.watch(baseThemeProvider);
    final audio = ref.watch(audioControlProvider);

    return IconTheme(
      data: IconThemeData(color: base.theme.colorScheme.onBackground),
      child: Column(
        children: [
          SizedBox(
            height: 100,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                const RepeatButton(size: 30),
                IconButton(
                  icon: const Icon(Icons.skip_previous_rounded),
                  padding: EdgeInsets.zero,
                  iconSize: 60,
                  onPressed: () => audio.skipToPrevious(),
                ),
                const PlayPauseButton(size: 90),
                IconButton(
                  icon: const Icon(Icons.skip_next_rounded),
                  padding: EdgeInsets.zero,
                  iconSize: 60,
                  onPressed: () => audio.skipToNext(),
                ),
                const ShuffleButton(size: 30),
              ],
            ),
          ),
          SizedBox(
            height: 40,
            child: Row(
              // crossAxisAlignment: CrossAxisAlignment.stretch,
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                IconButton(
                  icon: const Icon(Icons.queue_music_rounded),
                  padding: EdgeInsets.zero,
                  iconSize: 30,
                  onPressed: () {},
                ),
                const _MoreButton(),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _MoreButton extends HookConsumerWidget {
  const _MoreButton();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final song = ref.watch(mediaItemSongProvider).valueOrNull;

    return IconButton(
      icon: const Icon(Icons.more_horiz),
      padding: EdgeInsets.zero,
      iconSize: 30,
      onPressed: song != null
          ? () {
              showContextMenu(
                context: context,
                ref: ref,
                builder: (context) => BottomSheetMenu(
                  child: SongContextMenu(song: song),
                ),
              );
            }
          : null,
    );
  }
}
