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 '../connectivity_widget_wrapper_wrapper.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 ButtonStyle payBtnStyle = ElevatedButton.styleFrom(
        padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 25),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(30.0),
        ),
        foregroundColor: Colors.white,
        backgroundColor: Theme.of(context).colorScheme.primary,
        textStyle: const TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 16,
        ),
      );
      final Widget payBtnText = Text(tr(
          'g1_form_pay_send')); // + (!kReleaseMode ? ' ${state.status}' : ''));
      return Form(
        key: _formKey,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            G1PayAmountField(key: payAmountKey),
            const SizedBox(height: 10.0),
            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(height: 10.0),
            ConnectivityWidgetWrapperWrapper(
                stacked: false,
                offlineWidget: ElevatedButton(
                  onPressed: null,
                  style: payBtnStyle,
                  child: _buildBtn(Text(tr('offline'))),
                ),
                child: ElevatedButton(
                  key: paySentKey,
                  onPressed: (!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);
                          }
                        },
                  style: payBtnStyle,
                  child: _buildBtn(payBtnText),
                )),
            const SizedBox(height: 8),
            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();
                }
              },
            ),
          ],
        ),
      );
    });
  }

  Row _buildBtn(Widget payBtnText) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        const Icon(Icons.send),
        const SizedBox(width: 10),
        payBtnText,
      ],
    );
  }

  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,
    );
  }
}