import 'dart:convert';
import 'dart:developer';
import 'dart:ui';

import 'package:diplomaticquarterapp/config/config.dart';
import 'package:diplomaticquarterapp/core/enum/PaymentOptions.dart';
import 'package:diplomaticquarterapp/core/model/ResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/requests/AddProductToCartRequestModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/requests/CreateCustomerRequestModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/requests/OffersCategoriesRequestModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/requests/OffersProductsRequestModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesCartItemsResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesCategoriesResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesCustomerResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/order_response_model.dart';
import 'package:diplomaticquarterapp/core/service/base_service.dart';
import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:flutter/cupertino.dart';

import '../../../locator.dart';

class OffersAndPackagesServices extends BaseService {
  List<PackagesCategoriesResponseModel> categoryList = List();
  List<PackagesResponseModel> productList = List();
  List<PackagesResponseModel> latestOffersList = List();
  List<PackagesResponseModel> bestSellerList = List();
  List<PackagesResponseModel> bannersList = List();
  List<PackagesCartItemsResponseModel> cartItemList = List();
  String cartItemCount = "";

  PackagesCustomerResponseModel customer;

  Future<List<PackagesCategoriesResponseModel>> getAllCategories(OffersCategoriesRequestModel request) async {
    Future errorThrow;

    var url = EXA_CART_API_BASE_URL + PACKAGES_CATEGORIES;
    await baseAppClient.simpleGet(url, onSuccess: (dynamic stringResponse, int statusCode) {
      if (statusCode == 200) {
        var jsonResponse = json.decode(stringResponse);
        jsonResponse['categories'].forEach((json) {
          categoryList.add(PackagesCategoriesResponseModel().fromJson(json));
        });
      }
    }, onFailure: (String error, int statusCode) {
      log(error);
    }, queryParams: request.toFlatMap());

    return categoryList;
  }

  Future<List<PackagesResponseModel>> getAllProducts({@required OffersProductsRequestModel request, @required BuildContext context, @required bool showLoading = true}) async {
    Future errorThrow;

    request.sinceId = (productList.isNotEmpty) ? productList.last.id : 0;
    
    productList = List();
    var url = EXA_CART_API_BASE_URL + PACKAGES_PRODUCTS;
    await baseAppClient.simpleGet(url, onSuccess: (dynamic stringResponse, int statusCode) {
      if (statusCode == 200) {
        var jsonResponse = json.decode(stringResponse);
        jsonResponse['products'].forEach((json) {
          productList.add(PackagesResponseModel().fromJson(json));
        });
      }
    }, onFailure: (String error, int statusCode) {
      log(error);
    }, queryParams: request.toFlatMap());

    return productList;
  }

  Future<List<PackagesResponseModel>> getLatestOffers({@required OffersProductsRequestModel request, @required BuildContext context, @required bool showLoading = true}) async {

    var url = EXA_CART_API_BASE_URL + PACKAGES_PRODUCTS;
    await baseAppClient.simpleGet(url, onSuccess: (dynamic stringResponse, int statusCode) {
      if (statusCode == 200) {
        var jsonResponse = json.decode(stringResponse);
        jsonResponse['products'].forEach((json) {
          latestOffersList.add(PackagesResponseModel().fromJson(json));
        });
      }
    }, onFailure: (String error, int statusCode) {
      log(error);
    }, queryParams: request.toFlatMap());

    return latestOffersList;
  }

  Future<List<PackagesResponseModel>> getBestSellers({@required OffersProductsRequestModel request, @required BuildContext context, @required bool showLoading = true}) async {

    var url = EXA_CART_API_BASE_URL + PACKAGES_PRODUCTS;
    await baseAppClient.simpleGet(url, onSuccess: (dynamic stringResponse, int statusCode) {
      if (statusCode == 200) {
        var jsonResponse = json.decode(stringResponse);
        jsonResponse['products'].forEach((json) {
          bestSellerList.add(PackagesResponseModel().fromJson(json));
        });
      }
    }, onFailure: (String error, int statusCode) {
      log(error);
    }, queryParams: request.toFlatMap());

    return bestSellerList;
  }


  Future<List<PackagesResponseModel>> getBanners({@required OffersProductsRequestModel request, @required BuildContext context, @required bool showLoading = true}) async {
    var url = EXA_CART_API_BASE_URL + PACKAGES_PRODUCTS;
    await baseAppClient.simpleGet(url, onSuccess: (dynamic stringResponse, int statusCode) {
      if (statusCode == 200) {
        var jsonResponse = json.decode(stringResponse);
        jsonResponse['products'].forEach((json) {
          bannersList.add(PackagesResponseModel().fromJson(json));
        });
      }
    }, onFailure: (String error, int statusCode) {
      log(error);
    }, queryParams: request.toFlatMap());

    return bannersList;
  }

  Future loadOffersPackagesDataForMainPage({@required BuildContext context, bool showLoading = true, Function completion }) async {
    var finished = 0;
    var totalCalls = 3;

    completedAll(){

      finished++;
      if(completion != null && finished == totalCalls) {
        _hideLoading(context, showLoading);
        completion();
      }
    }

    _showLoading(context, showLoading);

    // Performing Parallel Request on same time
    // # 1
    getBestSellers(request: OffersProductsRequestModel(), context: context, showLoading: false).then((value){
        completedAll();
    });

    // # 2
    getLatestOffers(request: OffersProductsRequestModel(), context: context, showLoading: false).then((value){
      completedAll();
    });

    // # 3
    getBanners(request: OffersProductsRequestModel(), context: context, showLoading: false).then((value){
      completedAll();
    });

  }

  // --------------------
  // Create Customer
  // --------------------
  Future createCustomer(PackagesCustomerRequestModel request, {@required BuildContext context, bool showLoading = true, Function(bool) completion }) async{
    if(customer != null)
      return Future.value(customer);

    customer = null;
    Future errorThrow;

    _showLoading(context, showLoading);
    var url = EXA_CART_API_BASE_URL + PACKAGES_CUSTOMER;
    await baseAppClient.simplePost(url, body: request.json(), onSuccess: (dynamic stringResponse, int statusCode){
      _hideLoading(context, showLoading);

      var jsonResponse = json.decode(stringResponse);
      var customerJson = jsonResponse['customers'].first;
      customer = PackagesCustomerResponseModel.fromJson(customerJson);

    }, onFailure: (String error, int statusCode){
      _hideLoading(context, showLoading);
      errorThrow = Future.error(error);
      log(error);
    });

    await Future.delayed(Duration(seconds: 1));

    return errorThrow ?? customer;
  }



  // --------------------
  // Shopping Cart
  // --------------------
  Future<List<PackagesCartItemsResponseModel>> cartItems({@required BuildContext context, bool showLoading = true}) async{
    Future errorThrow;

    cartItemList.clear();
    _showLoading(context, showLoading);
    var url = EXA_CART_API_BASE_URL + PACKAGES_SHOPPING_CART + '/${customer.id}';
    await baseAppClient.simpleGet(url, onSuccess: (dynamic stringResponse, int statusCode) {
      _hideLoading(context, showLoading);

      var jsonResponse = json.decode(stringResponse);
      jsonResponse['shopping_carts'].forEach((json) {
        cartItemList.add(PackagesCartItemsResponseModel.fromJson(json));
      });

    }, onFailure: (String error, int statusCode) {
      _hideLoading(context, showLoading);
      log(error);
      errorThrow = Future.error({"error":error, "statusCode":statusCode});
    }, queryParams: null);

    return errorThrow ?? cartItemList;
  }

  Future<ResponseModel<PackagesCartItemsResponseModel>> addProductToCart(AddProductToCartRequestModel request, {@required BuildContext context, bool showLoading = true}) async{
    Future errorThrow;
    ResponseModel<PackagesCartItemsResponseModel> response;

    request.customer_id = customer.id;

    _showLoading(context, showLoading);
    var url = EXA_CART_API_BASE_URL + PACKAGES_SHOPPING_CART;
    await baseAppClient.simplePost(url, body: request.json(), onSuccess: (dynamic stringResponse, int statusCode){
      _hideLoading(context, showLoading);

      var jsonResponse = json.decode(stringResponse);
      var jsonCartItem = jsonResponse["shopping_carts"][0];
      response = ResponseModel(status: true, data: PackagesCartItemsResponseModel.fromJson(jsonCartItem), error: null);
      cartItemCount = response.data.quantity.toString();

    }, onFailure: (String error, int statusCode){
      _hideLoading(context, showLoading);
      errorThrow = Future.error(ResponseModel(status: true, data: null, error: error));
    });

    return errorThrow ?? response;
  }

  Future updateProductToCart(int cartItemID, {UpdateProductToCartRequestModel request,  @required BuildContext context, bool showLoading = true}) async{
    Future errorThrow;

    _showLoading(context, showLoading);
    var url = EXA_CART_API_BASE_URL + PACKAGES_SHOPPING_CART + '/$cartItemID';
    await baseAppClient.simplePut(url, body: request.json(), onSuccess: (dynamic stringResponse, int statusCode){
      _hideLoading(context, showLoading);

      var jsonResponse = json.decode(stringResponse);

    }, onFailure: (String error, int statusCode){
      _hideLoading(context, showLoading);
      log(error);
      errorThrow = Future.error({"error":error, "statusCode":statusCode});
    });

    return errorThrow ?? bannersList;
  }


  Future<bool> deleteProductFromCart(int cartItemID, {@required BuildContext context, bool showLoading = true}) async{
    Future errorThrow;

    _showLoading(context, showLoading);
    var url = EXA_CART_API_BASE_URL + PACKAGES_SHOPPING_CART + '/$cartItemID';
    await baseAppClient.simpleDelete(url, onSuccess: (dynamic stringResponse, int statusCode){
      _hideLoading(context, showLoading);
      // var jsonResponse = json.decode(stringResponse);

    }, onFailure: (String error, int statusCode){
      _hideLoading(context, showLoading);
      log(error);
      errorThrow = Future.error({"error":error, "statusCode":statusCode});
    });

    return errorThrow ?? true;
  }

  // --------------------
  // Place Order
  // --------------------
  Future placeOrder({@required String paymentOption, @required BuildContext context, bool showLoading = true}) async{
    Future errorThrow;

    var jsonBody = {
      "order": {
        "customer_id" : customer.id,
        "billing_address": {
          "email": customer.email,
          "phone_number": customer.addresses.first.phoneNumber
        },
        "payment_method_system_name": "Payments.PayFort",
        "payment_option": paymentOption
      }
    };

    int order_id;
    _showLoading(context, showLoading);
    var url = EXA_CART_API_BASE_URL + PACKAGES_ORDERS;
    await baseAppClient.simplePost(url, body: jsonBody, onSuccess: (dynamic stringResponse, int statusCode){
      _hideLoading(context, showLoading);

      var jsonResponse = json.decode(stringResponse);
      order_id = jsonResponse['orders'][0]['id'];

    }, onFailure: (String error, int statusCode){
      _hideLoading(context, showLoading);
      log(error);
      errorThrow = Future.error(error);
    });

    return errorThrow ?? order_id;
  }

  Future<ResponseModel<PackagesOrderResponseModel>> getOrderById(int id, {@required BuildContext context, bool showLoading = true}) async{
    Future errorThrow;
    ResponseModel<PackagesOrderResponseModel> response;

    _showLoading(context, showLoading);
    var url = EXA_CART_API_BASE_URL + PACKAGES_ORDERS + '/$id';
    await baseAppClient.simpleGet(url, onSuccess: (dynamic stringResponse, int statusCode) {
      _hideLoading(context, showLoading);

      var jsonResponse = json.decode(stringResponse);
      var jsonOrder = jsonResponse['orders'][0];
      response = ResponseModel(status: true, data: PackagesOrderResponseModel.fromJson(jsonOrder));

    }, onFailure: (String error, int statusCode) {
      _hideLoading(context, showLoading);
      errorThrow = Future.error(ResponseModel(status: false,error: error));
    }, queryParams: null);

    return errorThrow ?? response;
  }

}

_showLoading(BuildContext context, bool flag){
  if(flag)
    GifLoaderDialogUtils.showMyDialog(context);
}

_hideLoading(BuildContext context, bool flag){
  if(flag)
    GifLoaderDialogUtils.hideDialog(context);
}