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

import 'package:diplomaticquarterapp/config/config.dart';
import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
import 'package:diplomaticquarterapp/core/model/ResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/hospitals/hospitals_model.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/PackagesCustomerResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/order_response_model.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/tamara_payment_option.dart';
import 'package:diplomaticquarterapp/core/service/base_service.dart';
import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:flutter/cupertino.dart';

Map<String, String> packagesAuthHeader = {};

class OffersAndPackagesServices extends BaseService {
  AuthenticatedUser patientUser;
  List<PackagesCategoriesResponseModel> categoryList = [];
  List<PackagesResponseModel> productList = [];
  List<PackagesResponseModel> latestOffersList = [];
  List<TamaraPaymentOption> tamaraPaymentOptions = [];
  List<PackagesResponseModel> bestSellerList = [];
  List<PackagesResponseModel> bannersList = [];
  List<PackagesResponseModel> ordersHistory = [];
  List<PackagesCartItemsResponseModel> cartItemList = [];
  List<HospitalsModel> _hospitals = [];
  List<HospitalsModel> get hospitals => _hospitals;
  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, headers: packagesAuthHeader, 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) {}, 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 = [];
    var url = EXA_CART_API_BASE_URL + PACKAGES_PRODUCTS;
    await baseAppClient.simpleGet(url, headers: packagesAuthHeader, 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) {}, queryParams: request.toFlatMap());

    return productList;
  }

  Future<List<TamaraPaymentOption>> getTamaraOptions({@required BuildContext context, @required bool showLoading = true}) async {
    if (tamaraPaymentOptions != null && tamaraPaymentOptions.isNotEmpty) return tamaraPaymentOptions;

    tamaraPaymentOptions.clear();
    var url = EXA_CART_API_BASE_URL + PACKAGES_TAMARA_OPT;
    await baseAppClient.simpleGet(url, headers: packagesAuthHeader, onSuccess: (dynamic stringResponse, int statusCode) {
      if (statusCode == 200) {
        var jsonResponse = json.decode(stringResponse);
        jsonResponse['payment_option'].forEach((json) {
          tamaraPaymentOptions.add(TamaraPaymentOption.fromJson(json));
        });
      }
    }, onFailure: (String error, int statusCode) {
      log(error);
    });

    return tamaraPaymentOptions;
  }

  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, headers: packagesAuthHeader, onSuccess: (dynamic stringResponse, int statusCode) {
      latestOffersList.clear();
      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, headers: packagesAuthHeader, onSuccess: (dynamic stringResponse, int statusCode) {
      bestSellerList.clear();
      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, headers: packagesAuthHeader, 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 = 2;

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

    _showLoading(context, showLoading);

    final auth_token = await baseAppClient.generatePackagesToken();
    if (auth_token == null) {
      throw 'Something went wrong while authentication, Please try again letter';
    }
    packagesAuthHeader["Authorization"] = 'Bearer $auth_token';

    // Check and Create Customer
    if (patientUser != null) {
      customer = await getCurrentCustomer(context: context, showLoading: showLoading);
      if (customer == null) {
        createCustomer(PackagesCustomerRequestModel.fromUser(patientUser), context: context);
      }
    }

    // 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, headers: packagesAuthHeader, body: request.json(), onSuccess: (dynamic stringResponse, int statusCode) {
      var jsonResponse = json.decode(stringResponse);
      var customerJson = jsonResponse['customers'].first;
      customer = PackagesCustomerResponseModel.fromJson(customerJson);
    }, onFailure: (String error, int statusCode) {
      errorThrow = Future.error(error);
      log(error);
    });

    _hideLoading(context, showLoading);
    await Future.delayed(Duration(seconds: 1));

    return errorThrow ?? customer;
  }

  Future<PackagesCustomerResponseModel> getCurrentCustomer({@required BuildContext context, bool showLoading = true}) async {
    if (customer != null) return Future.value(customer);

    _showLoading(context, showLoading);
    var url = EXA_CART_API_BASE_URL + PACKAGES_CUSTOMER + "/username/${patientUser.patientID}";
    await baseAppClient.simpleGet(url, headers: packagesAuthHeader, onSuccess: (dynamic stringResponse, int statusCode) {
      var jsonResponse = json.decode(stringResponse);
      var customerJson = jsonResponse['customers'].first;
      customer = PackagesCustomerResponseModel.fromJson(customerJson);
    }, onFailure: (String error, int statusCode) {
      log(error);
    });

    _hideLoading(context, showLoading);
    return customer;
  }

  // --------------------
  // Shopping Cart
  // --------------------
  Future<Map<String, dynamic>> 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}';
    Map<String, dynamic> jsonResponse;
    await baseAppClient.simpleGet(url, headers: packagesAuthHeader, onSuccess: (dynamic stringResponse, int statusCode) {
      _hideLoading(context, showLoading);

      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 ?? jsonResponse;
  }

  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, headers: packagesAuthHeader, 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 = (jsonResponse['count'] ?? 0).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, headers: packagesAuthHeader, 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, headers: packagesAuthHeader, onSuccess: (dynamic stringResponse, int statusCode) {
      _hideLoading(context, showLoading);
    }, 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 Map<dynamic, dynamic> paymentParams, @required int projectID, @required BuildContext context, bool showLoading = true}) async {
    Future errorThrow;

    Map<dynamic, dynamic> jsonBody = {
      "customer_id": customer.id,
      "project_id": projectID,
      "billing_address": {"email": patientUser.emailAddress, "phone_number": patientUser.mobileNumber},
    };
    jsonBody.addAll(paymentParams);
    jsonBody = {'order': jsonBody};

    print(jsonBody);

    int order_id;
    _showLoading(context, showLoading);
    var url = EXA_CART_API_BASE_URL + PACKAGES_ORDERS;
    await baseAppClient.simplePost(url, headers: packagesAuthHeader, 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;
  }

  // --------------------
  // Order History
  // --------------------
  Future<List<PackagesResponseModel>> orderHistory({@required BuildContext context, bool showLoading = true}) async {
    // if(ordersHistory.isNotEmpty)
    //   return ordersHistory;

    Future errorThrow;
    // https://mdlaboratories.com/offersdiscounts/api/orders/items/0535256053?fields=id,product,utilize_by_vida,valid_until_date_utc,order_id&page=1&limit=100
    Map<String, dynamic> queryParams ={};
    queryParams['fields'] = 'id,product,utilize_by_vida,valid_until_date_utc,order_id';
    queryParams['page'] = "1";
    queryParams['limit'] = "100";
    print(queryParams);

    _showLoading(context, showLoading);
    var url = EXA_CART_API_BASE_URL + PACKAGES_ORDER_HISTORY + "/${user.mobileNumber}";

    await baseAppClient.simpleGet(url, headers: packagesAuthHeader, queryParams: queryParams, onSuccess: (dynamic stringResponse, int statusCode) {
      _hideLoading(context, showLoading);
      var jsonResponse = json.decode(stringResponse);
      final order_items = jsonResponse["order_items"] as List;
      ordersHistory = order_items.map((e) => PackagesResponseModel().fromJson(e['product'])).toList();
      print(ordersHistory);

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

    return errorThrow ?? ordersHistory;
  }

  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, headers: packagesAuthHeader, 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;
  }

  Future getHospitals({bool isResBasedOnLoc = true}) async {
    Map<String, dynamic> body = Map();
    body['Latitude'] = await this.sharedPref.getDouble(USER_LAT);
    body['Longitude'] = await this.sharedPref.getDouble(USER_LONG);
    body['IsOnlineCheckIn'] = isResBasedOnLoc;
    body['PatientOutSA'] = 0;

    await baseAppClient.post(GET_PROJECT,
        onSuccess: (dynamic response, int statusCode) {
          _hospitals.clear();
          response['ListProject'].forEach((hospital) {
            _hospitals.add(HospitalsModel.fromJson(hospital));
          });
        }, onFailure: (String error, int statusCode) {
          hasError = true;
          super.error = error;
        }, body: body);
  }

}

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

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