import 'dart:async';

import 'package:flutter/material.dart';

import 'package:flex_color_picker/flex_color_picker.dart';

import 'package:namida/base/setting_subpage_provider.dart';
import 'package:namida/class/lang.dart';
import 'package:namida/class/track.dart';
import 'package:namida/controller/current_color.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/settings_search_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/themes.dart';
import 'package:namida/core/translations/arb/app_localizations.dart';
import 'package:namida/core/translations/language.dart';
import 'package:namida/core/utils.dart';
import 'package:namida/ui/widgets/custom_widgets.dart';
import 'package:namida/ui/widgets/settings_card.dart';
import 'package:namida/youtube/class/youtube_id.dart';
import 'package:namida/youtube/controller/yt_miniplayer_ui_controller.dart';

enum _ThemeSettingsKeys with SettingKeysBase {
  themeMode,
  autoColoring,
  wallpaperColors(NamidaFeaturesAvailablity.android12and_plus),
  forceMiniplayerColors,
  pitchBlack,
  defaultColor,
  defaultColorDark,
  language,
  ;

  @override
  final NamidaFeaturesAvailablityBase? availability;
  const _ThemeSettingsKeys([this.availability]);
}

class ThemeSetting extends SettingSubpageProvider {
  const ThemeSetting({super.key, super.initialItem});

  @override
  SettingSubpageEnum get settingPage => SettingSubpageEnum.theme;

  @override
  Map<SettingKeysBase, List<String>> get lookupMap => {
    _ThemeSettingsKeys.themeMode: [lang.themeMode],
    _ThemeSettingsKeys.autoColoring: [lang.autoColoring, lang.autoColoringSubtitle],
    _ThemeSettingsKeys.wallpaperColors: [lang.pickColorsFromDeviceWallpaper],
    _ThemeSettingsKeys.forceMiniplayerColors: [lang.forceMiniplayerFollowTrackColors],
    _ThemeSettingsKeys.pitchBlack: [lang.usePitchBlack, lang.usePitchBlackSubtitle],
    _ThemeSettingsKeys.defaultColor: [lang.defaultColor, lang.defaultColorSubtitle],
    _ThemeSettingsKeys.defaultColorDark: ["${lang.defaultColor} (${lang.themeModeDark})", lang.defaultColorSubtitle],
    _ThemeSettingsKeys.language: [lang.language],
  };

  void _refreshColorCurrentPlayingItem() {
    final currentItem = Player.inst.currentItem.value;
    if (currentItem is YoutubeID) {
      CurrentColor.inst.updatePlayerColorFromYoutubeID(currentItem);
    } else if (currentItem is Selectable) {
      CurrentColor.inst.updatePlayerColorFromTrack(currentItem, null);
    }
  }

  Widget getThemeTile({double? maxWidth}) {
    return getItemWrapper(
      key: _ThemeSettingsKeys.themeMode,
      child: CustomListTile(
        bgColor: getBgColor(_ThemeSettingsKeys.themeMode),
        icon: Broken.brush_4,
        title: lang.themeMode,
        trailingRaw: ToggleThemeModeContainer(
          maxWidth: ((maxWidth ?? Dimensions.inst.availableAppContentWidth) * 0.4).withMaximum(248.0),
        ),
      ),
    );
  }

  Widget getAutoColoringTile() {
    return getItemWrapper(
      key: _ThemeSettingsKeys.autoColoring,
      child: ObxO(
        rx: settings.autoColor,
        builder: (context, autoColor) => CustomSwitchListTile(
          bgColor: getBgColor(_ThemeSettingsKeys.autoColoring),
          icon: Broken.colorfilter,
          title: lang.autoColoring,
          subtitle: "${lang.autoColoringSubtitle}. ${lang.performanceNote}",
          value: autoColor,
          onChanged: (isTrue) {
            settings.save(
              autoColor: !isTrue,
              performanceMode: PerformanceMode.custom,
            );
            if (isTrue) {
              CurrentColor.inst.updatePlayerColorFromColor(playerStaticColor);
              CurrentColor.inst.updateCurrentColorSchemeOfSubPages(playerStaticColor);
            } else {
              _refreshColorCurrentPlayingItem();
            }
          },
        ),
      ),
    );
  }

  Widget getLanguageTile(BuildContext context) {
    final theme = context.theme;
    final textTheme = theme.textTheme;
    return getItemWrapper(
      key: _ThemeSettingsKeys.language,
      child: ObxO(
        rx: Language.inst.currentLanguageRx,
        builder: (context, currentLanguage) => CustomListTile(
          bgColor: getBgColor(_ThemeSettingsKeys.language),
          icon: Broken.language_square,
          title: lang.language,
          subtitle: currentLanguage!.name,
          onTap: () {
            final allLocalesPre = AppLocalizations.supportedLocales;
            final allLanguages = allLocalesPre.map(NamidaLanguage.fromLocale).toFixedList();
            allLanguages.sortBy((e) => e.name);

            final selectedLangRx = Language.inst.getCurrentLanguageOrDevice().obs;

            NamidaNavigator.inst.navigateDialog(
              onDisposing: () {
                selectedLangRx.close();
              },
              dialog: CustomBlurryDialog(
                title: lang.language,
                normalTitleStyle: true,
                actions: [
                  // NamidaButton(
                  //   onTap: () async {
                  //     final files = await NamidaFileBrowser.pickFile(note: lang.addLanguage, allowedExtensions: NamidaFileExtensionsWrapper.json);
                  //     final path = files?.path;
                  //     if (path != null) {
                  //       try {
                  //         final st = await File(path).readAsString();
                  //         final map = jsonDecode(st);
                  //         final didUpdate = await Language.inst.loadLanguage(path.getFilenameWOExt, map);
                  //         if (didUpdate) {
                  //           NamidaNavigator.inst.closeDialog();
                  //         } else {
                  //           snackyy(title: lang.error, message: 'Unknown Error', isError: true);
                  //         }
                  //       } catch (e) {
                  //         snackyy(title: lang.error, message: e.toString(), isError: true);
                  //       }
                  //     }
                  //   },
                  //   text: lang.local,
                  // ),
                  const CancelButton(),
                  NamidaButton(
                    onTap: () => Language.inst.update(language: selectedLangRx.value).closeDialog(),
                    text: lang.confirm,
                  ),
                ],
                child: SizedBox(
                  height: namida.height * 0.5,
                  width: namida.width,
                  child: SmoothSingleChildScrollView(
                    child: Column(
                      children: [
                        ...allLanguages.map(
                          (e) => Padding(
                            padding: const EdgeInsets.all(3.0),
                            child: ObxO(
                              rx: selectedLangRx,
                              builder: (context, selectedLang) => ListTileWithCheckMark(
                                leading: Container(
                                  padding: const EdgeInsets.all(4.0),
                                  decoration: BoxDecoration(
                                    shape: BoxShape.circle,
                                    border: Border.all(
                                      width: 1.5,
                                      color: theme.colorScheme.onSurface.withAlpha(100),
                                    ),
                                  ),
                                  child: Text(
                                    e.name[0],
                                    style: const TextStyle(fontSize: 13.0),
                                  ),
                                ),
                                titleWidget: Text.rich(
                                  TextSpan(
                                    text: e.name,
                                    style: textTheme.displayMedium,
                                    children: e.country.isEmpty
                                        ? null
                                        : [
                                            TextSpan(
                                              text: " (${e.country})",
                                              style: textTheme.displaySmall,
                                            ),
                                          ],
                                  ),
                                ),
                                active: e == selectedLang,
                                onTap: () => selectedLangRx.value = e,
                              ),
                            ),
                          ),
                        ),
                        CustomListTile(
                          icon: Broken.add_circle,
                          title: lang.addLanguage,
                          subtitle: lang.addLanguageSubtitle,
                          onTap: () {
                            NamidaLinkUtils.openLink(AppSocial.TRANSLATION_REPO);
                          },
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            );
          },
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SettingsCard(
      title: lang.themeSettings,
      subtitle: lang.themeSettingsSubtitle,
      icon: Broken.brush_2,
      child: SizedBox(
        width: context.width,
        child: Column(
          children: [
            getThemeTile(),
            getAutoColoringTile(),
            getItemWrapper(
              key: _ThemeSettingsKeys.wallpaperColors,
              child: Obx(
                (context) => CustomSwitchListTile(
                  bgColor: getBgColor(_ThemeSettingsKeys.wallpaperColors),
                  enabled: settings.autoColor.valueR,
                  icon: Broken.gallery_import,
                  title: lang.pickColorsFromDeviceWallpaper,
                  value: settings.pickColorsFromDeviceWallpaper.valueR,
                  onChanged: (isTrue) {
                    settings.save(pickColorsFromDeviceWallpaper: !isTrue);
                    _refreshColorCurrentPlayingItem();
                  },
                ),
              ),
            ),
            getItemWrapper(
              key: _ThemeSettingsKeys.forceMiniplayerColors,
              child: Obx(
                (context) => CustomSwitchListTile(
                  bgColor: getBgColor(_ThemeSettingsKeys.forceMiniplayerColors),
                  icon: Broken.slider_horizontal,
                  title: lang.forceMiniplayerFollowTrackColors,
                  subtitle: '${lang.ignores}: ${lang.autoColoring}, ${lang.pickColorsFromDeviceWallpaper} & ${lang.defaultColor}',
                  value: settings.forceMiniplayerTrackColor.valueR,
                  onChanged: (isTrue) {
                    settings.save(forceMiniplayerTrackColor: !isTrue);
                    _refreshColorCurrentPlayingItem();
                  },
                ),
              ),
            ),
            getItemWrapper(
              key: _ThemeSettingsKeys.pitchBlack,
              child: ObxO(
                rx: settings.pitchBlack,
                builder: (context, pitchBlack) => CustomSwitchListTile(
                  bgColor: getBgColor(_ThemeSettingsKeys.pitchBlack),
                  icon: Broken.mirror,
                  title: lang.usePitchBlack,
                  subtitle: lang.usePitchBlackSubtitle,
                  value: pitchBlack,
                  onChanged: (isTrue) {
                    settings.save(pitchBlack: !isTrue);
                    if (context.isDarkMode) CurrentColor.inst.updateColorAfterThemeModeChange();
                  },
                ),
              ),
            ),
            getItemWrapper(
              key: _ThemeSettingsKeys.defaultColor,
              child: ObxO(
                rx: settings.autoColor,
                builder: (context, autoColor) => CustomListTile(
                  bgColor: getBgColor(_ThemeSettingsKeys.defaultColor),
                  enabled: !autoColor,
                  icon: Broken.bucket,
                  title: lang.defaultColor,
                  subtitle: lang.defaultColorSubtitle,
                  trailingRaw: FittedBox(
                    child: Obx(
                      (context) => CircleAvatar(
                        minRadius: 12,
                        backgroundColor: playerStaticColorLightR,
                      ),
                    ),
                  ),
                  onTap: () {
                    NamidaNavigator.inst.navigateDialog(
                      dialog: NamidaColorPickerDialog(
                        initialColor: playerStaticColorLight,
                        doneText: lang.done,
                        onColorChanged: (value) => _updateColorLight(value),
                        colorChangedDebouncer: true,
                        themeFollowsColor: true,
                        onDonePressed: (color) {
                          _updateColorLight(color);
                          NamidaNavigator.inst.closeDialog();
                        },
                        onRefreshButtonPressed: () {
                          _updateColorLight(kMainColorLight);
                          NamidaNavigator.inst.closeDialog();
                        },
                        cancelButton: false,
                      ),
                    );
                  },
                ),
              ),
            ),
            getItemWrapper(
              key: _ThemeSettingsKeys.defaultColorDark,
              child: ObxO(
                rx: settings.autoColor,
                builder: (context, autoColor) => CustomListTile(
                  bgColor: getBgColor(_ThemeSettingsKeys.defaultColorDark),
                  enabled: !autoColor,
                  leading: const StackedIcon(
                    baseIcon: Broken.bucket,
                    secondaryIcon: Broken.moon,
                  ),
                  title: "${lang.defaultColor} (${lang.themeModeDark})",
                  subtitle: lang.defaultColorSubtitle,
                  trailingRaw: FittedBox(
                    child: Obx(
                      (context) => CircleAvatar(
                        minRadius: 12,
                        backgroundColor: playerStaticColorDarkR,
                      ),
                    ),
                  ),
                  onTap: () {
                    NamidaNavigator.inst.navigateDialog(
                      dialog: NamidaColorPickerDialog(
                        initialColor: playerStaticColorDark,
                        doneText: lang.done,
                        onColorChanged: (value) => _updateColorDark(value),
                        colorChangedDebouncer: true,
                        themeFollowsColor: true,
                        onDonePressed: (color) {
                          _updateColorDark(color);
                          NamidaNavigator.inst.closeDialog();
                        },
                        onRefreshButtonPressed: () {
                          _updateColorDark(kMainColorDark);
                          NamidaNavigator.inst.closeDialog();
                        },
                        cancelButton: false,
                      ),
                    );
                  },
                ),
              ),
            ),
            getLanguageTile(context),
          ],
        ),
      ),
    );
  }

  void _updateColorLight(Color color) {
    settings.save(staticColor: color.intValue);
    if (!namida.isDarkMode) {
      CurrentColor.inst.updatePlayerColorFromColor(color, false);
    }
  }

  void _updateColorDark(Color color) {
    settings.save(staticColorDark: color.intValue);
    if (namida.isDarkMode) {
      CurrentColor.inst.updatePlayerColorFromColor(color, false);
    }
  }
}

class ToggleThemeModeContainer extends StatefulWidget {
  final double maxWidth;
  final double blurRadius;
  const ToggleThemeModeContainer({super.key, required this.maxWidth, this.blurRadius = 6.0});

  static void onThemeChangeTap(ThemeMode themeMode) async {
    settings.save(themeMode: themeMode);
    await Future.delayed(const Duration(milliseconds: kThemeAnimationDurationMS));
    CurrentColor.inst.updateColorAfterThemeModeChange();
    YoutubeMiniplayerUiController.inst.startDimTimer();
  }

  @override
  State<ToggleThemeModeContainer> createState() => _ToggleThemeModeContainerState();
}

class _ToggleThemeModeContainerState extends State<ToggleThemeModeContainer> {
  Widget? _cachedWidget;

  @override
  void didUpdateWidget(ToggleThemeModeContainer old) {
    super.didUpdateWidget(old);
    if (old.maxWidth != widget.maxWidth) {
      _cachedWidget = null;
    }
  }

  Alignment _themeModeToAlignment(ThemeMode theme) {
    return theme == ThemeMode.light
        ? Alignment.center
        : theme == ThemeMode.dark
        ? Alignment.centerRight
        : Alignment.centerLeft;
  }

  @override
  Widget build(BuildContext context) {
    // -- better fully isolate this widget, so that animations work smoothly outside theme animation hell
    if (_cachedWidget != null) return _cachedWidget!;
    const brConst = 8.0;
    const horizontalPaddingConst = 8.0;
    final itemsCount = ThemeMode.values.length;
    final bgSlideWidth = (widget.maxWidth / itemsCount) - horizontalPaddingConst;
    return _cachedWidget = RepaintBoundary(
      child: ObxO(
        rx: settings.themeMode,
        builder: (context, currentTheme) => Obx(
          (context) {
            final theme = AppThemes.inst.getAppTheme(CurrentColor.inst.color, !context.isDarkMode);
            return Container(
              decoration: BoxDecoration(
                color: Color.alphaBlend(theme.listTileTheme.textColor!.withAlpha(200), Colors.white.withAlpha(160)),
                borderRadius: BorderRadius.circular(12.0.multipliedRadius),
                boxShadow: [
                  BoxShadow(color: theme.listTileTheme.iconColor!.withAlpha(80), spreadRadius: 1.0, blurRadius: widget.blurRadius, offset: const Offset(0, 2)),
                ],
              ),
              width: widget.maxWidth,
              padding: const EdgeInsets.symmetric(vertical: 5.0, horizontal: horizontalPaddingConst),
              child: Stack(
                children: [
                  Positioned.fill(
                    child: AnimatedAlign(
                      duration: const Duration(milliseconds: 400),
                      curve: Curves.fastLinearToSlowEaseIn,
                      alignment: _themeModeToAlignment(currentTheme),
                      child: Container(
                        width: bgSlideWidth,
                        decoration: BoxDecoration(
                          color: theme.colorScheme.surface.withAlpha(180),
                          borderRadius: BorderRadius.circular(brConst.multipliedRadius),
                          // boxShadow: [
                          //   BoxShadow(color: Colors.black.withAlpha(100), spreadRadius: 1, blurRadius: 4, offset: Offset(0, 2)),
                          // ],
                        ),
                      ),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(vertical: 0),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: [
                        ...ThemeMode.values.map(
                          (e) => SizedBox(
                            width: bgSlideWidth,
                            child: NamidaInkWell(
                              borderRadius: brConst,
                              padding: const EdgeInsets.symmetric(vertical: 2.0),
                              onTap: () => ToggleThemeModeContainer.onThemeChangeTap(e),
                              child: Icon(
                                e.toIcon(),
                                color: currentTheme == e ? theme.listTileTheme.iconColor : theme.colorScheme.surface.withAlpha(180),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            );
          },
        ),
      ),
    );
  }
}

class NamidaColorPickerDialog extends StatefulWidget {
  final String doneText;
  final VoidCallback? onRefreshButtonPressed;
  final ValueChanged<Color>? onColorChanged;
  final bool colorChangedDebouncer;
  final bool themeFollowsColor;
  final void Function(Color color) onDonePressed;
  final bool cancelButton;
  final Color initialColor;

  const NamidaColorPickerDialog({
    super.key,
    required this.doneText,
    this.onRefreshButtonPressed,
    this.onColorChanged,
    this.colorChangedDebouncer = false,
    this.themeFollowsColor = false,
    required this.onDonePressed,
    required this.cancelButton,
    required this.initialColor,
  });

  @override
  State<NamidaColorPickerDialog> createState() => _NamidaColorPickerDialogState();
}

class _NamidaColorPickerDialogState extends State<NamidaColorPickerDialog> {
  late Color _currentColor;
  Timer? colorChangedDebouncer;
  void _onColorChanged(Color color) {
    if (widget.themeFollowsColor) {
      setState(() => _currentColor = color);
    } else {
      _currentColor = color;
    }

    final onColorChanged = widget.onColorChanged;
    if (onColorChanged != null) {
      if (widget.colorChangedDebouncer) {
        colorChangedDebouncer?.cancel();
        colorChangedDebouncer = Timer(
          const Duration(milliseconds: 300),
          () => onColorChanged(color),
        );
      } else {
        onColorChanged(color);
      }
    }
  }

  @override
  void initState() {
    _currentColor = widget.initialColor;
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    final theme = widget.themeFollowsColor ? AppThemes.inst.getAppTheme(_currentColor) : context.theme;
    Widget pickerWidget = CustomBlurryDialog(
      actions: [
        if (widget.onRefreshButtonPressed != null)
          IconButton(
            icon: const Icon(Broken.refresh),
            tooltip: lang.restoreDefaults,
            onPressed: widget.onRefreshButtonPressed,
          ),
        if (widget.cancelButton) const CancelButton(),
        NamidaButton(
          text: widget.doneText,
          onTap: () => widget.onDonePressed(_currentColor),
        ),
      ],
      child: ColorPicker(
        color: _currentColor,
        onColorChanged: _onColorChanged,
        hasBorder: true,
        enableTonalPalette: true,
        enableOpacity: true,
        showMaterialName: false,
        showColorCode: true,
        colorCodeHasColor: true,
        focusedEditHasNoColor: true,
        showEditIconButton: false,
        editIcon: Broken.edit_2,
        wheelSquarePadding: 12.0,
        wheelDiameter: 224.0,
        borderRadius: 8.0.multipliedRadius,
        opacityThumbRadius: 16.0,
        opacityTrackHeight: 12.0,
        selectedPickerTypeColor: theme.colorScheme.secondary.withOpacityExt(0.4),
        pickersEnabled: {
          ColorPickerType.wheel: true,
          ColorPickerType.both: true,
          ColorPickerType.customSecondary: false,
          ColorPickerType.custom: false,
          ColorPickerType.primary: false,
          ColorPickerType.accent: false,
          ColorPickerType.bw: false,
        },
        pickerTypeTextStyle: theme.textTheme.displayMedium,
        colorNameTextStyle: theme.textTheme.displaySmall,
        materialNameTextStyle: theme.textTheme.displaySmall,
        colorCodePrefixStyle: theme.textTheme.displaySmall?.copyWith(fontWeight: FontWeight.w300),
        colorCodeTextStyle: theme.textTheme.displayMedium?.copyWith(fontWeight: FontWeight.w400),
        copyPasteBehavior: ColorPickerCopyPasteBehavior(
          copyFormat: ColorPickerCopyFormat.hexAARRGGBB,
          ctrlC: true,
          ctrlV: true,
          editFieldCopyButton: true,
          copyIcon: Broken.copy,
        ),
      ),
    );

    if (widget.themeFollowsColor) {
      pickerWidget = Theme(
        data: theme,
        child: pickerWidget,
      );
    }

    return pickerWidget;
  }
}
