import 'dart:io';

import 'package:flutter/material.dart';

import 'package:modern_titlebar_buttons/modern_titlebar_buttons.dart';
import 'package:window_manager/window_manager.dart';

import 'package:namida/class/route.dart';
import 'package:namida/controller/miniplayer_controller.dart';
import 'package:namida/controller/navigator_controller.dart';
import 'package:namida/controller/platform/namida_channel/namida_channel.dart';
import 'package:namida/controller/player_controller.dart';
import 'package:namida/controller/scroll_search_controller.dart';
import 'package:namida/controller/settings_controller.dart';
import 'package:namida/controller/shortcuts_controller.dart';
import 'package:namida/controller/window_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/functions.dart';
import 'package:namida/core/icon_fonts/broken_icons.dart';
import 'package:namida/core/namida_converter_ext.dart';
import 'package:namida/core/translations/language.dart';
import 'package:namida/core/utils.dart';
import 'package:namida/packages/miniplayer.dart';
import 'package:namida/ui/pages/about_page.dart';
import 'package:namida/ui/pages/main_page.dart';
import 'package:namida/ui/pages/settings_page.dart';
import 'package:namida/ui/widgets/custom_widgets.dart';
import 'package:namida/ui/widgets/inner_drawer.dart';
import 'package:namida/ui/widgets/selected_tracks_preview.dart';
import 'package:namida/ui/widgets/settings/customization_settings.dart';
import 'package:namida/ui/widgets/settings/indexer_settings.dart';
import 'package:namida/ui/widgets/settings/theme_settings.dart';

class MainPageWrapper extends StatefulWidget {
  const MainPageWrapper({super.key});

  @override
  State<MainPageWrapper> createState() => _MainPageWrapperState();
}

class _MainPageWrapperState extends State<MainPageWrapper> with TickerProviderStateMixin {
  late AnimationController animation;

  @override
  void initState() {
    super.initState();
    animation = MiniPlayerController.inst.initialize(this);
    MiniPlayerController.inst.updateScreenValuesInitial();
    MiniPlayerController.inst.initializeSAnim(this);
    Player.inst.currentItem.addListener(_currentItemListener);
  }

  @override
  void dispose() {
    Player.inst.currentItem.removeListener(_currentItemListener);
    super.dispose();
  }

  // -- to fix black ui when nothing is playing
  bool? _isCurrentItemNull;
  void _currentItemListener() {
    final isItemNull = Player.inst.currentItem.value == null;
    if (isItemNull != _isCurrentItemNull) {
      _isCurrentItemNull = isItemNull;
      if (mounted) setState(() {}); // update mp values
    }
  }

  @override
  Widget build(BuildContext context) {
    return NamidaInnerDrawer(
      key: NamidaNavigator.inst.innerDrawerKey,
      borderRadius: 42.0.multipliedRadius,
      drawerChild: const NamidaDrawer(),
      maxPercentage: 194.0 / context.width,
      initiallySwipeable: settings.swipeableDrawer.value,
      child: MainScreenStack(
        animation: animation,
      ),
    );
  }
}

class MainScreenStack extends StatelessWidget {
  final Animation<double> animation;
  const MainScreenStack({super.key, required this.animation});

  @override
  Widget build(BuildContext context) {
    MiniPlayerController.inst.updateScreenValues(context); // for updating after split screen & landscape values.

    final miniplayerMaxWidth = Dimensions.inst.miniplayerMaxWidth;
    final miniplayerIsWideScreen = Dimensions.inst.miniplayerIsWideScreen;

    final selectedTracksWidget = SelectedTracksPreviewContainer(
      animation: animation,
      isMiniplayerAlwaysVisible: miniplayerIsWideScreen,
    );

    // -- do not create MainPage twice as it will cause duplication issues
    return Stack(
      alignment: Alignment.bottomCenter,
      children: [
        Padding(
          padding: !miniplayerIsWideScreen ? EdgeInsets.zero : EdgeInsets.only(right: miniplayerMaxWidth),
          child: MediaQuery.removePadding(
            context: context,
            removeRight: miniplayerIsWideScreen,
            child: Stack(
              alignment: Alignment.bottomCenter,
              children: [
                MainPage(
                  animation: animation,
                  isMiniplayerAlwaysVisible: miniplayerIsWideScreen,
                ),
                if (miniplayerIsWideScreen) selectedTracksWidget,
              ],
            ),
          ),
        ),
        RepaintBoundary(
          child: Padding(
            padding: !miniplayerIsWideScreen ? EdgeInsets.zero : EdgeInsets.only(left: Dimensions.inst.availableAppContentWidthContext(context)),
            child: MediaQuery.removePadding(
              context: context,
              removeLeft: miniplayerIsWideScreen,
              child: SafeArea(
                top: false,
                bottom: false,
                child: MiniPlayerParent(animation: animation),
              ),
            ),
          ),
        ),
        if (!miniplayerIsWideScreen) selectedTracksWidget,
      ],
    );
  }
}

class NamidaDrawer extends StatelessWidget {
  const NamidaDrawer({super.key});

  void toggleDrawer() => NamidaNavigator.inst.toggleDrawer();

  static void openSleepTimerDialog(BuildContext context) {
    final textTheme = context.textTheme;

    final initialSleepConfig = Player.inst.sleepTimerConfig.value;
    final minutesRx = initialSleepConfig.sleepAfterMin.obs;
    final tracksRx = initialSleepConfig.sleepAfterItems.obs;
    final hasInitialValues = initialSleepConfig.sleepAfterMin > 0 || initialSleepConfig.sleepAfterItems > 0;

    NamidaNavigator.inst.navigateDialog(
      onDisposing: () {
        minutesRx.close();
        tracksRx.close();
      },
      dialog: CustomBlurryDialog(
        title: lang.sleepAfter,
        icon: Broken.timer_1,
        normalTitleStyle: true,
        actions: [
          const CancelButton(),
          if (hasInitialValues)
            ObxO(
              rx: Player.inst.sleepTimerConfig,
              builder: (context, currentConfig) {
                return NamidaButton(
                  enabled: currentConfig.enableSleepAfterMins || currentConfig.enableSleepAfterItems,
                  icon: Broken.timer_pause,
                  text: lang.stop,
                  onTap: () {
                    Player.inst.resetSleepAfterTimer();
                    NamidaNavigator.inst.closeDialog();
                  },
                );
              },
            ),
          ObxO(
            rx: Player.inst.sleepTimerConfig,
            builder: (context, currentConfig) {
              return Obx(
                (context) => NamidaButton(
                  enabled: (minutesRx.valueR > 0 || tracksRx.valueR > 0) && (currentConfig.sleepAfterItems != tracksRx.value || currentConfig.sleepAfterMin != minutesRx.value),
                  icon: Broken.timer_start,
                  text: hasInitialValues ? lang.update : lang.start,
                  onTap: () {
                    if (minutesRx.value > 0 || tracksRx.value > 0) {
                      Player.inst.updateSleepTimerValues(
                        enableSleepAfterMins: minutesRx.value > 0,
                        enableSleepAfterItems: tracksRx.value > 0,
                        sleepAfterMin: minutesRx.value,
                        sleepAfterItems: tracksRx.value,
                      );
                    }
                    NamidaNavigator.inst.closeDialog();
                  },
                ),
              );
            },
          ),
        ],
        child: Column(
          children: [
            const SizedBox(
              height: 32.0,
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Obx(
                  (context) => NamidaWheelSlider(
                    max: 180,
                    initValue: minutesRx.valueR,
                    onValueChanged: (val) => minutesRx.value = val,
                    text: "${minutesRx.valueR}m",
                    topText: lang.minutes.capitalizeFirst(),
                    textPadding: 8.0,
                  ),
                ),
                Text(
                  lang.or,
                  style: textTheme.displayMedium,
                ),
                ObxO(
                  rx: tracksRx,
                  builder: (context, trs) => NamidaWheelSlider(
                    max: kMaximumSleepTimerTracks,
                    initValue: trs,
                    onValueChanged: (val) => tracksRx.value = val,
                    text: lang.countTracks(count: trs),
                    topText: lang.tracks,
                    textPadding: 8.0,
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final showLogoInDrawer = WindowController.instance?.usingCustomWindowTitleBar != true;
    return SafeArea(
      child: Column(
        children: [
          Expanded(
            child: SuperSmoothListView(
              children: [
                if (showLogoInDrawer)
                  NamidaLogoContainer(
                    afterTap: NamidaNavigator.inst.toggleDrawer,
                  ),
                const NamidaContainerDivider(width: 42.0, margin: EdgeInsets.all(10.0)),
                ...LibraryTab.values
                    .where((element) => element != LibraryTab.search)
                    .map(
                      (e) => ObxO(
                        rx: settings.extra.selectedLibraryTab,
                        builder: (context, selectedLibraryTab) => NamidaDrawerListTile(
                          enabled: selectedLibraryTab == e,
                          title: e.toText(),
                          icon: e.toIcon(),
                          onTap: () async {
                            ScrollSearchController.inst.animatePageController(e);
                            toggleDrawer();
                          },
                        ),
                      ),
                    ),
              ],
            ),
          ),
          const SizedBox(height: 12.0),
          Material(
            borderRadius: BorderRadius.circular(12.0.multipliedRadius),
            child: LayoutBuilder(
              builder: (context, constraints) {
                return ToggleThemeModeContainer(
                  maxWidth: constraints.maxWidth * 0.9,
                  blurRadius: 3.0,
                );
              },
            ),
          ),
          const SizedBox(height: 6.0),
          NamidaDrawerListTile(
            margin: const EdgeInsets.symmetric(horizontal: 12.0),
            enabled: false,
            title: lang.sleepTimer,
            icon: Broken.timer_1,
            onTap: () {
              toggleDrawer();
              openSleepTimerDialog(context);
            },
          ),
          const SizedBox(height: 6.0),
          Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              const SizedBox(width: 12.0),
              Expanded(
                child: NamidaDrawerListTile(
                  margin: EdgeInsets.zero,
                  padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 6.0),
                  enabled: false,
                  isCentered: true,
                  iconSize: 24.0,
                  title: '',
                  icon: Broken.brush_1,
                  onTap: () {
                    SettingsSubPage(
                      title: () => lang.customizations,
                      child: const CustomizationSettings(),
                    ).navigate();

                    toggleDrawer();
                  },
                ),
              ),
              const SizedBox(width: 6.0),
              Expanded(
                child: NamidaDrawerListTile(
                  margin: EdgeInsets.zero,
                  padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 6.0),
                  enabled: false,
                  isCentered: true,
                  iconSize: 24.0,
                  title: '',
                  icon: Broken.setting,
                  onTap: () {
                    const SettingsPage().navigate();
                    toggleDrawer();
                  },
                ),
              ),
              const SizedBox(width: 12.0),
            ],
          ),
          const SizedBox(height: 6.0),
          const SizedBox(height: 8.0),
        ],
      ),
    );
  }
}

class WrapWithWindowGoodies extends StatelessWidget {
  final Widget child;
  const WrapWithWindowGoodies({super.key, required this.child});

  @override
  Widget build(BuildContext context) {
    Widget child = ObxO(
      rx: settings.desktopTitlebar,
      builder: (context, show) => Column(
        children: [
          if (show) const NamidaDesktopAppBar(),
          Expanded(
            child: this.child,
          ),
        ],
      ),
    );
    final addRoundedCorners = WindowController.instance?.customRoundedCorners == true;
    if (addRoundedCorners) {
      final borderRadius = BorderRadiusGeometry.circular(8.0.multipliedRadius);
      child = BorderRadiusClip(
        borderRadius: borderRadius,
        child: DecoratedBox(
          position: DecorationPosition.foreground,
          decoration: BoxDecoration(
            borderRadius: borderRadius,
            border: Border.all(
              width: 1.0,
              color: const Color.fromARGB(200, 60, 60, 60),
            ),
          ),
          child: child,
        ),
      );
    }

    return child;
  }
}

class NamidaDesktopAppBar extends StatefulWidget {
  const NamidaDesktopAppBar({super.key});

  @override
  State<NamidaDesktopAppBar> createState() => NamidaDesktopAppBarState();
}

class NamidaDesktopAppBarState extends State<NamidaDesktopAppBar> with WindowListener {
  @override
  void initState() {
    windowManager.addListener(this);
    super.initState();
  }

  @override
  void dispose() {
    windowManager.removeListener(this);
    super.dispose();
  }

  @override
  void onWindowMaximize() {
    setState(() {});
  }

  @override
  void onWindowUnmaximize() {
    setState(() {});
  }

  @override
  void onWindowFocus() {
    // setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    final title = 'Namida';
    final height = WindowController.instance?.windowTitleBarHeightIfActive;

    final appBarTheme = AppBarTheme.of(context);
    final theme = context.theme;
    final textTheme = theme.textTheme;
    final colorscheme = theme.colorScheme;
    final brightness = theme.brightness;
    final buttonHeight = (height ?? 24.0) * 0.75;
    final buttonWidth = Platform.isWindows ? 42.0 : 18.0;
    // final backgroundColor = Color.alphaBlend(context.theme.scaffoldBackgroundColor, Colors.white.withOpacityExt(0.25));
    final backgroundColor = appBarTheme.backgroundColor ?? colorscheme.surface;
    final surfaceTintColor = appBarTheme.surfaceTintColor ?? colorscheme.surfaceTint;
    final logoImgPath = NamidaChannel.defaultLayerIconForPlatform;
    final logoBgColor = context.isDarkMode ? const Color(0x40262729) : const Color(0x063c3f46);
    final logoColor = context.isDarkMode
        ? Color.alphaBlend(theme.colorScheme.secondary.withOpacityExt(0.5), const Color.fromARGB(240, 230, 230, 230))
        : Color.alphaBlend(theme.colorScheme.secondary.withOpacityExt(0.5), const Color.fromARGB(220, 16, 16, 16));
    final logoTextColor = logoColor.withOpacityExt(0.7);

    final buttonsRow = Platform.isWindows
        ? Row(
            mainAxisAlignment: MainAxisAlignment.end,
            mainAxisSize: MainAxisSize.min,
            children: [
              SizedBox(
                width: buttonWidth * 0.95,
                child: WindowCaptionButton.minimize(
                  brightness: brightness,
                  onPressed: () async {
                    final isMinimized = await windowManager.isMinimized();
                    if (isMinimized) {
                      windowManager.restore();
                    } else {
                      windowManager.minimize();
                    }
                  },
                ),
              ),
              SizedBox(
                width: buttonWidth * 0.95,
                child: FutureBuilder<bool>(
                  future: windowManager.isMaximized(),
                  builder: (context, snapshot) {
                    if (snapshot.data == true) {
                      return WindowCaptionButton.unmaximize(
                        brightness: brightness,
                        onPressed: windowManager.unmaximize,
                      );
                    }
                    return WindowCaptionButton.maximize(
                      brightness: brightness,
                      onPressed: windowManager.maximize,
                    );
                  },
                ),
              ),
              SizedBox(
                width: buttonWidth,
                child: WindowCaptionButton.close(
                  brightness: brightness,
                  onPressed: () async {
                    await windowManager.close().ignoreError();
                  },
                ),
              ),
            ],
          )
        : ObxO(
            rx: settings.desktopTitlebarType,
            builder: (context, buttonsTypePre) {
              final buttonsType = buttonsTypePre.toThemeType();
              if (buttonsType == null) return const SizedBox();
              return Row(
                mainAxisAlignment: MainAxisAlignment.end,
                mainAxisSize: MainAxisSize.min,
                children: [
                  DecoratedMinimizeButton(
                    width: buttonWidth,
                    height: buttonHeight,
                    type: buttonsType,
                    onPressed: () async {
                      bool isMinimized = await windowManager.isMinimized();
                      if (isMinimized) {
                        windowManager.restore();
                      } else {
                        windowManager.minimize();
                      }
                    },
                  ),
                  DecoratedMaximizeButton(
                    width: buttonWidth,
                    height: buttonHeight,
                    type: buttonsType,
                    onPressed: () async {
                      final isMaximized = await windowManager.isMaximized();
                      if (isMaximized) {
                        await windowManager.unmaximize();
                      } else {
                        await windowManager.maximize();
                      }
                    },
                  ),
                  DecoratedCloseButton(
                    width: buttonWidth,
                    height: buttonHeight,
                    type: buttonsType,
                    onPressed: () async {
                      await windowManager.close().ignoreError();
                    },
                  ),
                ],
              );
            },
          );
    return SizedBox(
      height: height,
      child: Material(
        shadowColor: Colors.transparent,
        type: MaterialType.canvas,
        color: backgroundColor,
        surfaceTintColor: surfaceTintColor,
        child: Stack(
          children: [
            Positioned.fill(
              child: GestureDetector(
                behavior: HitTestBehavior.translucent,
                onPanStart: (_) => windowManager.startDragging(),
                onSecondaryTap: windowManager.popUpWindowMenu,
                onDoubleTap: () async {
                  bool isMaximized = await windowManager.isMaximized();
                  if (!isMaximized) {
                    windowManager.maximize();
                  } else {
                    windowManager.unmaximize();
                  }
                },
                child: const SizedBox(),
              ),
            ),
            Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Expanded(
                  child: SizedBox(
                    height: double.infinity,
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        Flexible(
                          child: GestureDetector(
                            behavior: HitTestBehavior.translucent,
                            onPanStart: (_) => windowManager.startDragging(),
                            child: NamidaInkWell(
                              onTap: () {
                                if (NamidaNavigator.inst.currentRoute?.route != RouteType.PAGE_about) {
                                  const AboutPage().navigate();
                                }
                              },
                              height: height,
                              animationDurationMS: 200,
                              decoration: BoxDecoration(
                                color: logoBgColor,
                                borderRadius: const BorderRadius.only(
                                  bottomRight: Radius.circular(8.0),
                                ),
                              ),
                              child: Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  const SizedBox(width: 6.0),
                                  Flexible(
                                    child: Image.asset(
                                      logoImgPath,
                                      width: 22.0,
                                      height: 22.0,
                                      cacheHeight: 240,
                                      cacheWidth: 240,
                                      color: logoColor,
                                      alignment: Alignment.center,
                                    ),
                                  ),
                                  const SizedBox(width: 4.0),
                                  Flexible(
                                    child: Text(
                                      title,
                                      style: textTheme.displayMedium?.copyWith(
                                        color: logoTextColor,
                                        fontSize: 14.0,
                                      ),
                                      overflow: TextOverflow.fade,
                                      softWrap: false,
                                    ),
                                  ),
                                  const SizedBox(width: 6.0),
                                  const SizedBox(width: 4.0),
                                ],
                              ),
                            ),
                          ),
                        ),
                        Flexible(
                          child: FittedBox(
                            fit: BoxFit.scaleDown,
                            child: SizedBox(
                              height: height,
                              child: Row(
                                crossAxisAlignment: CrossAxisAlignment.center,
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  SizedBox(width: 2.0),
                                  // -- dont try to hide based on rail bar or widescreen, its not reactive here and would look a bit bad
                                  _DesktopShortcutIcon(
                                    type: _DesktopShortcutActionType.opensRoute,
                                    tooltip: lang.home,
                                    icon: Broken.home_1,
                                    onTap: () => ScrollSearchController.inst.animatePageController(LibraryTab.home),
                                  ),
                                  _DesktopShortcutIcon(
                                    type: _DesktopShortcutActionType.performsAction,
                                    tooltip: lang.queue,
                                    icon: Broken.row_vertical,
                                    size: _DesktopShortcutIcon.iconSize * 0.85,
                                    onTap: ShortcutsController.instance?.openPlayerQueue,
                                  ),
                                  _DesktopShortcutIcon(
                                    type: _DesktopShortcutActionType.opensRoute,
                                    tooltip: lang.soundControl,
                                    icon: Broken.sound,
                                    onTap: NamidaOnTaps.inst.openSoundControl,
                                  ),
                                  _DesktopShortcutIcon(
                                    type: _DesktopShortcutActionType.opensDialog,
                                    tooltip: lang.refreshLibrary,
                                    icon: Broken.refresh_2,
                                    onTap: () => showRefreshPromptDialog(false, allowBypassing: true),
                                    child: RefreshLibraryIcon(
                                      widgetKey: 'desktop_appbar',
                                      color: _DesktopShortcutIcon.getColor(context),
                                      size: _DesktopShortcutIcon.iconSize,
                                    ),
                                  ),
                                  _DesktopShortcutIcon(
                                    type: _DesktopShortcutActionType.opensDialog,
                                    tooltip: lang.shortcuts,
                                    icon: Broken.flash_1,
                                    onTap: () => AboutPage.showShortcutsDialog(context),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
                buttonsRow,
              ],
            ),
            // -- juust slight dim
            Positioned.fill(
              child: IgnorePointer(
                child: ColoredBox(
                  color: backgroundColor.withOpacityExt(0.1),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

enum _DesktopShortcutActionType {
  opensRoute,
  opensDialog,
  performsAction,
}

class _DesktopShortcutIcon extends StatelessWidget {
  final String tooltip;
  final IconData icon;
  final double? size;
  final _DesktopShortcutActionType type;
  final VoidCallback? onTap;
  final Widget? child;

  const _DesktopShortcutIcon({
    required this.tooltip,
    required this.icon,
    this.size,
    required this.type,
    this.onTap,
    this.child,
  });

  static Color getColor(BuildContext context) {
    return context.theme.colorScheme.secondary.withOpacityExt(0.8);
  }

  static const double iconSize = 15.0;

  @override
  Widget build(BuildContext context) {
    return NamidaTooltip(
      message: () => tooltip,
      preferBelow: true,
      child: NamidaInkWell(
        onTap: () {
          // -- prevent executing actions over and over
          switch (type) {
            case _DesktopShortcutActionType.opensRoute:
              if (NamidaNavigator.inst.rootNavHasOpenedPages) return;
            case _DesktopShortcutActionType.opensDialog:
              if (NamidaNavigator.inst.openedDialogsCount > 0) return;
            case _DesktopShortcutActionType.performsAction:
            // -- allow
          }

          onTap?.call();
        },
        borderRadius: 99.0,
        alignment: Alignment.center,
        height: iconSize * 1.6,
        width: iconSize * 1.6,
        child:
            child ??
            Icon(
              icon,
              size: size ?? iconSize,
              color: getColor(context),
            ),
      ),
    );
  }
}
