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

import '../../../data/models/payment_cubit.dart';
import '../../../data/models/payment_state.dart';
import '../../../data/models/transaction_cubit.dart';
import '../../logger.dart';
import '../../pay_helper.dart';
import '../../tutorial_keys.dart';
import '../../ui_helpers.dart';
import 'g1_textfield.dart';

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

  @override
  State<PayForm> createState() => _PayFormState();
}

class _PayFormState extends State<PayForm> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final GlobalKey<FormFieldState<String>> _formCommentKey =
  GlobalKey<FormFieldState<String>>();
  final TextEditingController _commentController = TextEditingController();
  final ValueNotifier<String> _feedbackNotifier = ValueNotifier<String>('');

  @override
  void dispose() {
    _commentController.dispose();
    _feedbackNotifier.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<PaymentCubit, PaymentState>(
        builder: (BuildContext context, PaymentState state) {
          if (state.comment != null &&
              _commentController.text != state.comment) {
            _commentController.text = state.comment;
          }

          if (state.amount == null || state.amount == 0) {
            _feedbackNotifier.value = '';
          }
          final bool sentDisabled = _onPressed(state, context) == null;
          final Color sentColor =
          sentDisabled ? Colors.grey : Theme
              .of(context)
              .primaryColor;
          return Form(
            key: _formKey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                const SizedBox(height: 10.0),
                G1PayAmountField(key: payAmountKey),
                const SizedBox(height: 10.0),
                Row(children: <Widget>[
                  Expanded(
                      child: TextFormField(
                        key: _formCommentKey,
                        inputFormatters: <TextInputFormatter>[
                          NoNewLineTextInputFormatter()
                        ],
                        controller: _commentController,
                        onChanged: (String? value) {
                          context.read<PaymentCubit>().setComment(value ?? '');
                        },
                        decoration: InputDecoration(
                          labelText: tr('g1_form_pay_desc'),
                          hintText: tr('g1_form_pay_hint'),
                          border: const OutlineInputBorder(),
                        ),
                        validator: (String? value) {
                          if (value != null &&
                              !basicEnglishCharsRegExp.hasMatch(value)) {
                            return tr('valid_comment');
                          }
                          return null;
                        },
                        // Disallow autocomplete
                        autofillHints: const <String>[],
                      )),
                  const SizedBox(width: 5.0),
                  Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Material(
                        color: Colors.transparent,
                        child: IgnorePointer(
                          ignoring: sentDisabled,
                          child: IconTheme(
                            data: const IconThemeData(size: 40.0),
                            child: IconButton(
                              key: paySentKey,
                              tooltip: tr('g1_form_pay_send'),
                              icon: Icon(
                                Icons.send,
                                color: sentColor,
                              ),
                              onPressed: _onPressed(state, context),
                              splashRadius: 20,
                              splashColor: Colors.white.withOpacity(0.5),
                              highlightColor: Colors.transparent,
                            ),
                          ),
                        ),
                      ),
                      Text(
                        tr('g1_form_pay_send'),
                        style: TextStyle(fontSize: 12, color: sentColor),
                      ),
                    ],
                  ),

                ]),
                const SizedBox(height: 10.0),
                ValueListenableBuilder<String>(
                  valueListenable: _feedbackNotifier,
                  builder: (BuildContext context, String value, Widget? child) {
                    if (value.isNotEmpty) {
                      return Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[
                          const Icon(Icons.error_outline, color: Colors.red),
                          const SizedBox(width: 4),
                          Text(
                            capitalize(value),
                            style: const TextStyle(color: Colors.red),
                          ),
                        ],
                      );
                    } else {
                      return const SizedBox.shrink();
                    }
                  },
                ),
              ],
            ),
          );
        });
  }

  Future<void> Function()? _onPressed(PaymentState state,
      BuildContext context) {
    return (!state.canBeSent() ||
        state.amount == null ||
        !_commentValidate() ||
        !_weHaveBalance(context, state.amount!))
        ? null
        : () async {
      try {
        await payWithRetry(
            context: context,
            to: state.contact!,
            amount: state.amount!,
            comment: state.comment);
      } on RetryException {
        // Here the transactions can be lost, so we must implement some manual retry use
        await payWithRetry(
            context: context,
            to: state.contact!,
            amount: state.amount!,
            comment: state.comment,
            useMempool: true);
      }
    };
  }

  bool _commentValidate() {
    final String currentComment = _commentController.value.text;
    final bool val = (currentComment != null &&
        basicEnglishCharsRegExp.hasMatch(currentComment)) ||
        currentComment.isEmpty;
    logger('Validating comment: $val');
    if (_formKey.currentState != null) {
      _formKey.currentState!.validate();
    }
    return val;
  }

  bool _weHaveBalance(BuildContext context, double amount) {
    final double balance = getBalance(context);
    logger('We have $balance, need $amount');
    final bool weHave = balance >= amount * 100;

    if (!weHave) {
      _feedbackNotifier.value = tr('insufficient balance');
    } else {
      _feedbackNotifier.value = '';
    }
    return weHave;
  }

  double getBalance(BuildContext context) =>
      context
          .read<TransactionCubit>()
          .balance;
}

class RetryException implements Exception {
  RetryException();
}

class NoNewLineTextInputFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(TextEditingValue oldValue,
      TextEditingValue newValue) {
    final int cursorPosition = newValue.selection.baseOffset;
    final String newText = newValue.text.replaceAll('\n', '');
    final TextSelection newSelection =
    TextSelection.collapsed(offset: cursorPosition);
    return TextEditingValue(
      text: newText,
      selection: newSelection,
    );
  }
}