

import 'package:flutter/material.dart';
import 'package:stripe_sdk/stripe_sdk.dart';
import 'package:stripe_sdk/stripe_sdk_ui.dart';

import '../../constants.dart';
import '../../events/eventbus.dart';
import '../../events/events.dart';
import '../../generated/l10n.dart';
import '../../models/order.dart';
import '../../models/payment_platform.dart';
import '../../models/stripe_payment_method.dart';
import '../../routes.dart';
import '../../store/actions.dart';
import '../../store/store.dart';
import '../../utils/utils.dart';
import '../../widgets/general/breadcrumbs.dart';
import '../../widgets/general/navigationbar.dart';


class DesktopStripePayWeb extends StatefulWidget {
  final Key key;
  final Order order;
  final PaymentPlatform paymentPlatform;
  final StripePaymentMethod stripePaymentMethod;
  const DesktopStripePayWeb(this.order, this.paymentPlatform, {this.key, this.stripePaymentMethod});

  @override
  State<StatefulWidget> createState() {
    return DesktopStripePayWebState();
  }

}

class DesktopStripePayWebState extends State<DesktopStripePayWeb> {

  GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();
  final formKey = GlobalKey<FormState>();
  final card = StripeCard();

  CardForm form;

  bool isSubmitting;

  double sideSpace = 0;
  double mainSpace = 1200;

  @override
  Widget build(BuildContext context) {
    store.dispatch(UpdateContext(context));

    if (MediaQuery.of(context).size.width <= 1200) {
      mainSpace = MediaQuery.of(context).size.width;
      sideSpace = 0;
    } else {
      mainSpace = 1200;
      sideSpace = (MediaQuery.of(context).size.width - 1200) / 2;
    }

    Widget body = Center(
      child: Icon(
        Icons.credit_card,
        size: 40.0,
        color: Colors.black26,
      ),
    );
    if (widget.stripePaymentMethod == null) {
      form = CardForm(card: card, formKey: formKey,);
      body = ListView(
        children: <Widget>[
          form,
          Container(
            padding: EdgeInsets.only(top: 20.0, bottom: 20.0, right: 16.0),
            alignment: Alignment.centerRight,
            child: ElevatedButton(
              style: ElevatedButton.styleFrom(
                primary: Theme.of(context).primaryColor,
              ),
              child: Text(
                S.of(context).submit,
                style: TextStyle(
                  color: Colors.white,
                ),
              ),
              onPressed: () {
                if (formKey.currentState.validate()) {
                  formKey.currentState.save();
                  _paymentRequestWithCard(context);
                } else {
                  ScaffoldMessenger.of(context).showSnackBar(
                      messageSnackBar(
                          context, S.of(context).this_credit_card_is_invalid
                      )
                  );
                }
              },
            ),
          ),
        ],
      );
    }

    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      if (widget.stripePaymentMethod != null) {
        _paymentWithPaymentMethod(context);
      }
    });

    return Scaffold(
      key: _scaffoldKey,
      appBar: MiniNavigationBar(
        title: S.of(context).blog,
        back: true,
        breadCrumbs: [
          BreadCrumb(S.of(context).add_credit_card, null),
        ],
        breadCrumbHeight: Constants.BREADCRUMB_HEIGHT,
      ),
      body: Row(
        children: [
          Container(width: sideSpace,),
          Expanded(child: body,),
          Container(width: sideSpace,),
        ],
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    isSubmitting = false;
    StripeApi.init(widget.paymentPlatform.publishableKey);
  }

  SnackBar messageSnackBar(BuildContext context, String message) {
    Column column = Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[Text(
        message,
        style: TextStyle(
          color: Colors.white,
        ),
      )],
    );
    return SnackBar(
      content: Container(
        height: 45.0,
        child: column,
      ),
      action: SnackBarAction(
        label: S.of(context).ok,
        onPressed: () {
          ScaffoldMessenger.of(context).hideCurrentSnackBar();
        },
      ),
    );
  }

  _paymentWithPaymentMethod(BuildContext context) async {
    Utils.stripePaymentIntent(widget.order, widget.stripePaymentMethod.customerId,
        widget.stripePaymentMethod.paymentMethodId,
        widget.stripePaymentMethod.paymentMethodType, (response) async {

      if (response.data['status'] == Constants.STRIPE_STATUS_REQUIRES_CONFIRMATION) {
        await StripeApi.instance.confirmPaymentIntent(
          response.data[Constants.STRIPE_CLIENT_SECRET],
          data: {
            'payment_method': response.data['payment_method'],
          },
        ).then((result2) {
          if (result2['status'] == Constants.STRIPE_STATUS_SUCCEDED) {
            Utils.stripeChargedSuccess(widget.order,
                widget.stripePaymentMethod.paymentMethodId,
                result2['id'], (response) {
                  if (isSubmitting) {
                    Navigator.of(context).pop();
                  }
                  eventBus.fire(OnOrderUpdated());
                  Routes.router.navigateTo(context, '/orderdetail/${widget
                      .order.id}', replace: true);
                },
                (showErrorDialog)
            );
          } else {
            showErrorDialog(Exception('Unknown error'));
          }
        }).catchError(showErrorDialog);
      }
    }, (showErrorDialog));

    isSubmitting = true;
    Utils.showSubmitDialog(context);
  }

  _paymentRequestWithCard(BuildContext context) async {
    isSubmitting = true;
    Utils.showSubmitDialog(context);
    await StripeApi.instance.createPaymentMethodFromCard(card)
        .then((result) {
      Utils.stripePaymentIntent(widget.order, null, result['id'], result['type'], (response) async {
        if (response.data['status'] == Constants.STRIPE_STATUS_REQUIRES_CONFIRMATION) {
          await StripeApi.instance.confirmPaymentIntent(
            response.data[Constants.STRIPE_CLIENT_SECRET],
            data: {
              'payment_method': response.data['payment_method'],
            }
          ).then((result2) {
            if (result2['status'] == Constants.STRIPE_STATUS_SUCCEDED) {
              Utils.stripeChargedSuccess(widget.order,
                result['id'], // payment method id
                result2['id'], (response) { // payment intent id
                  if (isSubmitting) {
                    Navigator.of(context).pop();
                  }
                  eventBus.fire(OnOrderUpdated());
                  Routes.router.navigateTo(context, '/orderdetail/${widget
                      .order.id}', replace: true);
                },
                (showErrorDialog)
              );
            } else {
              showErrorDialog(Exception('Unknown error'));
            }
          }).catchError(showErrorDialog);
        }
      }, (showErrorDialog),
        cardBrand: result['card']['brand'],
        cardCountry: result['card']['country'],
        cardExpMonth: result['card']['exp_month'],
        cardExpYear: result['card']['exp_year'],
        cardFunding: result['card']['funding'],
        cardLast4: result['card']['last4'],
      );
    }).catchError(showErrorDialog);
  }

  void showErrorDialog(dynamic error) {
    if (isSubmitting) {
      Navigator.of(context).pop();
      isSubmitting = false;
    }
    Utils.showMessageDialog(context, error, onOk: () {
      Navigator.of(context).pop();
      Navigator.of(context).pop();
    });
  }
}