import 'package:get/get_rx/src/rx_types/rx_types.dart';
import 'package:mypoint_flutter_app/core/network/api/affiliate_api.dart' deferred as affiliate_api;
import '../../shared/widgets/base_view/base_response_model.dart';
import '../../core/network/restful_api_viewmodel.dart';
import '../home/models/banner_model.dart';
import 'model/affiliate_brand_model.dart';
import 'model/affiliate_category_model.dart';
import 'model/affiliate_category_type.dart';
import 'model/affiliate_product_top_sale_model.dart';
import 'model/cashback_overview_model.dart';

class AffiliateTabViewModel extends RestfulApiViewModel {
  final RxList<BannerModel> banners = <BannerModel>[].obs;
  final RxList<AffiliateBrandModel> affiliateBrands = <AffiliateBrandModel>[].obs;
  final RxList<AffiliateCategoryModel> affiliateCategories = <AffiliateCategoryModel>[].obs;
  final RxList<AffiliateCategoryModel> allAffiliateCategories = <AffiliateCategoryModel>[].obs;
  final RxList<AffiliateProductTopSaleModel> affiliateProducts = <AffiliateProductTopSaleModel>[].obs;
  final Rxn<CashbackOverviewModel> overview = Rxn<CashbackOverviewModel>();
  void Function((List<AffiliateBrandModel>, String) data)? onShowAffiliateBrandPopup;

  bool _affiliateLibLoaded = false;

  Future<void> _ensureAffiliateLibraryLoaded() async {
    if (_affiliateLibLoaded) return;
    await affiliate_api.loadLibrary();
    _affiliateLibLoaded = true;
  }

  Future<BaseResponseModel<T>> _callAffiliate<T>(Future<BaseResponseModel<T>> Function(dynamic api) fn) async {
    await _ensureAffiliateLibraryLoaded();
    final api = affiliate_api.AffiliateApi(client);
    return fn(api);
  }

  bool get isDataAvailable {
    return affiliateBrands.isNotEmpty || affiliateCategories.isNotEmpty || affiliateProducts.isNotEmpty;
  }

  Future<void> refreshData({bool isShowLoading = true}) async {
    if (isShowLoading && isDataAvailable) return;
    if (isShowLoading) showLoading();
    await Future.wait([
      _getAffiliateOverview(),
      _getAffiliateBrandGetList(),
      _getAffiliateBanners(),
      _getAffiliateCategoryGetList(),
      _getAffiliateProductTopSale(),
    ]);
    if (isShowLoading) hideLoading();
  }

  Future<void> _getAffiliateBrandGetList() async {
    await callApi<List<AffiliateBrandModel>>(
      request: () => _callAffiliate((api) => api.affiliateBrandGetList()),
      onSuccess: (data, _) {
        affiliateBrands.assignAll(data);
      },
      onFailure: (msg, _, _) async {
        affiliateBrands.clear();
      },
      withLoading: false,
    );
  }

  Future<void> _getAffiliateCategoryGetList() async {
    await callApi<List<AffiliateCategoryModel>>(
      request: () => _callAffiliate((api) => api.affiliateCategoryGetList()),
      onSuccess: (data, _) {
        final category = AffiliateCategoryModel(code: AffiliateCategoryType.other, name: "Khác");
        final results = data;
        allAffiliateCategories.assignAll(results);

        final limitedData = results.take(7).toList();
        limitedData.add(category);
        affiliateCategories.assignAll(limitedData);
      },
      onFailure: (msg, _, _) async {
        affiliateCategories.clear();
        allAffiliateCategories.clear();
      },
      withLoading: false,
    );
  }

  Future<void> _getAffiliateProductTopSale() async {
    await callApi<List<AffiliateProductTopSaleModel>>(
      request: () => _callAffiliate((api) => api.affiliateProductTopSale()),
      onSuccess: (data, _) {
        affiliateProducts.assignAll(data);
      },
      onFailure: (msg, _, _) async {
        affiliateProducts.clear();
      },
      withLoading: false,
    );
  }

  Future<void> _getAffiliateBanners() async {
    await callApi<List<BannerModel>>(
      request: () => _callAffiliate((api) => api.affiliateGetBanners()),
      onSuccess: (data, _) {
        banners.assignAll(data);
      },
      onFailure: (msg, _, _) async {
        banners.clear();
      },
      withLoading: false,
    );
  }

  Future<void> _getAffiliateOverview() async {
    await callApi<CashbackOverviewModel>(
      request: () => _callAffiliate((api) => api.getCashBackOverview()),
      onSuccess: (data, _) {
        overview.value = data;
      },
      onFailure: (msg, _, _) async {
        overview.value = null;
      },
      withLoading: false,
    );
  }

  Future<void> affiliateBrandGetListBuyCategory(AffiliateCategoryModel category) async {
    await callApi<List<AffiliateBrandModel>>(
      request:
          () => _callAffiliate(
            (api) => api.affiliateBrandGetList(categoryCode: AffiliateCategoryModel.codeToJson(category.code)),
          ),
      onSuccess: (data, _) {
        if (data.isNotEmpty) {
          onShowAffiliateBrandPopup?.call((data, category.name));
        }
      },
    );
  }
}
