import 'dart:io' show Platform;

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

import 'package:auto_route/auto_route.dart';
import 'package:collection/collection.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'package:fladder/models/items/media_segments_model.dart';
import 'package:fladder/models/settings/video_player_settings.dart';
import 'package:fladder/providers/arguments_provider.dart';
import 'package:fladder/providers/connectivity_provider.dart';
import 'package:fladder/providers/settings/video_player_settings_provider.dart';
import 'package:fladder/providers/user_provider.dart';
import 'package:fladder/screens/settings/settings_list_tile.dart';
import 'package:fladder/screens/settings/settings_scaffold.dart';
import 'package:fladder/screens/settings/widgets/key_listener.dart';
import 'package:fladder/screens/settings/widgets/settings_label_divider.dart';
import 'package:fladder/screens/settings/widgets/settings_list_group.dart';
import 'package:fladder/screens/settings/widgets/settings_message_box.dart';
import 'package:fladder/screens/settings/widgets/subtitle_editor.dart';
import 'package:fladder/screens/shared/animated_fade_size.dart';
import 'package:fladder/screens/shared/input_fields.dart';
import 'package:fladder/screens/video_player/components/video_player_options_sheet.dart';
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
import 'package:fladder/util/bitrate_helper.dart';
import 'package:fladder/util/box_fit_extension.dart';
import 'package:fladder/util/localization_helper.dart';
import 'package:fladder/widgets/shared/enum_selection.dart';
import 'package:fladder/widgets/shared/item_actions.dart';

@RoutePage()
class PlayerSettingsPage extends ConsumerStatefulWidget {
  const PlayerSettingsPage({super.key});

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

class _PlayerSettingsPageState extends ConsumerState<PlayerSettingsPage> {
  @override
  Widget build(BuildContext context) {
    final videoSettings = ref.watch(videoPlayerSettingsProvider);
    final provider = ref.read(videoPlayerSettingsProvider.notifier);

    final connectionState = ref.watch(connectivityStatusProvider);

    final userSettings = ref.watch(userProvider.select((value) => value?.userSettings));

    return SettingsScaffold(
      label: context.localized.settingsPlayerTitle,
      items: [
        ...settingsListGroup(
          context,
          SettingsLabelDivider(label: context.localized.video),
          [
            if (!AdaptiveLayout.of(context).isDesktop && !kIsWeb)
              Column(
                children: [
                  SettingsListTile(
                    label: Text(context.localized.videoScalingFillScreenTitle),
                    subLabel: Text(context.localized.videoScalingFillScreenDesc),
                    onTap: () => provider.setFillScreen(!videoSettings.fillScreen),
                    trailing: Switch(
                      value: videoSettings.fillScreen,
                      onChanged: (value) => provider.setFillScreen(value),
                    ),
                  ),
                  AnimatedFadeSize(
                    child: videoSettings.fillScreen
                        ? SettingsMessageBox(
                            context.localized.videoScalingFillScreenNotif,
                            messageType: MessageType.warning,
                          )
                        : Container(),
                  ),
                ],
              ),
            SettingsListTile(
              label: Text(context.localized.videoScaling),
              trailing: EnumBox(
                current: videoSettings.videoFit.label(context),
                itemBuilder: (context) => BoxFit.values
                    .map(
                      (entry) => ItemActionButton(
                        label: Text(entry.label(context)),
                        action: () => ref.read(videoPlayerSettingsProvider.notifier).setFitType(entry),
                      ),
                    )
                    .toList(),
              ),
            ),
            SettingsListTile(
              label: _StatusIndicator(
                homeInternet: connectionState.homeInternet,
                label: Text(context.localized.homeStreamingQualityTitle),
              ),
              subLabel: Text(context.localized.homeStreamingQualityDesc),
              trailing: EnumBox(
                current: ref.watch(
                  videoPlayerSettingsProvider.select((value) => value.maxHomeBitrate.label(context)),
                ),
                itemBuilder: (context) => Bitrate.values
                    .map(
                      (entry) => ItemActionButton(
                        label: Text(entry.label(context)),
                        action: () => ref.read(videoPlayerSettingsProvider.notifier).state =
                            videoSettings.copyWith(maxHomeBitrate: entry),
                      ),
                    )
                    .toList(),
              ),
            ),
            SettingsListTile(
              label: _StatusIndicator(
                homeInternet: !connectionState.homeInternet,
                label: Text(context.localized.internetStreamingQualityTitle),
              ),
              subLabel: Text(context.localized.internetStreamingQualityDesc),
              trailing: EnumBox(
                current: ref.watch(
                  videoPlayerSettingsProvider.select((value) => value.maxInternetBitrate.label(context)),
                ),
                itemBuilder: (context) => Bitrate.values
                    .map(
                      (entry) => ItemActionButton(
                        label: Text(entry.label(context)),
                        action: () => ref.read(videoPlayerSettingsProvider.notifier).state =
                            videoSettings.copyWith(maxInternetBitrate: entry),
                      ),
                    )
                    .toList(),
              ),
            ),
          ],
        ),
        const SizedBox(height: 12),
        ...settingsListGroup(context, SettingsLabelDivider(label: context.localized.mediaSegmentActions), [
          ...videoSettings.segmentSkipSettings.entries.sorted((a, b) => b.key.index.compareTo(a.key.index)).map(
                (entry) => Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                  child: Row(
                    children: [
                      Expanded(
                        child: Text(
                          entry.key.label(context),
                          style: Theme.of(context).textTheme.titleLarge,
                        ),
                      ),
                      EnumBox(
                        current: entry.value.label(context),
                        itemBuilder: (context) => SegmentSkip.values
                            .map(
                              (value) => ItemActionButton(
                                label: Text(value.label(context)),
                                action: () {
                                  final newEntries = videoSettings.segmentSkipSettings.map(
                                      (key, currentValue) => MapEntry(key, key == entry.key ? value : currentValue));
                                  ref.read(videoPlayerSettingsProvider.notifier).state =
                                      videoSettings.copyWith(segmentSkipSettings: newEntries);
                                },
                              ),
                            )
                            .toList(),
                      )
                    ],
                  ),
                ),
              ),
        ]),
        const SizedBox(height: 12),
        ...settingsListGroup(
          context,
          SettingsLabelDivider(label: context.localized.shortCuts),
          [
            if (userSettings != null)
              SettingsListTile(
                label: Text(context.localized.skipBackLength),
                trailing: SizedBox(
                    width: 125,
                    child: IntInputField(
                      suffix: context.localized.seconds(10),
                      controller: TextEditingController(text: userSettings.skipBackDuration.inSeconds.toString()),
                      onSubmitted: (value) {
                        if (value != null) {
                          ref.read(userProvider.notifier).setBackwardSpeed(value);
                        }
                      },
                    )),
              ),
            SettingsListTile(
              label: Text(context.localized.skipForwardLength),
              trailing: SizedBox(
                  width: 125,
                  child: IntInputField(
                    suffix: context.localized.seconds(10),
                    controller: TextEditingController(text: userSettings!.skipForwardDuration.inSeconds.toString()),
                    onSubmitted: (value) {
                      if (value != null) {
                        ref.read(userProvider.notifier).setForwardSpeed(value);
                      }
                    },
                  )),
            ),
            if (AdaptiveLayout.inputDeviceOf(context) == InputDevice.pointer)
              ExpansionTile(
                title: Text(
                  context.localized.keyboardShortCuts,
                  style: Theme.of(context).textTheme.titleLarge,
                ),
                children: VideoHotKeys.values
                    .map(
                      (entry) => Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                        child: Row(
                          children: [
                            Expanded(
                              child: Text(
                                entry.label(context),
                                style: Theme.of(context).textTheme.titleMedium,
                              ),
                            ),
                            Flexible(
                              child: KeyCombinationWidget(
                                currentKey: videoSettings.hotKeys[entry],
                                defaultKey: videoSettings.defaultShortCuts[entry]!,
                                onChanged: (value) =>
                                    ref.read(videoPlayerSettingsProvider.notifier).setShortcuts(MapEntry(entry, value)),
                              ),
                            ),
                          ],
                        ),
                      ),
                    )
                    .toList(),
              ),
          ],
        ),
        const SizedBox(height: 12),
        ...settingsListGroup(context, SettingsLabelDivider(label: context.localized.playbackTrackSelection), [
          SettingsListTile(
            label: Text(context.localized.rememberAudioSelections),
            subLabel: Text(context.localized.rememberAudioSelectionsDesc),
            onTap: () => ref.read(userProvider.notifier).setRememberAudioSelections(),
            trailing: Switch(
              value: ref.watch(userProvider.select(
                (value) => value?.userConfiguration?.rememberAudioSelections ?? true,
              )),
              onChanged: (_) => ref.read(userProvider.notifier).setRememberAudioSelections(),
            ),
          ),
          SettingsListTile(
            label: Text(context.localized.rememberSubtitleSelections),
            subLabel: Text(context.localized.rememberSubtitleSelectionsDesc),
            onTap: () => ref.read(userProvider.notifier).setRememberSubtitleSelections(),
            trailing: Switch(
              value: ref.watch(userProvider.select(
                (value) => value?.userConfiguration?.rememberSubtitleSelections ?? true,
              )),
              onChanged: (_) => ref.read(userProvider.notifier).setRememberSubtitleSelections(),
            ),
          ),
        ]),
        const SizedBox(height: 12),
        ...settingsListGroup(
          context,
          SettingsLabelDivider(label: context.localized.advanced),
          [
            if (PlayerOptions.available.length != 1)
              SettingsListTile(
                label: Text(context.localized.playerSettingsBackendTitle),
                subLabel: Text(context.localized.playerSettingsBackendDesc),
                trailing: Builder(builder: (context) {
                  final wantedPlayer = videoSettings.wantedPlayer;
                  final currentPlayer = videoSettings.playerOptions;
                  return EnumBox(
                    current: currentPlayer == null
                        ? "${context.localized.defaultLabel} (${PlayerOptions.platformDefaults.label(context)})"
                        : wantedPlayer.label(context),
                    itemBuilder: (context) => [
                      ItemActionButton(
                        label: Text(
                            "${context.localized.defaultLabel} (${PlayerOptions.platformDefaults.label(context)})"),
                        action: () => ref.read(videoPlayerSettingsProvider.notifier).state =
                            videoSettings.copyWith(playerOptions: null),
                      ),
                      ...PlayerOptions.available.map(
                        (entry) => ItemActionButton(
                          label: Text(entry.label(context)),
                          action: () => ref.read(videoPlayerSettingsProvider.notifier).state =
                              videoSettings.copyWith(playerOptions: entry),
                        ),
                      )
                    ],
                  );
                }),
              ),
            AnimatedFadeSize(
              child: switch (videoSettings.wantedPlayer) {
                PlayerOptions.libMPV => Column(
                    children: [
                      SettingsListTile(
                        label: Text(context.localized.settingsPlayerVideoHWAccelTitle),
                        subLabel: Text(context.localized.settingsPlayerVideoHWAccelDesc),
                        onTap: () => provider.setHardwareAccel(!videoSettings.hardwareAccel),
                        trailing: Switch(
                          value: videoSettings.hardwareAccel,
                          onChanged: (value) => provider.setHardwareAccel(value),
                        ),
                      ),
                      if (!kIsWeb)
                        SettingsListTile(
                          label: Text(context.localized.settingsPlayerNativeLibassAccelTitle),
                          subLabel: Text(context.localized.settingsPlayerNativeLibassAccelDesc),
                          onTap: () => provider.setUseLibass(!videoSettings.useLibass),
                          trailing: Switch(
                            value: videoSettings.useLibass,
                            onChanged: (value) => provider.setUseLibass(value),
                          ),
                        ),
                      if (!videoSettings.useLibass)
                        SettingsListTile(
                          label: Text(context.localized.settingsPlayerCustomSubtitlesTitle),
                          subLabel: Text(context.localized.settingsPlayerCustomSubtitlesDesc),
                          onTap: videoSettings.useLibass
                              ? null
                              : () {
                                  showDialog(
                                    context: context,
                                    barrierDismissible: true,
                                    useSafeArea: false,
                                    builder: (context) => const SubtitleEditor(),
                                  );
                                },
                        ),
                      AnimatedFadeSize(
                        child: videoSettings.useLibass && videoSettings.hardwareAccel && Platform.isAndroid
                            ? SettingsMessageBox(
                                context.localized.settingsPlayerMobileWarning,
                                messageType: MessageType.warning,
                              )
                            : Container(),
                      ),
                      SettingsListTile(
                        label: Text(context.localized.settingsPlayerBufferSizeTitle),
                        subLabel: Text(context.localized.settingsPlayerBufferSizeDesc),
                        trailing: SizedBox(
                            width: 70,
                            child: IntInputField(
                              suffix: 'MB',
                              controller: TextEditingController(text: videoSettings.bufferSize.toString()),
                              onSubmitted: (value) {
                                if (value != null) {
                                  provider.setBufferSize(value);
                                }
                              },
                            )),
                      ),
                    ],
                  ),
                PlayerOptions.nativePlayer => Column(
                    children: [
                      SettingsListTile(
                        label: Text(context.localized.mediaTunnelingTitle),
                        subLabel: Text(context.localized.mediaTunnelingDesc),
                        onTap: () => provider.setMediaTunneling(!videoSettings.enableTunneling),
                        trailing: Switch(
                          value: videoSettings.enableTunneling,
                          onChanged: (value) => provider.setMediaTunneling(value),
                        ),
                      ),
                    ],
                  ),
                PlayerOptions.libMDK => SettingsMessageBox(
                    messageType: MessageType.info,
                    "${context.localized.noVideoPlayerOptions}\n${context.localized.mdkExperimental}"),
              },
            ),
            if (videoSettings.wantedPlayer != PlayerOptions.nativePlayer) ...[
              Column(
                children: [
                  SettingsListTile(
                    label: Text(context.localized.settingsAutoNextTitle),
                    subLabel: Text(context.localized.settingsAutoNextDesc),
                    trailing: EnumBox(
                      current: ref.watch(
                        videoPlayerSettingsProvider.select(
                          (value) => value.nextVideoType.label(context),
                        ),
                      ),
                      itemBuilder: (context) => AutoNextType.values
                          .map(
                            (entry) => ItemActionButton(
                              label: Text(entry.label(context)),
                              action: () => ref.read(videoPlayerSettingsProvider.notifier).state =
                                  videoSettings.copyWith(nextVideoType: entry),
                            ),
                          )
                          .toList(),
                    ),
                  ),
                  AnimatedFadeSize(
                    child: switch (ref.watch(videoPlayerSettingsProvider.select((value) => value.nextVideoType))) {
                      AutoNextType.smart => SettingsMessageBox(AutoNextType.smart.desc(context)),
                      AutoNextType.static => SettingsMessageBox(AutoNextType.static.desc(context)),
                      _ => const SizedBox.shrink(),
                    },
                  ),
                ],
              ),
              if (!AdaptiveLayout.of(context).isDesktop && !kIsWeb && !ref.read(argumentsStateProvider).htpcMode)
                SettingsListTile(
                  label: Text(context.localized.playerSettingsOrientationTitle),
                  subLabel: Text(context.localized.playerSettingsOrientationDesc),
                  onTap: () => showOrientationOptions(context, ref),
                ),
            ],
          ],
        ),
      ],
    );
  }
}

class _StatusIndicator extends StatelessWidget {
  final bool homeInternet;
  final Widget label;
  const _StatusIndicator({required this.homeInternet, required this.label});

  @override
  Widget build(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        if (homeInternet) ...[
          Container(
            width: 8,
            height: 8,
            decoration: const BoxDecoration(
              color: Colors.greenAccent,
              shape: BoxShape.circle,
            ),
          ),
          const SizedBox(width: 6),
        ],
        Flexible(child: label),
      ],
    );
  }
}
