import 'package:app_hit_a_wod/src/blocs/cancel_subscription.bloc.dart';
import 'package:app_hit_a_wod/src/blocs/change_pricing_form.bloc.dart';
import 'package:app_hit_a_wod/src/blocs/payment_method_form.bloc.dart';
import 'package:app_hit_a_wod/src/blocs/renew_subscription_manually.bloc.dart';
import 'package:app_hit_a_wod/src/models/box.model.dart';
import 'package:app_hit_a_wod/src/models/company.model.dart';
import 'package:app_hit_a_wod/src/models/pricing.model.dart';
import 'package:app_hit_a_wod/src/models/stripe_user.model.dart';
import 'package:app_hit_a_wod/src/models/subscription_selection.model.dart';
import 'package:app_hit_a_wod/src/providers/api.provider.dart';
import 'package:app_hit_a_wod/src/providers/auth.provider.dart';
import 'package:app_hit_a_wod/src/providers/user-subscriptions.provider.dart';
import 'package:app_hit_a_wod/src/utils.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart';
import 'package:stripe_sdk/stripe_sdk_ui.dart';

import '../../styles.dart';

class BillingPage extends StatelessWidget {
  const BillingPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final AuthProvider auth = Provider.of<AuthProvider>(context);
    final UserSubscriptionsProvider us_provider = Provider.of<UserSubscriptionsProvider>(context);
    final ApiProvider _api = Provider.of<ApiProvider>(context);

    return RefreshIndicator(
      onRefresh: () async {
        return _refreshScreen(auth);
      },
      color: colors["primary"],
      displacement: 1,
      child: SingleChildScrollView(
        physics: AlwaysScrollableScrollPhysics(),
        padding: EdgeInsets.all(20),
        child: StreamBuilder(
          stream: us_provider.activeStream,
          builder: (context, AsyncSnapshot data) {
            if(data.hasData) {
              final SubscriptionSelection ss = data.data;
              return FutureBuilder(
                future: _api.getStripeUserFromCompany(ss.company.id, ss.us.user_id),
                builder: (BuildContext context, AsyncSnapshot<StripeUser> data) {
                  final StripeUser stripeUser = data.hasData ? data.data : null;
                  return Column(children: <Widget>[
                    SizedBox(height: 20),
                    Wrap(children: <Widget>[Text("Facturación y pagos", style: Theme.of(context).textTheme.subtitle)], alignment: WrapAlignment.center,),
                    SizedBox(height: 30),
                    _yourSubscription(context, ss, stripeUser, _api),
                    SizedBox(height: 20),
                    _myPaymentMethod(context, _api, ss, stripeUser), //ja inclou el seu sizedbox, si es que es mostra
                    _myOrders(context),
                    SizedBox(height: 20)
                  ]);
                  
                }
              );
            }
            else return _skeletonLayout();
          }
        )
      )
    );
  }

  _yourSubscription(BuildContext context, SubscriptionSelection ss, StripeUser stripeUser, ApiProvider api) {
    return neuContainer(
      Column(
        mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
        children: 
          ss.role.slug == "athlete" ?
          <Widget>[
            _yourSubscriptionHeaderRow(context, ss, stripeUser, api),
            SizedBox(height: 20),
            Row(children: <Widget>[
              neuChip(Text(ss.company.name, style: TextStyle(color: Colors.white),), colors: secondaryShadow),
              SizedBox(width: 10),
              Expanded(child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
                RichText(overflow: TextOverflow.ellipsis, text: TextSpan(children: [TextSpan(text: "Tarifa: ", style: TextStyle(fontWeight: FontWeight.w500)), TextSpan(text: ss.pricing.name)], style: Theme.of(context).textTheme.body1)),
                SizedBox(height: 5),
                _subscriptionEndingText(context, ss, stripeUser)
              ]))
            ]),          
            SizedBox(height: 40),
            _mySubscriptionActionsButtonsAndText(context, ss, stripeUser, api)
          ] : 
          [
            _yourSubscriptionHeaderRow(context, ss, stripeUser, api),
            SizedBox(height: 20),
            Text("Al no ser un atleta, tu suscripción se gestiona desde la web de administración de Hit a Wod.", style: Theme.of(context).textTheme.body1.copyWith(fontStyle: FontStyle.italic))
          ]
      ),
      padding: EdgeInsets.all(30),
      width: double.infinity
    );
  }

  _myOrders(BuildContext context) {
    return neuContainer(
      Column(
        mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text("Mis pedidos", style: Theme.of(context).textTheme.title),
          SizedBox(height: 20),
          neuButton(
            NeumorphicButton(
              padding: EdgeInsets.all(20),
              style: neuButtonStyle(),
              child: Text("Ver todos mis pedidos", style: Theme.of(context).textTheme.display2, textAlign: TextAlign.center,),
              onClick: () {
                Navigator.pushNamed(context, 'my-orders');
              },
            ),
            colors: primaryColors,
            width: double.infinity,
            borderRadius: BorderRadius.all(Radius.circular(8))
          )
        ]
      ),
      padding: EdgeInsets.all(30),
      width: double.infinity
    );
  }

  _myPaymentMethod(BuildContext context, ApiProvider _api, SubscriptionSelection ss, StripeUser stripeUser) {
    if(!ss.company.is_stripe_active) {
      return Container();
    }
    else {
      return Column(children: <Widget>[
        neuContainer(Column(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
          Text("Tu método de pago", style: Theme.of(context).textTheme.title),
          SizedBox(height: 20),
          (
            (stripeUser == null || !stripeUser.is_stripe_active ) ?
            Column(children: <Widget>[ //quan no té el pago automatic activat
              Text("No tienes configurado ningún método de pago con este centro.", style: Theme.of(context).textTheme.body1),
              SizedBox(height: 50),
              neuButton(NeumorphicButton( //boto de iniciar suscripcio amb renovacio automatica
                  padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
                  style: neuButtonStyle(),
                  child: Text("Configurar método de pago", style: Theme.of(context).textTheme.display2, textAlign: TextAlign.center,),
                  onClick: () { _showPaymentMethodDialog(context, _api, ss, stripeUser); },
                ), colors: primaryColors, width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8)
              ))
            ],) :
            Column(children: <Widget>[ //quan té el pago automatic activat
              Row(crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[
                ClipRRect(borderRadius: BorderRadius.circular(8), child: Image( width: 60, image: UtilsHAW.creditCardImage(stripeUser.card_brand!=null ? stripeUser.card_brand.toLowerCase() : "unknown") )),
                SizedBox(width: 20),
                Text("${stripeUser.card_brand[0].toUpperCase() + stripeUser.card_brand.substring(1)} terminada en ${stripeUser.card_last_four}", style: Theme.of(context).textTheme.body1, overflow: TextOverflow.ellipsis,)
              ]),
              SizedBox(height: 50),
              neuButton(NeumorphicButton( //boto de iniciar suscripcio amb renovacio automatica
                  padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
                  style: neuButtonStyle(),
                  child: Text("Actualizar método de pago", style: Theme.of(context).textTheme.display2, textAlign: TextAlign.center,),
                  onClick: () { _showPaymentMethodDialog(context, _api, ss, stripeUser); },
                ), colors: primaryColors, width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8)
              ))
            ],)
          )
        ]),
          padding: EdgeInsets.all(30),
          width: double.infinity),
        SizedBox(height: 20) //no borrarlo
      ],);
    }
  }

  _yourSubscriptionHeaderRow(BuildContext context, SubscriptionSelection ss, StripeUser stripeUser, ApiProvider api) {
    if(stripeUser==null || !stripeUser.is_stripe_active || !ss.company.is_stripe_active) {
      return Text(ss.pricing.recharge_weekly ? "Tu suscripción" : "Tu bono", style: Theme.of(context).textTheme.title, textAlign: TextAlign.left);
    }
    else return Row(crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[
      Text(ss.pricing.recharge_weekly ? "Tu suscripción" : "Tu bono", style: Theme.of(context).textTheme.title, textAlign: TextAlign.left),
      SizedBox(width: 20),
      Expanded( child: NeumorphicToggle(
        style: NeumorphicToggleStyle(backgroundColor: neuColor, borderRadius: BorderRadius.circular(8)),
        height: 50.0,
        selectedIndex: !ss.us.renew || ss.us.stripe_id==null ? 0 : 1,
        displayForegroundOnlyIfSelected: true,
        children: [
          ToggleElement(
            background: Center( child: Text("Manual", overflow: TextOverflow.ellipsis) ),
            foreground: Center( child: Text("Manual", overflow: TextOverflow.ellipsis) ),
          ),
          ToggleElement(
            background: Center( child: Text("Auto", overflow: TextOverflow.ellipsis) ),
            foreground: Center( child: Text("Auto", overflow: TextOverflow.ellipsis) )
          ),
        ],
        thumb: Neumorphic( style: neuStyle() ),
        onChanged: (value) { 
          if(value==0) {
            //anem cap a manual, hem de cancelar
            _showCancelSubscriptionDialog(context, ss, stripeUser, api);
          }
          else if(value==1) {
            //anem cap a auto, hem d'activar la suscripcio automatica
            _showChangePricingDialog(context, ss, stripeUser, api, automatic: true, selectCurrentSubscription: true );
          }
        },
      ))
    ]);
  }

  _subscriptionEndingText(BuildContext context, SubscriptionSelection ss, StripeUser stripeUser) {
    if(!ss.pricing.recharge_weekly) return Container();
    else if(stripeUser!=null && ss.us.stripe_id!=null && ss.us.renew) return RichText(overflow: TextOverflow.ellipsis, text: TextSpan(children: [TextSpan(text: "Se renovará el ", style: TextStyle(fontWeight: FontWeight.w500)), TextSpan(text: DateFormat('dd/MM/yyyy').format(ss.us.end_date))], style: Theme.of(context).textTheme.body1));
    else return RichText(overflow: TextOverflow.ellipsis, text: TextSpan(children: [TextSpan(text: "Fin: ", style: TextStyle(fontWeight: FontWeight.w500)), TextSpan(text: DateFormat('dd/MM/yyyy').format(ss.us.ends_at!=null ? ss.us.ends_at : ss.us.end_date))], style: Theme.of(context).textTheme.body1));
  }

  _mySubscriptionActionsButtonsAndText(BuildContext context, SubscriptionSelection ss, StripeUser stripeUser, ApiProvider api) {
    if(!ss.pricing.recharge_weekly) {
      //es un bono
      if(stripeUser==null || !stripeUser.is_stripe_active) { //no te metode de pago configurat
        if(ss.company.is_stripe_active) return Text("Si configuras un método de pago con este centro de Crossfit, podrás pagar tus bonos y tarifas desde la aplicación de Hit a Wod.", style: Theme.of(context).textTheme.body1.copyWith(fontStyle: FontStyle.italic));
        else return Text("Para renovar el bono, deberás dirigirte a la recepción de tu centro y renovar allí.", style: Theme.of(context).textTheme.body1.copyWith(fontStyle: FontStyle.italic));
      }
      else if(stripeUser!=null && ss.company.is_stripe_active) { //es un bono i pot renovar-lo automaticament
        return Column(children: <Widget>[
          neuButton(NeumorphicButton( //boto de ampliar bono
              padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
              style: neuButtonStyle(),
              child: Text("Renovar bono", style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center,),
              onClick: () { _showRenewManuallyDialog(context, ss, stripeUser, api); },
            ), width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8)
          )),
          SizedBox(height: 20),
          neuButton(NeumorphicButton( //boto de iniciar suscripcio amb renovacio automatica
              padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
              style: neuButtonStyle(),
              child: Text("Cambiar tarifa", style: Theme.of(context).textTheme.display2, textAlign: TextAlign.center,),
              onClick: () { _showChangePricingDialog(context, ss, stripeUser, api, automatic: false, selectCurrentSubscription: false ); },
            ), colors: primaryColors, width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8)
          ))
        ]);
      }
      else return Text("Para renovar tu bono contacta con tu centro de Crossfit.", style: Theme.of(context).textTheme.body1.copyWith(fontStyle: FontStyle.italic));
    }
    else {
      //ara ja no es bono segur, es una tarifa normal
      if(!ss.company.is_stripe_active) return Text("El pago automático no está disponible para tu box. Recuerda renovar la tarifa en recepción cuando ésta vaya a finalizar para no quedarte sin acceso a la aplicación.", style: Theme.of(context).textTheme.body1.copyWith(fontStyle: FontStyle.italic));
      else if(stripeUser==null || !stripeUser.is_stripe_active) return Text("El pago automático está disponible en tu box. Simplemente debes configurar un método de pago para poderlo activar.", style: Theme.of(context).textTheme.body1.copyWith(fontStyle: FontStyle.italic));
      else if(ss.us.stripe_id!=null && ss.us.renew) { //automatic FULL
        return Column(children: <Widget>[
          neuButton(NeumorphicButton( //boto de iniciar suscripcio amb renovacio automatica
              padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
              style: neuButtonStyle(),
              child: Text("Cambiar tarifa", style: Theme.of(context).textTheme.display2, textAlign: TextAlign.center,),
              onClick: () { _showChangePricingDialog(context, ss, stripeUser, api, automatic: true, selectCurrentSubscription: false ); },
            ), colors: primaryColors, width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8)
          )),
          SizedBox(height: 20),
          neuButton(NeumorphicButton( //boto de ampliar bono
              padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
              style: neuButtonStyle(),
              child: Text("Cancelar suscripción", style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center,),
              onClick: () { _showCancelSubscriptionDialog(context, ss, stripeUser, api); },
            ), width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8)
          ))
        ]);
      }
      else { //esta en manual pero pot automatic si vol
        return Column(children: <Widget>[
          neuButton(NeumorphicButton( //boto de renovar manualment
              padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
              style: neuButtonStyle(),
              child: Text("Renovar manualmente", style: Theme.of(context).textTheme.display2, textAlign: TextAlign.center,),
              onClick: () { _showRenewManuallyDialog(context, ss, stripeUser, api); },
            ), colors: primaryColors, width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8)
          )),
          SizedBox(height: 20),
          neuButton(NeumorphicButton( //boto de canviar tarifa
              padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
              style: neuButtonStyle(),
              child: Text("Cambiar tarifa", style: Theme.of(context).textTheme.display2, textAlign: TextAlign.center,),
              onClick: () { _showChangePricingDialog(context, ss, stripeUser, api, automatic: false, selectCurrentSubscription: false ); },
            ), colors: secondaryShadow, width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8)
          )),
        ]);
      }
    }
  }

  void _showPaymentMethodDialog(BuildContext context, ApiProvider _api, SubscriptionSelection ss, StripeUser stripeUser) {
    final bloc = PaymentMethodFormBloc(context, _api);
    neuDialog(
      context: context, 
      padding: EdgeInsets.symmetric(vertical: 20, horizontal: 20),
      child: Container(
        child: Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Text("Nombre completo", style: Theme.of(context).textTheme.body1),
            SizedBox(height: 10),
            StreamBuilder(
              stream: bloc.cardNameStream,
              builder: (context, data) {
                if(data.hasData) {
                  return neuInput(TextFormField(autofocus: true, textCapitalization: TextCapitalization.words, initialValue: data.data, decoration: InputDecoration(
                    border: InputBorder.none,
                    hintText: 'Nombre completo',
                  ), onChanged: bloc.setCardName ),);
                }
                else return Container();
              },
            ),
            SizedBox(height: 20),
            Text("Número de tarjeta", style: Theme.of(context).textTheme.body1),
            SizedBox(height: 10),
            StreamBuilder(
              stream: bloc.cardNumberStream,
              builder: (context, data) {
                if(data.hasData) {
                  final brand = StripeCard.asCardBrand(getPossibleCardType(data.data));
                  return neuInput(CardNumberFormField(initialValue: data.data, decoration: InputDecoration(
                    border: InputBorder.none,
                    hintText: 'Número de tarjeta',
                    suffix: (data.data!="" && brand!=null) ? SizedBox(width: 60, child: ClipRRect(borderRadius: BorderRadius.circular(4), child: Image( height: 20, width: 50, image: UtilsHAW.creditCardImage(brand.toLowerCase())))) : null,
                  ), onChanged: bloc.setCardNumber ),);
                }
                else return Container();
              },
            ),
            SizedBox(height: 20),
            Row(children: <Widget>[
              Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,children: <Widget>[
                Text("Fecha de expiración", style: Theme.of(context).textTheme.body1),
                SizedBox(height: 10),
                StreamBuilder(
                  stream: CombineLatestStream.combine2(bloc.cardMonthStream, bloc.cardYearStream, (a, b) => {"year": b, "month": a}),
                  builder: (context, data)  {
                    if(data.hasData) {
                      final int month = data.data["month"]; 
                      final int year = data.data["year"]; 
                      return neuInput(CardExpiryFormField(initialMonth: month, initialYear: year, decoration: InputDecoration(
                        border: InputBorder.none,
                        hintText: 'MM/YY',
                      ), onChanged: (month, year) { bloc.setCardMonth(month); bloc.setCardYear(year); }));
                    }
                    else return Container();
                  }
                )
              ])),
              SizedBox(width: 20),
              Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,children: <Widget>[
                Text("CVC", style: Theme.of(context).textTheme.body1),
                SizedBox(height: 10),
                StreamBuilder(
                  stream: bloc.cardCvcStream,
                  builder: (context, data) {
                    return SizedBox(width: 100, child: neuInput( CardCvcFormField(initialValue: data.data, decoration: InputDecoration(
                      border: InputBorder.none,
                      hintText: '123',
                    ), onChanged: bloc.setCvcNumber ),));
                  }
                ),
              ])
            ]),
            SizedBox(height: 20),
            Row(crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[
              StreamBuilder(
                stream: bloc.streamCheckedTerminosCondiciones,
                builder: (context, data) {
                  return NeumorphicCheckbox(
                    value: data.hasData ? data.data : false,
                    style: neuCheckboxStyle(),
                    onChanged: bloc.setChecked
                  );
                }
              ),
              SizedBox(width: 20),
              Expanded(child: Text("He leído y acepto los términos y condiciones.", style: Theme.of(context).textTheme.body1),)
            ]),
            SizedBox(height: 20),
            StreamBuilder(
              stream: bloc.statusStream,
              builder: (context, data) {
                String status = data.hasData ? data.data : 'init';

                return neuButton(NeumorphicButton( //boto de iniciar suscripcio amb renovacio automatica
                  padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
                  style: neuButtonStyle(),
                  child: status=='loading' ? 
                    Row(mainAxisAlignment: MainAxisAlignment.center, children: [SizedBox(width: 30, height: 30, child: CircularProgressIndicator(strokeWidth: 3, backgroundColor: Colors.transparent, valueColor: new AlwaysStoppedAnimation<Color>(Color(0xFFF8F8FC)),))]) : 
                    Text((data.hasData && !data.hasError && status=='valid') ? "Guardar tarjeta" : "Validar tarjeta", style: Theme.of(context).textTheme.display2, textAlign: TextAlign.center,),
                  onClick: () async {
                    if(data.hasData && !data.hasError && status=='valid') {
                      bloc.savePaymentMethod(ss.company, ss.us.user_id);
                    }
                    else if(status!='loading') {
                      bloc.checkValidation();
                    }
                  },
                ), colors: primaryColors, width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8)));
              }
            ), 
            StreamBuilder(
              stream: bloc.statusStream,
              builder: (context, data) {
                if(data.hasError) {
                  return Column(children: [SizedBox(height: 20), Text(data.error.toString(), style: Theme.of(context).textTheme.display3)]);
                }
                else return Container();
              }
            )
          ],
        )
      )
    );
  }

  _skeletonLayout() => Column(children: <Widget>[
    Wrap(children: <Widget>[neuSkeletonCard(50, 300)], alignment: WrapAlignment.center,),
    SizedBox(height: 20),
    neuSkeletonCard(350, double.infinity),
    SizedBox(height: 20),
    neuSkeletonCard(250, double.infinity),
    SizedBox(height: 20),
    neuSkeletonCard(150, double.infinity),
    SizedBox(height: 20),
  ]);

  _refreshScreen(AuthProvider auth) async {
    List<Future> list = [];
    list.add(auth.refreshToken());
    await Future.wait(list);
    return;
  }

  void _showRenewManuallyDialog(BuildContext context, SubscriptionSelection ss, StripeUser stripeUser, ApiProvider api) {
    final bloc = RenewSubscriptionManuallyBloc(context, api, stripeUser, ss);
    neuDialog(
      context: context, 
      padding: EdgeInsets.symmetric(vertical: 20, horizontal: 20), 
      child: StreamBuilder(
        stream: bloc.statusStream,
        builder: (context, data)  {
          final status = data.hasData ? data.data : 'init';

          return Container(
            child: Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                _renewHeaderCompany(context, ss.company, ss.box, "Renovación manual"),
                SizedBox(height: 50),
                RichText(text: TextSpan(text: "Precio: ", style: Theme.of(context).textTheme.body1.copyWith(fontWeight: FontWeight.w500), children: [TextSpan(text: "${ss.pricing.price}€ (${(ss.pricing.vat_included*100)}% IVA incluido)", style: Theme.of(context).textTheme.body1)])),
                SizedBox(height: 20),
                RichText(text: TextSpan(text: "Tarifa: ", style: Theme.of(context).textTheme.body1.copyWith(fontWeight: FontWeight.w500), children: [TextSpan(text: ss.pricing.name, style: Theme.of(context).textTheme.body1)])),
                SizedBox(height: 20),
                RichText(text: TextSpan(text: "Caducará en: ", style: Theme.of(context).textTheme.body1.copyWith(fontWeight: FontWeight.w500), children: [TextSpan(text: ss.pricing.recharge_weekly ? DateFormat('dd/MM/yyyy').format(ss.us.end_date.add(Duration(days: ss.pricing.days))) : (ss.pricing.days==null ? "No caduca." : DateFormat('dd/MM/yyyy').format(DateTime.now())), style: Theme.of(context).textTheme.body1)])),
                SizedBox(height: 50),
                Text(
                  "Se generará un nuevo pedido y se le cobrará el importe especificado al momento. Además, se generará una nueva factura que podrá consultar en el apartado de 'Mis pedidos'.", 
                  style: Theme.of(context).textTheme.body1.copyWith(fontStyle: FontStyle.italic)
                ),
                SizedBox(height: 20),
                neuButton(NeumorphicButton( //boto de iniciar suscripcio amb renovacio automatica
                  padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
                  style: neuButtonStyle(),
                  child: status=='loading' ?
                    Row(mainAxisAlignment: MainAxisAlignment.center, children: [SizedBox(width: 30, height: 30, child: CircularProgressIndicator(strokeWidth: 3, backgroundColor: Colors.transparent, valueColor: new AlwaysStoppedAnimation<Color>(Color(0xFFF8F8FC)),))]) :
                    Text("Renovar (${ss.pricing.price}€)", style: Theme.of(context).textTheme.display2, textAlign: TextAlign.center,),
                  onClick: () { bloc.renew(); },
                ), colors: primaryColors, width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8))),
                (
                  data.hasError ?
                  Column(children: [SizedBox(height: 20), Text(data.error.toString(), style: Theme.of(context).textTheme.display3)]) :
                  Container()
                )
              ]
            )
          );
        }
      )
    );
  }

  _renewHeaderCompany(BuildContext context, Company c, Box b, String subtitle) {
    double widthAndHeight = 50;
    return Row(children: <Widget>[
      ClipRRect(borderRadius: BorderRadius.circular(8), child: CachedNetworkImage(imageUrl: c.logo_url, width: widthAndHeight, height: widthAndHeight, fit: BoxFit.cover, placeholder: (_, __) => SizedBox(width: widthAndHeight, height: widthAndHeight, child: CircularProgressIndicator(strokeWidth: 3, backgroundColor: Colors.transparent, valueColor: new AlwaysStoppedAnimation<Color>(colors["primary"]),)))),
      SizedBox(width: 20),
      Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
        Text("${c.name}, ${b.city}", style: Theme.of(context).textTheme.body1.copyWith(fontWeight: FontWeight.w500)),
        SizedBox(height: 10),
        Text(subtitle, style: Theme.of(context).textTheme.body1)
      ]))
    ]);
  }

  void _showChangePricingDialog(BuildContext context, SubscriptionSelection ss, StripeUser stripeUser, ApiProvider api, { bool automatic = false, bool selectCurrentSubscription = false }) {
    final bloc = ChangePricingFormBloc(context, api, stripeUser, ss, automatic: automatic, selectCurrentSubscription: selectCurrentSubscription);

    neuDialog(
      context: context, 
      padding: EdgeInsets.symmetric(vertical: 20, horizontal: 20), 
      child: StreamBuilder(
        stream: bloc.statusStream,
        builder: (context, data)  {
          final status = data.hasData ? data.data : 'init';

          if(status=='loading_pricings') {
            return Column(children: <Widget>[
              Row(children: <Widget>[
                neuSkeletonCard(100, 100),
                SizedBox(width: 20),
                Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[
                    neuSkeletonCard(30, double.infinity-200),
                    SizedBox(height: 20),
                    neuSkeletonCard(30, double.infinity-100),
                ]))
              ]),
              SizedBox(height: 50),
              neuSkeletonCard(100, double.infinity),
              SizedBox(height: 20),
              neuSkeletonCard(100, double.infinity),
              SizedBox(height: 20),
              neuSkeletonCard(100, double.infinity),
              SizedBox(height: 50),
              neuSkeletonCard(40, double.infinity),
              SizedBox(height: 20),
              neuSkeletonCard(60, double.infinity),
            ]);
          }
          else return Container(
            child: Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                _renewHeaderCompany(context, ss.company, ss.box, "Cambiar de tarifa"),
                SizedBox(height: 20),
                StreamBuilder( //llistar tarifes
                  stream: CombineLatestStream.combine2(bloc.pricingsStream, bloc.pricingSelectedStream, (a, b) => {"pricings": a, "selected_pricing": b}),
                  builder: (context, AsyncSnapshot data) {
                    if(data.hasData) {
                      final List<Pricing> pricings = data.data["pricings"];
                      final Pricing selected_pricing = data.data["selected_pricing"];
                      return Column(children: pricings.map((Pricing p) => Column(children: <Widget>[
                        neuButton(NeumorphicButton(
                            padding: EdgeInsets.all(15),
                            style: (selected_pricing!=null && p.id==selected_pricing.id) ? neuStylePressed() : neuButtonStyle(),
                            boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(8)),
                            child: Column(
                              children: <Widget>[
                                Row(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
                                  Expanded(child: Expanded(child: Text(p.name, style: Theme.of(context).textTheme.body1.copyWith(fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis))),
                                  SizedBox(width: 20),
                                  neuChip(Text((p.recharge_weekly && p.days!=null) ? UtilsHAW.daysToStringPeriod(p.days) : "Bono", style: TextStyle(color: Colors.white),), colors: secondaryShadow, padding: EdgeInsets.symmetric(horizontal: 12, vertical: 5))
                                ]),
                                SizedBox(height: 10),
                                Row(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
                                  Expanded(child: Text(p.description, style: Theme.of(context).textTheme.body1)),
                                  SizedBox(width: 20),
                                  Column(children: [
                                    neuChip(Text(p.price!=null ? "${p.price}€" : "Gratis", style: TextStyle(color: Colors.white),), colors: primaryColors, padding: EdgeInsets.symmetric(horizontal: 12, vertical: 5)),
                                    SizedBox(height: 20),
                                    (
                                      p.boxes.length > 1 ?
                                      neuChip(Text("Multibox", style: TextStyle(color: Colors.white),), colors: secondaryShadow, padding: EdgeInsets.symmetric(horizontal: 12, vertical: 5)) :
                                      Container()
                                    )
                                  ]) 
                                ]),
                              ],
                            ),
                            onClick: () { (selected_pricing!=null && selected_pricing.id==p.id) ? bloc.setPricing(null) : bloc.setPricing(p); }), 
                          borderRadius: BorderRadius.all(Radius.circular(8)),
                          width: double.infinity
                        ),
                        SizedBox(height: 20)
                      ])).toList());
                    }
                    else return Column(children: <Widget>[
                      neuSkeletonCard(100, double.infinity),
                      SizedBox(height: 20),
                      neuSkeletonCard(100, double.infinity),
                      SizedBox(height: 20),
                      neuSkeletonCard(100, double.infinity)
                    ]);
                  }
                ),
                SizedBox(height: 20),
                StreamBuilder( //override
                  stream: CombineLatestStream.combine2(bloc.automaticStream, bloc.pricingSelectedStream, (a, b) => { "automatic": a, "pricing": b }),
                  builder: (context, data) {
                    if(data.hasData) {
                      final Pricing p = data.data["pricing"];
                      final bool automatic = data.data["automatic"];
                      if(p!=null && p.recharge_weekly) {
                        return Column(children: [
                          Text("¿Cuando quieres que empiece la nueva suscripción?", style: Theme.of(context).textTheme.body1.copyWith(fontWeight: FontWeight.w500)),
                          SizedBox(height: 20),
                          NeumorphicToggle(
                            style: NeumorphicToggleStyle(backgroundColor: neuColor, borderRadius: BorderRadius.circular(8)),
                            height: 50.0,
                            selectedIndex: automatic ? 0 : 1,
                            displayForegroundOnlyIfSelected: true,
                            children: [
                              ToggleElement(
                                background: Center(child: Text('Renovación automática', style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center)),
                                foreground: Center(child: Text('Renovación automática', style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center))
                              ),
                              ToggleElement(
                                background: Center(child: Text('Renovación manual', style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center)),
                                foreground: Center(child: Text('Renovación manual', style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center))
                              )
                            ], thumb: Neumorphic( style: neuStyle() ), onChanged: (val) { bloc.setAutomatic(val==0 ? true : false); }
                          ),
                        ]);
                      }
                      else return Container();
                    }
                    else return neuSkeletonCard(40, double.infinity);
                  }
                ),
                SizedBox(height: 20),
                StreamBuilder( //automatic
                  stream: bloc.overrideStream,
                  builder: (context, data) {
                    if(data.hasData) {
                      return Row(children: [
                        NeumorphicCheckbox(
                          value: automatic,
                          style: neuCheckboxStyle(),
                          onChanged: bloc.setOverride
                        ),
                        SizedBox(width: 20),
                        Expanded(child: Text("Cambiar ahora de tarifa y no esperar a que termine el período de facturación actual.", style: Theme.of(context).textTheme.body1, overflow: TextOverflow.clip,))
                      ]);
                    }
                    else return neuSkeletonCard(40, double.infinity);
                  }
                ),
                SizedBox(height: 20),
                StreamBuilder(
                  stream: bloc.pricingSelectedStream,
                  builder: (context, data) {
                    if(data.hasData) {
                      final Pricing pricing = data.data;
                      return Text("Se generará un nuevo pedido con una nueva factura, y además se le cobrará ${pricing.price}€ por parte del centro de Crossfit. Su suscripción se ampliará por ${pricing.days!=null ? (pricing.days.toString() + ' días.') : 'días ilimitados.'}", style: Theme.of(context).textTheme.body1.copyWith(fontStyle: FontStyle.italic));
                    }
                    else return Container();
                  }
                ),
                SizedBox(height: 20),
                neuButton(NeumorphicButton( //boto de iniciar suscripcio amb renovacio automatica
                  padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
                  style: neuButtonStyle(),
                  child: status=='loading' ?
                    Row(mainAxisAlignment: MainAxisAlignment.center, children: [SizedBox(width: 30, height: 30, child: CircularProgressIndicator(strokeWidth: 3, backgroundColor: Colors.transparent, valueColor: new AlwaysStoppedAnimation<Color>(Color(0xFFF8F8FC)),))]) :
                    Text("Cambiar tarifa", style: Theme.of(context).textTheme.display2, textAlign: TextAlign.center,),
                  onClick: bloc.changePricing,
                ), colors: primaryColors, width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8))),
                (
                  data.hasError ?
                  Column(children: [SizedBox(height: 20), Text(data.error.toString(), style: Theme.of(context).textTheme.display3)]) :
                  Container()
                )
              ]
            )
          );
        }
      )
    );
  }

  void _showCancelSubscriptionDialog(BuildContext context, SubscriptionSelection ss, StripeUser stripeUser, ApiProvider api) {
    final bloc = CancelSubscriptionBloc(context, api, ss, stripeUser);

    neuDialog(
      context: context, 
      padding: EdgeInsets.symmetric(vertical: 20, horizontal: 20),
      child: Container(
        child: Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            _renewHeaderCompany(context, ss.company, ss.box, "Cancelar suscripción"),
            SizedBox(height: 30),
            Row(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
              Icon(Icons.done, color: colors["secondary"]),
              SizedBox(width: 20),
              Expanded(child: Text("Se desactivará la renovación automática y ya no se te cobrará más de forma automática.", style: Theme.of(context).textTheme.body1)) 
            ]),
            SizedBox(height: 20),
            Row(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
              Icon(Icons.done, color: colors["secondary"]),
              SizedBox(width: 20),
              Expanded(child: Text("Seguirás teniendo acceso hasta que finalice el período de facturación actual, concretamente hasta el ${DateFormat('dd/MM/yyyy').format(ss.us.end_date)}.", style: Theme.of(context).textTheme.body1)) 
            ]),
            SizedBox(height: 20),
            Row(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
              Icon(Icons.done, color: colors["secondary"]),
              SizedBox(width: 20),
              Expanded(child: Text("Una vez desactivada la renovación automática, podrás seguir renovando esta suscripción de forma manual, o volver a activar la suscripción automática si así lo deseas.", style: Theme.of(context).textTheme.body1)) 
            ]),
            SizedBox(height: 30),
            StreamBuilder(
              stream: bloc.statusStream,
              builder: (context, data) {
                final status = data.hasData ? data.data : 'init';
                return Column(children: <Widget>[
                  neuButton(NeumorphicButton( //boto de iniciar suscripcio amb renovacio automatica
                    padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
                    style: neuButtonStyle(),
                    child: status=='loading' ?
                      Row(mainAxisAlignment: MainAxisAlignment.center, children: [SizedBox(width: 30, height: 30, child: CircularProgressIndicator(strokeWidth: 3, backgroundColor: Colors.transparent, valueColor: new AlwaysStoppedAnimation<Color>(Color(0xFFF8F8FC)),))]) :
                      Text("Cancelar suscripción", style: Theme.of(context).textTheme.display2, textAlign: TextAlign.center,),
                    onClick: () {
                      if(!data.hasError && status!="loading") {
                        bloc.cancel();
                      }
                    },
                  ), colors: primaryColors, width: double.infinity, borderRadius: BorderRadius.all(Radius.circular(8))),
                  (
                    data.hasError ?
                    Column(children: [SizedBox(height: 20), Text(data.error.toString(), style: Theme.of(context).textTheme.display3)]) :
                    Container()
                  )
                ]);
              }
            )
          ]
        )
      )
    );
  }

}