// ignore_for_file: use_build_context_synchronously

import 'dart:async';

import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

import '../models/music.dart';
import '../services/cache_service.dart';
import '../state/theme.dart';
import 'app_router.dart';
import 'hooks/use_download_actions.dart';
import 'images.dart';

enum MenuSize {
  small,
  medium,
}

Future<T?> showContextMenu<T>({
  required BuildContext context,
  required WidgetRef ref,
  required WidgetBuilder builder,
}) {
  return showModalBottomSheet<T>(
    backgroundColor: ref.read(baseThemeProvider).theme.colorScheme.background,
    useRootNavigator: true,
    isScrollControlled: true,
    context: context,
    builder: builder,
  );
}

class BottomSheetMenu extends HookConsumerWidget {
  final Widget child;
  final MenuSize size;

  const BottomSheetMenu({
    super.key,
    required this.child,
    this.size = MenuSize.medium,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final theme = ref.watch(baseThemeProvider);
    final height = size == MenuSize.medium ? 0.4 : 0.25;

    return Theme(
      data: theme.theme,
      child: DraggableScrollableSheet(
        expand: false,
        initialChildSize: height,
        maxChildSize: height,
        minChildSize: height - 0.05,
        snap: true,
        snapSizes: [height - 0.05, height],
        builder: (context, scrollController) {
          return PrimaryScrollController(
            controller: scrollController,
            child: SizedBox(
              child: Padding(
                padding: const EdgeInsets.only(top: 8),
                child: child,
              ),
            ),
          );
        },
      ),
    );
  }
}

class AlbumContextMenu extends HookConsumerWidget {
  final Album album;

  const AlbumContextMenu({
    super.key,
    required this.album,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final downloadActions = useAlbumDownloadActions(
      context: context,
      ref: ref,
      album: album,
    );

    return ListView(
      children: [
        _AlbumHeader(album: album),
        const SizedBox(height: 8),
        const _Star(),
        if (album.artistId != null) _ViewArtist(id: album.artistId!),
        for (var action in downloadActions)
          _DownloadAction(key: ValueKey(action.type), downloadAction: action),
      ],
    );
  }
}

class SongContextMenu extends HookConsumerWidget {
  final Song song;

  const SongContextMenu({
    super.key,
    required this.song,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return ListView(
      children: [
        _SongHeader(song: song),
        const SizedBox(height: 8),
        const _Star(),
        if (song.artistId != null) _ViewArtist(id: song.artistId!),
        if (song.albumId != null) _ViewAlbum(id: song.albumId!),
        // const _DownloadAction(),
      ],
    );
  }
}

class ArtistContextMenu extends HookConsumerWidget {
  final Artist artist;

  const ArtistContextMenu({
    super.key,
    required this.artist,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return ListView(
      children: [
        _ArtistHeader(artist: artist),
        const SizedBox(height: 8),
        const _Star(),
        // const _Download(),
      ],
    );
  }
}

class PlaylistContextMenu extends HookConsumerWidget {
  final Playlist playlist;

  const PlaylistContextMenu({
    super.key,
    required this.playlist,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final downloadActions = usePlaylistDownloadActions(
      context: context,
      ref: ref,
      playlist: playlist,
    );

    return ListView(
      children: [
        _PlaylistHeader(playlist: playlist),
        const SizedBox(height: 8),
        for (var action in downloadActions)
          _DownloadAction(key: ValueKey(action.type), downloadAction: action),
      ],
    );
  }
}

class _AlbumHeader extends HookConsumerWidget {
  final Album album;

  const _AlbumHeader({
    required this.album,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final cache = ref.watch(cacheServiceProvider);

    return _Header(
      title: album.name,
      subtitle: album.albumArtist,
      image: CardClip(
        child: UriCacheInfoImage(
          cache: cache.albumArt(album, thumbnail: true),
        ),
      ),
    );
  }
}

class _SongHeader extends HookConsumerWidget {
  final Song song;

  const _SongHeader({
    required this.song,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return _Header(
      title: song.title,
      subtitle: song.artist,
      image: SongAlbumArt(song: song, square: false),
    );
  }
}

class _ArtistHeader extends HookConsumerWidget {
  final Artist artist;

  const _ArtistHeader({
    required this.artist,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final l = AppLocalizations.of(context);
    return _Header(
      title: artist.name,
      subtitle: l.resourcesAlbumCount(artist.albumCount),
      image: CircleClip(child: ArtistArtImage(artistId: artist.id)),
    );
  }
}

class _PlaylistHeader extends HookConsumerWidget {
  final Playlist playlist;

  const _PlaylistHeader({
    required this.playlist,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final cache = ref.watch(cacheServiceProvider);
    final l = AppLocalizations.of(context);
    return _Header(
      title: playlist.name,
      subtitle: l.resourcesSongCount(playlist.songCount),
      image: CardClip(
        child: UriCacheInfoImage(
          cache: cache.playlistArt(playlist, thumbnail: true),
        ),
      ),
    );
  }
}

class _Header extends HookConsumerWidget {
  final String title;
  final String? subtitle;
  final Widget image;

  const _Header({
    required this.title,
    this.subtitle,
    required this.image,
  });

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

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(height: 80, width: 80, child: image),
          const SizedBox(width: 16),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(title, style: theme.textTheme.titleLarge),
                if (subtitle != null)
                  Text(subtitle!, style: theme.textTheme.titleSmall),
              ],
            ),
          )
        ],
      ),
    );
  }
}

class _Star extends HookConsumerWidget {
  const _Star();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final l = AppLocalizations.of(context);
    return _MenuItem(
      title: l.actionsStar,
      icon: const Icon(Icons.star_outline_rounded),
      onTap: () {},
    );
  }
}

class _DownloadAction extends HookConsumerWidget {
  final DownloadAction downloadAction;

  const _DownloadAction({
    super.key,
    required this.downloadAction,
  });

  String _actionText(AppLocalizations l) {
    switch (downloadAction.type) {
      case DownloadActionType.download:
        return l.actionsDownload;
      case DownloadActionType.cancel:
        return l.actionsDownloadCancel;
      case DownloadActionType.delete:
        return l.actionsDownloadDelete;
    }
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return _MenuItem(
      title: _actionText(AppLocalizations.of(context)),
      icon: downloadAction.iconBuilder(context),
      onTap: downloadAction.action,
    );
  }
}

class _ViewArtist extends HookConsumerWidget {
  final String id;

  const _ViewArtist({
    required this.id,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final l = AppLocalizations.of(context);
    return _MenuItem(
      title: l.resourcesArtistActionsView,
      icon: const Icon(Icons.person_rounded),
      onTap: () async {
        final router = context.router;

        await router.pop();
        if (router.currentPath == '/now-playing') {
          await router.pop();
          await router.navigate(const LibraryRouter());
        }
        await router.navigate(ArtistRoute(id: id));
      },
    );
  }
}

class _ViewAlbum extends HookConsumerWidget {
  final String id;

  const _ViewAlbum({
    required this.id,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final l = AppLocalizations.of(context);
    return _MenuItem(
      title: l.resourcesAlbumActionsView,
      icon: const Icon(Icons.album_rounded),
      onTap: () async {
        final router = context.router;

        await router.pop();
        if (router.currentPath == '/now-playing') {
          await router.pop();
          await router.navigate(const LibraryRouter());
        }
        await router.navigate(AlbumSongsRoute(id: id));
      },
    );
  }
}

class _MenuItem extends StatelessWidget {
  final String title;
  final Widget icon;
  final FutureOr<void> Function()? onTap;

  const _MenuItem({
    required this.title,
    required this.icon,
    this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(title),
      leading: Padding(
        padding: const EdgeInsetsDirectional.only(start: 8),
        child: icon,
      ),
      onTap: onTap,
    );
  }
}
