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

import 'package:iconsax_plus/iconsax_plus.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:screen_brightness/screen_brightness.dart';

import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/movie_model.dart';
import 'package:fladder/models/media_playback_model.dart';
import 'package:fladder/models/playback/playback_model.dart';
import 'package:fladder/models/settings/video_player_settings.dart';
import 'package:fladder/providers/settings/client_settings_provider.dart';
import 'package:fladder/providers/settings/video_player_settings_provider.dart';
import 'package:fladder/providers/user_provider.dart';
import 'package:fladder/providers/video_player_provider.dart';
import 'package:fladder/screens/shared/animated_fade_size.dart';
import 'package:fladder/screens/shared/default_title_bar.dart';
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
import 'package:fladder/util/fladder_image.dart';
import 'package:fladder/util/list_padding.dart';
import 'package:fladder/util/localization_helper.dart';
import 'package:fladder/widgets/full_screen_helpers/full_screen_wrapper.dart';
import 'package:fladder/widgets/navigation_scaffold/components/floating_player_bar.dart';
import 'package:fladder/widgets/shared/progress_floating_button.dart';

class VideoPlayerNextWrapper extends ConsumerStatefulWidget {
  final Widget video;
  final Widget controls;
  final List<Widget> overlays;
  const VideoPlayerNextWrapper({
    required this.video,
    required this.controls,
    this.overlays = const [],
    super.key,
  });

  @override
  ConsumerState<ConsumerStatefulWidget> createState() => _VideoPlayerNextWrapperState();
}

class _VideoPlayerNextWrapperState extends ConsumerState<VideoPlayerNextWrapper> {
  bool show = false;
  bool showOverwrite = false;
  late RestartableTimerController timerController =
      RestartableTimerController(const Duration(seconds: 30), const Duration(milliseconds: 33), onTimeout: onTimeOut);

  void onTimeOut() {
    timerController.cancel();
    if (showOverwrite == true) return;
    final nextUp = ref.read(playBackModel.select((value) => value?.nextVideo));
    if (nextUp != null) {
      ref.read(playbackModelHelper).loadNewVideo(nextUp);
    }
    hideNextUp();
  }

  void showNextScreen(MediaPlaybackModel model) {
    final nextUp = ref.read(playBackModel.select((value) => value?.nextVideo));
    if (nextUp == null) return;
    if (show) return;
    if (showOverwrite) return;
    if (!model.playing) return;
    if (model.buffering) return;

    setState(() {
      show = true;
      timerController.reset();
      timerController.play();
    });
  }

  void determineShow(MediaPlaybackModel model) {
    final playerState = ref.watch(mediaPlaybackProvider.select((value) => value.state));
    if (playerState != VideoPlayerState.fullScreen) {
      showOverwrite = false;
      show = false;
      return;
    }

    final nextType = ref.read(videoPlayerSettingsProvider.select((value) => value.nextVideoType));
    if (nextType == AutoNextType.off || model.duration < const Duration(seconds: 40)) {
      showOverwrite = false;
      show = false;
      return;
    }

    final credits = ref.read(playBackModel)?.mediaSegments?.outro;

    if (nextType == AutoNextType.static || credits == null) {
      if ((model.duration - model.position).abs() < const Duration(seconds: 32)) {
        showNextScreen(model);
        return;
      }
    } else if (nextType == AutoNextType.smart) {
      final maxTime = ref.read(userProvider.select((value) => value?.serverConfiguration?.maxResumePct ?? 90));
      final resumeDuration = model.duration * (maxTime / 100);
      final timeLeft = model.duration - credits.end;
      if (credits.end > resumeDuration && timeLeft < const Duration(seconds: 30)) {
        if (model.position >= credits.start) {
          showNextScreen(model);
          return;
        }
      } else if ((model.duration - model.position).abs() < const Duration(seconds: 32)) {
        showNextScreen(model);
        return;
      }
    }
    setState(() {
      show = false;
      showOverwrite = false;
      timerController.cancel();
    });
  }

  void hideNextUp() {
    timerController.cancel();
    setState(() {
      show = false;
      showOverwrite = true;
    });
  }

  Future<void> closePlayer() async {
    clearOverlaySettings();
    ref.read(videoPlayerProvider).stop();
    Navigator.of(context).pop();
  }

  Future<void> clearOverlaySettings() async {
    if (AdaptiveLayout.of(context).inputDevice != InputDevice.pointer) {
      ScreenBrightness().resetApplicationScreenBrightness();
    } else {
      fullScreenHelper.closeFullScreen(ref);
    }

    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
      statusBarIconBrightness: ref.read(clientSettingsProvider.select((value) => value.statusBarBrightness(context))),
    ));
  }

  @override
  void dispose() {
    timerController.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    const animSpeed = Duration(milliseconds: 250);
    final nextUp = ref.watch(playBackModel.select((value) => value?.nextVideo));
    final currentItem = ref.watch(playBackModel.select((value) => value?.item));
    final portraitMode = MediaQuery.sizeOf(context).width < MediaQuery.sizeOf(context).height;

    double padding = show ? 16 : 0;

    ref.listen(mediaPlaybackProvider, (previous, next) => determineShow(next));
    return Hero(
      tag: videoPlayerHeroTag,
      child: Stack(
        children: [
          Container(
            color: Theme.of(context).colorScheme.surfaceContainerLowest.withValues(alpha: 0.2),
          ),
          if (nextUp != null)
            AnimatedAlign(
              duration: animSpeed,
              alignment: portraitMode ? Alignment.bottomCenter : Alignment.centerRight,
              child: AnimatedOpacity(
                duration: animSpeed,
                opacity: show ? 1 : 0,
                child: Padding(
                  padding: MediaQuery.paddingOf(context).add(const EdgeInsets.all(32)),
                  child: FractionallySizedBox(
                    widthFactor: portraitMode ? null : 0.35,
                    heightFactor: portraitMode ? 0.5 : null,
                    child: Card(
                      elevation: 10,
                      child: Padding(
                        padding: const EdgeInsets.all(16.0),
                        child: Column(
                          mainAxisSize: MainAxisSize.min,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Row(
                              mainAxisSize: MainAxisSize.min,
                              children: [
                                Expanded(
                                  child: Text(
                                    context.localized.nextUp,
                                    softWrap: false,
                                    overflow: TextOverflow.fade,
                                    style: Theme.of(context)
                                        .textTheme
                                        .titleLarge
                                        ?.copyWith(fontWeight: FontWeight.bold, fontSize: 24.0),
                                  ),
                                ),
                                SizedBox.square(
                                  dimension: 45.0,
                                  child: ProgressFloatingButton(
                                    controller: timerController,
                                  ),
                                ),
                              ].addInBetween(
                                const SizedBox(
                                  height: 16,
                                  width: 16,
                                ),
                              ),
                            ),
                            const Divider(),
                            Flexible(
                              child: SingleChildScrollView(
                                child: _NextUpInformation(
                                  item: nextUp,
                                ),
                              ),
                            ),
                          ].addInBetween(const SizedBox(
                            height: 8,
                            width: 8,
                          )),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ),
          AnimatedAlign(
            duration: animSpeed,
            alignment: portraitMode ? Alignment.topCenter : Alignment.centerLeft,
            child: AnimatedPadding(
              duration: animSpeed,
              padding: EdgeInsets.all(padding).add(show ? MediaQuery.paddingOf(context) : EdgeInsets.zero),
              child: AnimatedFractionallySizedBox(
                duration: animSpeed,
                heightFactor: show ? (portraitMode ? 0.40 : 0.9) : 1.0,
                widthFactor: show ? (portraitMode ? 1 : 0.60) : 1.0,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    if (currentItem != null)
                      AnimatedFadeSize(
                        duration: animSpeed,
                        child: show
                            ? Padding(
                                padding: const EdgeInsets.only(bottom: 16),
                                child: Row(
                                  children: [
                                    Expanded(
                                      child: Column(
                                        mainAxisSize: MainAxisSize.min,
                                        crossAxisAlignment: CrossAxisAlignment.start,
                                        children: [
                                          Flexible(
                                              child: Text(currentItem.title,
                                                  style: Theme.of(context).textTheme.displaySmall)),
                                          if (currentItem.label(context) != null)
                                            Flexible(
                                              child: Text(
                                                currentItem.label(context)!,
                                                maxLines: 2,
                                                overflow: TextOverflow.fade,
                                                style: Theme.of(context).textTheme.bodyMedium,
                                              ),
                                            ),
                                        ],
                                      ),
                                    ),
                                    const SizedBox(width: 8),
                                    IconButton.filledTonal(
                                      onPressed: () => hideNextUp(),
                                      tooltip: context.localized.resumeVideo,
                                      icon: const Icon(IconsaxPlusBold.maximize_4),
                                    ),
                                    const SizedBox(width: 8),
                                    IconButton.filledTonal(
                                      onPressed: () => closePlayer(),
                                      tooltip: context.localized.closeVideo,
                                      icon: const Icon(IconsaxPlusBold.close_square),
                                    ),
                                  ],
                                ),
                              )
                            : const SizedBox.shrink(),
                      ),
                    Flexible(
                      child: Stack(
                        fit: StackFit.passthrough,
                        children: [
                          AnimatedContainer(
                            duration: animSpeed,
                            decoration: BoxDecoration(
                              color: Colors.black,
                              borderRadius: BorderRadius.circular(show ? 16 : 0),
                            ),
                            child: widget.video,
                          ),
                          IgnorePointer(
                            ignoring: show,
                            child: AnimatedOpacity(
                              opacity: show ? 0 : 1,
                              duration: animSpeed,
                              child: widget.controls,
                            ),
                          ),
                        ],
                      ),
                    ),
                    IgnorePointer(
                      ignoring: !show,
                      child: AnimatedFadeSize(
                        duration: animSpeed,
                        child: show
                            ? Padding(
                                padding: const EdgeInsets.only(top: 16),
                                child: _SimpleControls(
                                  skip: nextUp != null ? () => onTimeOut() : null,
                                ),
                              )
                            : const SizedBox.shrink(),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
          if (AdaptiveLayout.of(context).isDesktop)
            IgnorePointer(
              ignoring: !show,
              child: AnimatedOpacity(
                duration: animSpeed,
                opacity: show ? 1 : 0,
                child: const Align(
                  alignment: Alignment.topRight,
                  child: DefaultTitleBar(),
                ),
              ),
            ),
        ],
      ),
    );
  }
}

class _NextUpInformation extends StatelessWidget {
  final ItemBaseModel item;
  const _NextUpInformation({
    required this.item,
  });

  @override
  Widget build(BuildContext context) {
    return switch (item) {
      MovieModel _ => Row(
          children: [
            Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Flexible(
                  child: ConstrainedBox(
                    constraints: const BoxConstraints(maxWidth: 150),
                    child: AspectRatio(
                      aspectRatio: 0.67,
                      child: Card(
                        child: FladderImage(
                          image: item.images?.primary,
                        ),
                      ),
                    ),
                  ),
                ),
                Text(
                  item.title,
                  style: Theme.of(context).textTheme.titleLarge,
                ),
              ].addInBetween(
                const SizedBox(height: 8),
              ),
            ),
            Flexible(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    context.localized.overview,
                    style: Theme.of(context).textTheme.titleLarge,
                  ),
                  const Divider(),
                  Text(item.overview.summary),
                ],
              ),
            )
          ].addInBetween(
            const SizedBox(width: 16),
          ),
        ),
      _ => Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              item.title,
              style: Theme.of(context).textTheme.titleLarge,
            ),
            if (item.label(context) != null)
              Text(
                item.label(context)!,
              ),
            Flexible(
              child: AspectRatio(
                aspectRatio: 2.1,
                child: Card(
                  child: FladderImage(
                    image: item.images?.primary,
                  ),
                ),
              ),
            ),
            Text(
              context.localized.overview,
              style: Theme.of(context).textTheme.titleLarge,
            ),
            Text(item.overview.summary),
            const SizedBox(height: 12)
          ].addInBetween(
            const SizedBox(height: 8),
          ),
        )
    };
  }
}

class _SimpleControls extends ConsumerWidget {
  final Function()? skip;
  const _SimpleControls({
    this.skip,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final player = ref.watch(videoPlayerProvider);
    final isPlaying = ref.watch(mediaPlaybackProvider.select((value) => value.playing));
    return Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          IconButton.filledTonal(
            onPressed: () => player.playOrPause(),
            icon: Icon(isPlaying ? IconsaxPlusBold.pause : IconsaxPlusBold.play),
          ),
          if (skip != null)
            IconButton.filledTonal(
              onPressed: skip,
              tooltip: context.localized.playNextVideo,
              icon: const Icon(IconsaxPlusBold.next),
            )
        ].addInBetween(const SizedBox(width: 4)));
  }
}
