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

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

import 'package:fladder/models/book_model.dart';
import 'package:fladder/providers/book_viewer_provider.dart';
import 'package:fladder/providers/items/book_details_provider.dart';
import 'package:fladder/providers/settings/book_viewer_settings_provider.dart';
import 'package:fladder/screens/book_viewer/book_viewer_chapters.dart';
import 'package:fladder/screens/book_viewer/book_viewer_settings.dart';
import 'package:fladder/screens/shared/default_title_bar.dart';
import 'package:fladder/screens/shared/fladder_snackbar.dart';
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
import 'package:fladder/util/input_handler.dart';
import 'package:fladder/util/localization_helper.dart';
import 'package:fladder/util/throttler.dart';
import 'package:fladder/widgets/shared/fladder_slider.dart';

class BookViewController {
  bool controlsVisible = true;

  late ValueNotifier<bool> visibilityChanged = ValueNotifier(controlsVisible);

  void toggleControls({bool? value}) {
    controlsVisible = value ?? !controlsVisible;
    visibilityChanged.value = controlsVisible;
  }
}

class BookViewerControls extends ConsumerStatefulWidget {
  final AutoDisposeStateNotifierProvider<BookDetailsProviderNotifier, BookProviderModel> provider;
  final BookViewController viewController;

  final ExtendedPageController controller;
  const BookViewerControls({
    required this.provider,
    required this.controller,
    required this.viewController,
    super.key,
  });

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

class _BookViewerControlsState extends ConsumerState<BookViewerControls> {
  final Throttler throttler = Throttler(duration: const Duration(milliseconds: 130));
  final Duration pageAnimDuration = const Duration(milliseconds: 125);
  final Curve pageAnimCurve = Curves.easeInCubic;
  late final BookViewController viewController = widget.viewController;

  late final double topPadding = MediaQuery.of(context).viewPadding.top;
  late final double bottomPadding = MediaQuery.of(context).viewPadding.bottom;

  bool showControls = true;
  void toggleControls({bool? value}) {
    setState(() {
      showControls = value ?? !showControls;
    });
    SystemChrome.setEnabledSystemUIMode(!showControls ? SystemUiMode.leanBack : SystemUiMode.edgeToEdge, overlays: []);
    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
      statusBarColor: Colors.transparent,
      systemNavigationBarColor: Colors.transparent,
      systemNavigationBarDividerColor: Colors.transparent,
    ));
  }

  @override
  void initState() {
    super.initState();
    WakelockPlus.enable();
    viewController.visibilityChanged.addListener(() {
      toggleControls(value: viewController.controlsVisible);
    });
  }

  @override
  void dispose() {
    WakelockPlus.disable();
    ScreenBrightness().resetApplicationScreenBrightness();
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge, overlays: []);
    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
      statusBarColor: Colors.transparent,
      systemNavigationBarColor: Colors.transparent,
      systemNavigationBarDividerColor: Colors.transparent,
    ));
    super.dispose();
  }

  bool _onKey(KeyEvent value) {
    final bookViewerSettings = ref.read(bookViewerSettingsProvider);
    if (value is KeyRepeatEvent) {
      if (value.logicalKey == LogicalKeyboardKey.arrowLeft || value.logicalKey == LogicalKeyboardKey.keyA) {
        bookViewerSettings.readDirection == ReadDirection.leftToRight ? previousPage() : nextPage();
        return true;
      }
      if (value.logicalKey == LogicalKeyboardKey.arrowRight || value.logicalKey == LogicalKeyboardKey.keyD) {
        bookViewerSettings.readDirection == ReadDirection.leftToRight ? nextPage() : previousPage();
        return true;
      }
    }
    if (value is KeyDownEvent) {
      if (value.logicalKey == LogicalKeyboardKey.arrowLeft || value.logicalKey == LogicalKeyboardKey.keyA) {
        bookViewerSettings.readDirection == ReadDirection.leftToRight ? previousPage() : nextPage();
        return true;
      }
      if (value.logicalKey == LogicalKeyboardKey.arrowRight || value.logicalKey == LogicalKeyboardKey.keyD) {
        bookViewerSettings.readDirection == ReadDirection.leftToRight ? nextPage() : previousPage();
        return true;
      }
      if (value.logicalKey == LogicalKeyboardKey.keyF) {
        toggleControls();
        return true;
      }
    }
    return false;
  }

  @override
  Widget build(BuildContext context) {
    final details = ref.watch(widget.provider);
    final bookViewerSettings = ref.watch(bookViewerSettingsProvider);
    final chapters = details.chapters;
    final bookViewerDetails = ref.watch(bookViewerProvider);
    final currentPage = bookViewerDetails.currentPage;
    const overlayColor = Colors.black;
    final previousChapter = details.previousChapter(bookViewerDetails.book);
    final nextChapter = details.nextChapter(bookViewerDetails.book);

    final double leftPadding = MediaQuery.of(context).viewPadding.left;
    final double rightPadding = MediaQuery.of(context).viewPadding.right;

    return InputHandler(
      onKeyEvent: (node, event) => _onKey(event) ? KeyEventResult.handled : KeyEventResult.ignored,
      child: Stack(
        children: [
          IgnorePointer(
            ignoring: !showControls,
            child: AnimatedOpacity(
              duration: const Duration(milliseconds: 500),
              opacity: showControls ? 1 : 0,
              child: Stack(
                children: [
                  Container(
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        begin: Alignment.topCenter,
                        end: Alignment.bottomCenter,
                        colors: [
                          overlayColor.withValues(alpha: 1),
                          overlayColor.withValues(alpha: 0.65),
                          overlayColor.withValues(alpha: 0),
                        ],
                      ),
                    ),
                    child: Padding(
                      padding:
                          EdgeInsets.only(top: topPadding, left: leftPadding, right: rightPadding).copyWith(bottom: 8),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          if (AdaptiveLayout.of(context).isDesktop)
                            const Flexible(
                              child: DefaultTitleBar(
                                height: 50,
                                brightness: Brightness.dark,
                              ),
                            ),
                          Row(
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: [
                              const BackButton(),
                              const SizedBox(
                                width: 16,
                              ),
                              Flexible(
                                child: Text(
                                  bookViewerDetails.book?.name ?? "None",
                                  style: Theme.of(context).textTheme.titleLarge,
                                ),
                              )
                            ],
                          ),
                          const SizedBox(height: 16),
                        ],
                      ),
                    ),
                  ),
                  if (!bookViewerDetails.loading) ...{
                    if (bookViewerDetails.book != null && bookViewerDetails.pages.isNotEmpty) ...{
                      Align(
                        alignment: Alignment.bottomCenter,
                        child: Container(
                          decoration: BoxDecoration(
                            gradient: LinearGradient(
                              begin: Alignment.topCenter,
                              end: Alignment.bottomCenter,
                              colors: [
                                overlayColor.withValues(alpha: 0),
                                overlayColor.withValues(alpha: 0.65),
                                overlayColor.withValues(alpha: 1),
                              ],
                            ),
                          ),
                          child: Padding(
                            padding: EdgeInsets.only(
                              bottom: bottomPadding,
                              left: leftPadding,
                              right: rightPadding,
                            ).copyWith(
                              top: 16,
                              bottom: 16,
                            ),
                            child: Column(
                              mainAxisSize: MainAxisSize.min,
                              children: [
                                const SizedBox(height: 30),
                                Row(
                                  children: [
                                    const SizedBox(width: 8),
                                    Tooltip(
                                      message: bookViewerSettings.readDirection == ReadDirection.leftToRight
                                          ? previousChapter?.name != null
                                              ? "Load ${previousChapter?.name}"
                                              : ""
                                          : nextChapter?.name != null
                                              ? "Load ${nextChapter?.name}"
                                              : "",
                                      child: IconButton.filled(
                                        onPressed: bookViewerSettings.readDirection == ReadDirection.leftToRight
                                            ? previousChapter != null
                                                ? () async => await loadNextBook(previousChapter)
                                                : null
                                            : nextChapter != null
                                                ? () async => await loadNextBook(nextChapter)
                                                : null,
                                        icon: const Icon(IconsaxPlusLinear.backward),
                                      ),
                                    ),
                                    const SizedBox(width: 8),
                                    Flexible(
                                      child: Container(
                                        decoration: BoxDecoration(
                                          color: Colors.black.withValues(alpha: 0.7),
                                          borderRadius: BorderRadius.circular(60),
                                        ),
                                        child: Padding(
                                          padding: const EdgeInsets.symmetric(horizontal: 24),
                                          child: Row(
                                            children: [
                                              if (bookViewerSettings.readDirection == ReadDirection.leftToRight)
                                                ...controls(currentPage, bookViewerSettings, bookViewerDetails)
                                              else
                                                ...controls(currentPage, bookViewerSettings, bookViewerDetails)
                                                    .reversed,
                                            ],
                                          ),
                                        ),
                                      ),
                                    ),
                                    const SizedBox(width: 8),
                                    Tooltip(
                                      message: bookViewerSettings.readDirection == ReadDirection.leftToRight
                                          ? nextChapter?.name != null
                                              ? "Load ${nextChapter?.name}"
                                              : ""
                                          : previousChapter?.name != null
                                              ? "Load ${previousChapter?.name}"
                                              : "",
                                      child: IconButton.filled(
                                        onPressed: bookViewerSettings.readDirection == ReadDirection.leftToRight
                                            ? nextChapter != null
                                                ? () async => await loadNextBook(nextChapter)
                                                : null
                                            : previousChapter != null
                                                ? () async => await loadNextBook(previousChapter)
                                                : null,
                                        icon: const Icon(IconsaxPlusLinear.forward),
                                      ),
                                    ),
                                    const SizedBox(width: 8),
                                  ],
                                ),
                                const SizedBox(height: 16),
                                Row(
                                  mainAxisSize: MainAxisSize.max,
                                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                  children: [
                                    Transform.flip(
                                      flipX: bookViewerSettings.readDirection == ReadDirection.rightToLeft,
                                      child: IconButton(
                                          onPressed: () => widget.controller
                                              .animateToPage(1, duration: pageAnimDuration, curve: pageAnimCurve),
                                          icon: const Icon(IconsaxPlusLinear.backward)),
                                    ),
                                    IconButton(
                                      onPressed: () {
                                        showBookViewerSettings(context);
                                      },
                                      icon: const Icon(IconsaxPlusLinear.setting_2),
                                    ),
                                    IconButton(
                                      onPressed: chapters.length > 1
                                          ? () {
                                              showBookViewerChapters(
                                                context,
                                                widget.provider,
                                                onPressed: (book) async {
                                                  Navigator.of(context).pop();
                                                  loadNextBook(book);
                                                },
                                              );
                                            }
                                          : () => fladderSnackbar(context, title: "No other chapters"),
                                      icon: const Icon(IconsaxPlusLinear.bookmark_2),
                                    )
                                  ],
                                ),
                              ],
                            ),
                          ),
                        ),
                      ),
                    } else
                      const Center(
                        child: Card(
                          child: Padding(
                            padding: EdgeInsets.all(8.0),
                            child: Row(
                              mainAxisSize: MainAxisSize.min,
                              children: [
                                Icon(Icons.menu_book_rounded),
                                SizedBox(width: 8),
                                Text("Unable to load book"),
                              ],
                            ),
                          ),
                        ),
                      )
                  },
                ],
              ),
            ),
          ),
          if (bookViewerDetails.loading)
            Center(
              child: Card(
                child: Padding(
                  padding: const EdgeInsets.all(16),
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      if (bookViewerDetails.book != null) ...{
                        Flexible(
                          child: Text("${context.localized.loading} ${bookViewerDetails.book?.name}",
                              style: Theme.of(context).textTheme.titleMedium),
                        ),
                        const SizedBox(width: 16),
                      },
                      const CircularProgressIndicator.adaptive(strokeCap: StrokeCap.round),
                    ],
                  ),
                ),
              ),
            )
        ],
      ),
    );
  }

  List<Widget> controls(int currentPage, BookViewerSettingsModel bookViewerSettings, BookViewerModel details) {
    final clampedCurrentPage = currentPage.clamp(1, details.pages.length);
    return [
      const SizedBox(width: 6),
      Text(
        (currentPage.clamp(1, details.pages.length)).toInt().toString().padLeft(1).padRight(1),
        style: Theme.of(context).textTheme.titleMedium,
      ),
      Flexible(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 12),
          child: Transform.flip(
            flipX: bookViewerSettings.readDirection == ReadDirection.rightToLeft,
            child: SizedBox(
              height: 40,
              child: FladderSlider(
                value: clampedCurrentPage.toDouble(),
                divisions: details.pages.length - 1,
                min: 1,
                max: details.pages.length.toDouble(),
                onChangeEnd: (value) => widget.controller.jumpToPage(value.toInt()),
                onChanged: (value) => ref.read(bookViewerProvider.notifier).setPage(value),
              ),
            ),
          ),
        ),
      ),
      Text(
        details.pages.length.toString().padLeft(1).padRight(1),
        style: Theme.of(context).textTheme.titleMedium,
      ),
    ];
  }

  Future<void> loadNextBook(BookModel? book) async {
    await ref.read(bookViewerProvider.notifier).fetchBook(book);
    widget.controller.jumpToPage(0);
    return;
  }

  Future<void> nextPage() async =>
      throttler.run(() async => await widget.controller.nextPage(duration: pageAnimDuration, curve: pageAnimCurve));

  Future<void> previousPage() async =>
      throttler.run(() async => await widget.controller.previousPage(duration: pageAnimDuration, curve: pageAnimCurve));
}
