import 'package:app_hit_a_wod/src/models/company.model.dart';
import 'package:app_hit_a_wod/src/models/stripe_user.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/utils.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/subjects.dart';
import 'package:stripe_sdk/stripe_sdk.dart';
import 'package:stripe_sdk/stripe_sdk_ui.dart';

class PaymentMethodFormBloc  {

  BuildContext _context;
  ApiProvider _api;

  //card form subject
  BehaviorSubject<String> _cardNameSubject = new BehaviorSubject();
  Stream<String> get cardNameStream => _cardNameSubject.stream;
  get setCardName => _cardNameSubject.sink.add;
  BehaviorSubject<String> _cardNumberSubject = new BehaviorSubject();
  Stream<String> get cardNumberStream => _cardNumberSubject.stream;
  get setCardNumber => _cardNumberSubject.sink.add;
  BehaviorSubject<int> _cardMonthSubject = new BehaviorSubject();
  Stream<int> get cardMonthStream => _cardMonthSubject.stream;
  get setCardMonth => _cardMonthSubject.sink.add;
  BehaviorSubject<int> _cardYearSubject = new BehaviorSubject();
  Stream<int> get cardYearStream => _cardYearSubject.stream;
  get setCardYear => _cardYearSubject.sink.add;
  BehaviorSubject<String> _cardCvcSubject = new BehaviorSubject();
  Stream<String> get cardCvcStream => _cardCvcSubject.stream;
  get setCvcNumber => _cardCvcSubject.sink.add;
  BehaviorSubject<bool> _checkedTerminosCondicionesSubject = new BehaviorSubject();
  Stream<bool> get streamCheckedTerminosCondiciones => _checkedTerminosCondicionesSubject.stream;
  get setChecked => _checkedTerminosCondicionesSubject.sink.add;
  BehaviorSubject<String> _statusSubject = new BehaviorSubject(); //'init', 'valid', 'loading', 'done'
  Stream<String> get statusStream => _statusSubject.stream;

  PaymentMethodFormBloc(BuildContext this._context, ApiProvider this._api) {
    _cardNumberSubject.sink.add("");
    _cardMonthSubject.sink.add(null);
    _cardYearSubject.sink.add(null);
    _cardCvcSubject.sink.add(null);
    _checkedTerminosCondicionesSubject.sink.add(false);
    _statusSubject.sink.add('init');
    _cardNameSubject.sink.add("");
  }

  checkValidation() {
    final StripeCard card = _card();
    final bool checked = _checkedTerminosCondicionesSubject.value;

    if(!checked) {
      _statusSubject.sink.addError("Acepta los términos y condiciones");
    }
    else if(!card.validateCard()) {
      _statusSubject.sink.addError("Los datos de la tarjeta no son válidos");
    }
    else _statusSubject.sink.add('valid');
  }

  Future<bool> savePaymentMethod(Company company, int user_id) async {
    _statusSubject.sink.add('loading');
    try {
      final response = await _api.createStripeIntentByStripeUser(company.id, user_id); //1. Creem intent
      final intent = response["intent"];
      final String client_secret = intent["client_secret"];
      Stripe stripe = Stripe(company.stripe_public_key, returnUrlForSca: UtilsHAW.STRIPE_SCA_URL);
      StripeApi stripe_api = StripeApi(company.stripe_public_key);
      final payment_method = await stripe_api.createPaymentMethodFromCard(_card()); //2. Creem payment method
      final confirm_setup_response = await stripe.confirmSetupIntentWithPaymentMethod(client_secret, payment_method["id"]); //3. Confirmem setup intent
      //4. Via webhook s'actualitzara el servidor amb el metode de pago id
      //_statusSubject.sink.add('done');
      final auth = Provider.of<AuthProvider>(_context, listen: false);
      auth.refreshToken();
      Navigator.pop(_context);
      
      return confirm_setup_response["status"]=="succeeded";
    } on DioError catch(e) {
      _statusSubject.sink.add('invalid');
      _statusSubject.sink.addError(e.response!=null ? e.response.data["error"] : e.toString());
      return false;
    } on Exception catch(e) {
      _statusSubject.sink.add('invalid');
      _statusSubject.sink.addError(e.toString());
      return false;
    }
  }

  _card() {
    return StripeCard(number: _cardNumberSubject.value, expMonth: _cardMonthSubject.value, expYear: _cardYearSubject.value, cvc: _cardCvcSubject.value, name: _cardNameSubject.value);
  }

}