import '../../../app/config/api_paths.dart';
import '../../../shared/widgets/base_view/base_response_model.dart';
import '../../../app/config/callbacks.dart';
import '../../../features/data_network_service/product_network_data_model.dart';
import '../../../features/voucher/models/my_product_model.dart';
import '../../../features/mobile_card/models/mobile_service_redeem_data.dart';
import '../../../features/mobile_card/models/product_mobile_card_model.dart';
import '../../../features/mobile_card/models/usable_voucher_model.dart';
import '../../../features/topup/models/brand_network_model.dart';
import '../../../features/traffic_service/traffic_service_model.dart';
import '../../../features/transaction/model/order_product_payment_response_model.dart';
import '../../../features/transaction/model/payment_bank_account_info_model.dart';
import '../../../features/transaction/model/payment_method_model.dart';
import '../../../features/transaction/model/preview_order_payment_model.dart';
import '../../../features/voucher/models/like_product_response_model.dart';
import '../../../features/voucher/models/my_mobile_card_response.dart';
import '../../../features/voucher/models/my_product_status_type.dart';
import '../../../features/voucher/models/product_brand_model.dart';
import '../../../features/voucher/models/product_model.dart';
import '../../../features/voucher/models/product_store_model.dart';
import '../../../features/voucher/models/product_type.dart';
import '../../../features/voucher/models/search_product_response_model.dart';
import '../../../shared/preferences/data_preference.dart';
import '../restful_api_client.dart';

class ProductApi {
  ProductApi(this.client);

  final RestfulAPIClient client;

  Future<BaseResponseModel<List<ProductModel>>> getProducts(Json body) {
    return client.requestNormal(APIPaths.getProducts, Method.GET, body, (data) {
      final list = data as List<dynamic>;
      return list.map((e) => ProductModel.fromJson(e)).toList();
    });
  }

  Future<BaseResponseModel<SearchProductResponseModel>> getSearchProducts(Json body) {
    return client.requestNormal(
      APIPaths.getSearchProducts,
      Method.POST,
      body,
      (data) => SearchProductResponseModel.fromJson(data as Json),
    );
  }

  Future<BaseResponseModel<List<ProductModel>>> productsCustomerLikes(Json body) {
    return client.requestNormal(APIPaths.productsCustomerLikes, Method.GET, body, (data) {
      final list = data as List<dynamic>;
      return list.map((e) => ProductModel.fromJson(e)).toList();
    });
  }

  Future<BaseResponseModel<ProductModel>> getProduct(int id) {
    final path = APIPaths.getProductDetail.replaceAll('%@', id.toString());
    return client.requestNormal(path, Method.GET, const {}, (data) => ProductModel.fromJson(data as Json));
  }

  Future<BaseResponseModel<ProductModel>> getCustomerProductDetail(int id) {
    final path = APIPaths.getCustomerProductDetail.replaceAll('%@', id.toString());
    return client.requestNormal(path, Method.GET, const {}, (data) => ProductModel.fromJson(data as Json));
  }

  Future<BaseResponseModel<List<ProductStoreModel>>> getProductStores(int id) {
    final body = {'product_id': id, 'size': 20, 'index': 0};
    return client.requestNormal(APIPaths.getProductStores, Method.GET, body, (data) {
      final list = data as List<dynamic>;
      return list.map((e) => ProductStoreModel.fromJson(e)).toList();
    });
  }

  Future<BaseResponseModel<LikeProductResponseModel>> likeProduct(int id) {
    final body = {'product_id': id};
    return client.requestNormal(APIPaths.productCustomerLikes, Method.POST, body, (data) {
      return LikeProductResponseModel.fromJson(data as Json);
    });
  }

  Future<BaseResponseModel<EmptyCodable>> unlikeProduct(int id) {
    final path = APIPaths.productCustomerUnlikes.replaceAll('%@', id.toString());
    return client.requestNormal(path, Method.DELETE, const {}, (data) => EmptyCodable.fromJson(data as Json));
  }

  Future<BaseResponseModel<List<EmptyCodable>>> verifyOrderProduct(Json body) {
    return client.requestNormal(APIPaths.verifyOrderProduct, Method.POST, body, (data) {
      final list = data as List<dynamic>;
      return list.map((e) => EmptyCodable.fromJson(e)).toList();
    });
  }

  Future<BaseResponseModel<PreviewOrderPaymentModel>> getPreviewOrderInfo(Json body) {
    return client.requestNormal(
      APIPaths.getPreviewOrderInfo,
      Method.POST,
      body,
      (data) => PreviewOrderPaymentModel.fromJson(data as Json),
    );
  }

  Future<BaseResponseModel<List<PaymentBankAccountInfoModel>>> getPreviewOrderBankAccounts() {
    return client.requestNormal(APIPaths.getPreviewOrderBankAccounts, Method.GET, const {}, (data) {
      final list = data as List<dynamic>;
      return list.map((e) => PaymentBankAccountInfoModel.fromJson(e)).toList();
    });
  }

  Future<BaseResponseModel<List<PaymentMethodModel>>> getPreviewPaymentMethods() {
    return client.requestNormal(APIPaths.getPreviewPaymentMethods, Method.GET, const {}, (data) {
      final list = data as List<dynamic>;
      return list.map((e) => PaymentMethodModel.fromJson(e)).toList();
    });
  }

  Future<BaseResponseModel<OrderProductPaymentResponseModel>> orderSubmitPayment({
    required List<ProductModel> products,
    required int quantity,
    required String requestId,
    int? point,
    int? cash,
    PaymentMethodModel? method,
    int? paymentTokenId,
    bool? saveToken,
    String? metadata,
    String? targetPhoneNumber,
  }) {
    final items =
        products.map((product) {
          return {
            'product_id': product.id,
            'product_type': product.type ?? '',
            'quantity': quantity,
            'target_phone_number': targetPhoneNumber ?? '',
          };
        }).toList();
    final Map<String, dynamic> params = {'request_id': requestId, 'items': items, 'flow': '21'};
    final firstProduct = products.first;
    if (firstProduct.previewFlashSale?.isFlashSalePrice == true && firstProduct.previewFlashSale?.id != null) {
      params['flash_sale_id'] = firstProduct.previewFlashSale!.id;
    }
    if (method != null) {
      params['payment_method'] = method.code;
    }
    if (point != null && point != 0) {
      params['pay_point'] = point;
    }
    if (cash != null && cash != 0) {
      params['pay_cash'] = cash;
    }
    if (paymentTokenId != null) {
      params['payment_token_id'] = paymentTokenId;
    }
    if (saveToken != null) {
      params['save_token'] = saveToken;
    }
    if (metadata != null) {
      params['metadata'] = metadata;
    }
    return client.requestNormal(APIPaths.orderSubmitPayment, Method.POST, params, (data) {
      return OrderProductPaymentResponseModel.fromJson(data as Json);
    });
  }

  Future<BaseResponseModel<List<MyProductModel>>> getCustomerProducts(Json body) {
    return client.requestNormal(APIPaths.getCustomerProducts, Method.GET, body, (data) {
      final list = data as List<dynamic>;
      return list.map((e) => MyProductModel.fromJson(e)).toList();
    });
  }

  Future<BaseResponseModel<List<ProductBrandModel>>> getTopUpBrands(ProductType type) {
    final body = {'type': type.value};
    return client.requestNormal(APIPaths.getTopUpBrands, Method.GET, body, (data) {
      final list = data as List<dynamic>;
      return list.map((e) => ProductBrandModel.fromJson(e)).toList();
    });
  }

  Future<BaseResponseModel<List<ProductBrandModel>>> productTopUpBrands() {
    final body = {'topup_type': 'PRODUCT_MODEL_MOBILE_SERVICE', 'page_size': '999', 'page_index': 0};
    return client.requestNormal(APIPaths.productTopUpsBrands, Method.GET, body, (data) {
      final list = data as List<dynamic>;
      return list.map((e) => ProductBrandModel.fromJson(e)).toList();
    });
  }

  Future<BaseResponseModel<BrandNameCheckResponse>> checkMobileNetwork(String phone) {
    final body = {'phone': phone};
    return client.requestNormal(APIPaths.checkMobileNetwork, Method.GET, body, (data) {
      return BrandNameCheckResponse.fromJson(data as Json);
    });
  }

  Future<BaseResponseModel<ProductMobileCardResponse>> productMobileCardGetList() {
    final token = DataPreference.instance.token ?? '';
    final body = {'start': 0, 'limit': 200, 'access_token': token};
    return client.requestNormal(APIPaths.productMobileCardGetList, Method.POST, body, (data) {
      return ProductMobileCardResponse.fromJson(data as Json);
    });
  }

  Future<BaseResponseModel<MobileServiceRedeemData>> redeemMobileCard(String productId) {
    final token = DataPreference.instance.token ?? '';
    final body = {'product_id': productId, 'get_customer_balance': '1', 'access_token': token};
    return client.requestNormal(APIPaths.redeemMobileCard, Method.POST, body, (data) {
      return MobileServiceRedeemData.fromJson(data as Json);
    });
  }

  Future<BaseResponseModel<RedeemProductResponseModel>> getMobileCardCode(String itemId) {
    final token = DataPreference.instance.token ?? '';
    final body = {'product_item_id': itemId, 'access_token': token};
    return client.requestNormal(APIPaths.getMobileCardCode, Method.POST, body, (data) {
      return RedeemProductResponseModel.fromJson(data as Json);
    });
  }

  Future<BaseResponseModel<List<TopUpNetworkDataModel>>> getNetworkProducts(String brandId) {
    final body = {
      'brand_id': brandId,
      'topup_type': 'PRODUCT_MODEL_MOBILE_SERVICE',
      'page_size': '999',
      'page_index': 0,
    };
    return client.requestNormal(APIPaths.getNetworkProducts, Method.GET, body, (data) {
      final list = data as List<dynamic>;
      return list.map((e) => TopUpNetworkDataModel.fromJson(e)).toList();
    });
  }

  Future<BaseResponseModel<EmptyCodable>> redeemProductTopUps(int productId, String phoneNumber) {
    final token = DataPreference.instance.token ?? '';
    final body = {
      'access_token': token,
      'product_id': productId,
      'quantity': 1,
      'phone_number': phoneNumber,
      'lang': 'vi',
    };
    return client.requestNormal(APIPaths.redeemProductTopUps, Method.POST, body, (data) {
      return EmptyCodable.fromJson(data as Json);
    });
  }

  Future<BaseResponseModel<MyVoucherResponse>> getMyMobileCards(MyProductStatusType status, Json body) {
    final token = DataPreference.instance.token ?? '';
    body['access_token'] = token;
    body['product_model_code'] = 'PRODUCT_MODEL_MOBILE_CARD';
    body['list_order'] = 'DESC';
    var path = '';
    switch (status) {
      case MyProductStatusType.waiting:
        path = APIPaths.getMyProductGetWaitingList;
      case MyProductStatusType.used:
        path = APIPaths.getMyProductGetUsedList;
      case MyProductStatusType.expired:
        path = APIPaths.getMyProductGetExpiredList;
    }
    return client.requestNormal(path, Method.POST, body, (data) {
      return MyVoucherResponse.fromJson(data as Json);
    });
  }

  Future<BaseResponseModel<EmptyCodable>> myProductMarkAsUsed(String id) {
    final token = DataPreference.instance.token ?? '';
    final body = {'product_item_id': id, 'lang': 'vi', 'access_token': token};
    return client.requestNormal(APIPaths.myProductMarkAsUsed, Method.POST, body, (data) {
      return EmptyCodable.fromJson(data as Json);
    });
  }

  Future<BaseResponseModel<EmptyCodable>> myProductMarkAsNotUsedYet(String id) {
    final token = DataPreference.instance.token ?? '';
    final body = {'product_item_id': id, 'lang': 'vi', 'access_token': token};
    return client.requestNormal(APIPaths.myProductMarkAsNotUsedYet, Method.POST, body, (data) {
      return EmptyCodable.fromJson(data as Json);
    });
  }

  Future<BaseResponseModel<TrafficServiceResponseModel>> getProductVnTraSold(Json body) {
    return client.requestNormal(APIPaths.getProductVnTraSold, Method.GET, body, (data) {
      return TrafficServiceResponseModel.fromJson(data as Json);
    });
  }
}
