import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hiddify/core/localization/translations.dart';
import 'package:hiddify/utils/utils.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class SettingsInputDialog<T> extends HookConsumerWidget with PresLogger {
  const SettingsInputDialog({
    super.key,
    required this.title,
    required this.initialValue,
    this.mapTo,
    this.validator,
    this.valueFormatter,
    this.onReset,
    this.optionalAction,
    this.icon,
    this.digitsOnly = false,
  });

  final String title;
  final T initialValue;
  final T? Function(String value)? mapTo;
  final bool Function(String value)? validator;
  final String Function(T value)? valueFormatter;
  final VoidCallback? onReset;
  final (String text, VoidCallback)? optionalAction;
  final IconData? icon;
  final bool digitsOnly;

  Future<T?> show(BuildContext context) async {
    return showDialog(
      context: context,
      useRootNavigator: true,
      builder: (context) => this,
    );
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final t = ref.watch(translationsProvider);
    final localizations = MaterialLocalizations.of(context);

    final textController = useTextEditingController(
      text: valueFormatter?.call(initialValue) ?? initialValue.toString(),
    );

    return FocusTraversalGroup(
      policy: OrderedTraversalPolicy(),
      child: AlertDialog(
        title: Text(title),
        icon: icon != null ? Icon(icon) : null,
        content: FocusTraversalOrder(
          order: const NumericFocusOrder(1),
          child: CustomTextFormField(
            controller: textController,
            inputFormatters: [
              FilteringTextInputFormatter.singleLineFormatter,
              if (digitsOnly) FilteringTextInputFormatter.digitsOnly,
            ],
            autoCorrect: true,
            hint: title,
          ),
        ),
        actions: [
          if (optionalAction != null)
            FocusTraversalOrder(
              order: const NumericFocusOrder(5),
              child: TextButton(
                onPressed: () async {
                  optionalAction!.$2();
                  await Navigator.of(context)
                      .maybePop(T == String ? textController.value.text : null);
                },
                child: Text(optionalAction!.$1.toUpperCase()),
              ),
            ),
          if (onReset != null)
            FocusTraversalOrder(
              order: const NumericFocusOrder(4),
              child: TextButton(
                onPressed: () async {
                  onReset!();
                  await Navigator.of(context).maybePop(null);
                },
                child: Text(t.general.reset.toUpperCase()),
              ),
            ),
          FocusTraversalOrder(
            order: const NumericFocusOrder(3),
            child: TextButton(
              onPressed: () async {
                await Navigator.of(context).maybePop();
              },
              child: Text(localizations.cancelButtonLabel.toUpperCase()),
            ),
          ),
          FocusTraversalOrder(
            order: const NumericFocusOrder(2),
            child: TextButton(
              onPressed: () async {
                if (validator?.call(textController.value.text) == false) {
                  await Navigator.of(context).maybePop(null);
                } else if (mapTo != null) {
                  await Navigator.of(context)
                      .maybePop(mapTo!.call(textController.value.text));
                } else {
                  await Navigator.of(context)
                      .maybePop(T == String ? textController.value.text : null);
                }
              },
              child: Text(localizations.okButtonLabel.toUpperCase()),
            ),
          ),
        ],
      ),
    );
  }
}

class SettingsPickerDialog<T> extends HookConsumerWidget with PresLogger {
  const SettingsPickerDialog({
    super.key,
    required this.title,
    required this.selected,
    required this.options,
    required this.getTitle,
    this.onReset,
  });

  final String title;
  final T selected;
  final List<T> options;
  final String Function(T e) getTitle;
  final VoidCallback? onReset;

  Future<T?> show(BuildContext context) async {
    return showDialog(
      context: context,
      useRootNavigator: true,
      builder: (context) => this,
    );
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final t = ref.watch(translationsProvider);
    final localizations = MaterialLocalizations.of(context);

    return AlertDialog(
      title: Text(title),
      content: Column(
        children: options
            .map(
              (e) => RadioListTile(
                title: Text(getTitle(e)),
                value: e,
                groupValue: selected,
                onChanged: (value) async {
                  await Navigator.of(context).maybePop(e);
                },
              ),
            )
            .toList(),
      ),
      actions: [
        if (onReset != null)
          TextButton(
            onPressed: () async {
              onReset!();
              await Navigator.of(context).maybePop(null);
            },
            child: Text(t.general.reset.toUpperCase()),
          ),
        TextButton(
          onPressed: () async {
            await Navigator.of(context).maybePop();
          },
          child: Text(localizations.cancelButtonLabel.toUpperCase()),
        ),
      ],
      scrollable: true,
    );
  }
}

class SettingsSliderDialog extends HookConsumerWidget with PresLogger {
  const SettingsSliderDialog({
    super.key,
    required this.title,
    required this.initialValue,
    this.onReset,
    this.min = 0,
    this.max = 1,
    this.divisions,
    this.labelGen,
  });

  final String title;
  final double initialValue;
  final VoidCallback? onReset;
  final double min;
  final double max;
  final int? divisions;
  final String Function(double value)? labelGen;

  Future<double?> show(BuildContext context) async {
    return showDialog(
      context: context,
      useRootNavigator: true,
      builder: (context) => this,
    );
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final t = ref.watch(translationsProvider);
    final localizations = MaterialLocalizations.of(context);

    final sliderValue = useState(initialValue);

    return AlertDialog(
      title: Text(title),
      content: IntrinsicHeight(
        child: Slider(
          value: sliderValue.value,
          min: min,
          max: max,
          divisions: divisions,
          onChanged: (value) => sliderValue.value = value,
          label: labelGen?.call(sliderValue.value),
        ),
      ),
      actions: [
        if (onReset != null)
          TextButton(
            onPressed: () async {
              onReset!();
              await Navigator.of(context).maybePop(null);
            },
            child: Text(t.general.reset.toUpperCase()),
          ),
        TextButton(
          onPressed: () async {
            await Navigator.of(context).maybePop();
          },
          child: Text(localizations.cancelButtonLabel.toUpperCase()),
        ),
        TextButton(
          onPressed: () async {
            await Navigator.of(context).maybePop(sliderValue.value);
          },
          child: Text(localizations.okButtonLabel.toUpperCase()),
        ),
      ],
    );
  }
}
