import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart';
import '../../networking/restful_api_viewmodel.dart';
import '../affiliate/model/affiliate_brand_model.dart';
import '../faqs/faqs_model.dart';
import '../voucher/models/product_model.dart';
import 'models/achievement_model.dart';
import 'models/banner_model.dart';
import 'models/brand_model.dart';
import 'models/flash_sale_model.dart';
import 'models/header_section_type.dart';
import 'models/hover_data_model.dart';
import 'models/main_section_config_model.dart';
import 'models/main_service_model.dart';
import 'models/my_product_model.dart';

class HomeTabViewModel extends RestfulApiViewModel {
  final RxList<ProductModel> products = <ProductModel>[].obs;
  final RxList<PageItemModel> news = <PageItemModel>[].obs;
  final RxList<MainServiceModel> services = <MainServiceModel>[].obs;
  final RxList<AchievementModel> achievements = <AchievementModel>[].obs;
  final RxList<BannerModel> banners = <BannerModel>[].obs;
  final RxList<BrandModel> brands = <BrandModel>[].obs;
  final RxList<AffiliateBrandModel> affiliates = <AffiliateBrandModel>[].obs;
  final RxList<MyProductModel> myProducts = <MyProductModel>[].obs;
  final RxList<MainSectionConfigModel> sectionLayouts = <MainSectionConfigModel>[].obs;
  final Rxn<FlashSaleModel> flashSaleData = Rxn<FlashSaleModel>();
  final Rxn<HoverDataModel> hoverData = Rxn<HoverDataModel>();

  late final Map<HeaderSectionType, Future<void> Function(MainSectionConfigModel)> _sectionLoaders;

  @override
  void onInit() {
    super.onInit();
    _sectionLoaders = {
      HeaderSectionType.topButton: _loadTopButtons,
      HeaderSectionType.banner: _loadBanners,
      HeaderSectionType.campaign: _loadCampaigns,
      HeaderSectionType.product: _loadProducts,
      HeaderSectionType.news: _loadNews,
      HeaderSectionType.flashSale: _loadFlashSale,
      HeaderSectionType.brand: _loadBrands,
      HeaderSectionType.pointPartner: _loadAffiliateBrands,
      HeaderSectionType.myProduct: _loadMyProducts,
    };
    getSectionLayoutHome();
    loadDataPiPiHome();
  }

  MainSectionConfigModel? getMainSectionConfigModel(HeaderSectionType type) {
    return sectionLayouts.firstWhereOrNull((section) => section.headerSectionType == type);
  }

  Future<void> getSectionLayoutHome({bool showLoading = true}) async {
    await callApi<List<MainSectionConfigModel>>(
      request: () => client.getSectionLayoutHome(),
      onSuccess: (data, _) => _resolveSectionLayouts(data),
      onFailure: (message, response, error) async => _resolveSectionLayouts(await _loadSectionLayoutHomeFromCache()),
      withLoading: showLoading,
    );
  }

  Future<void> loadDataPiPiHome() async {
    await callApi<HoverDataModel>(
      request: () => client.getDataPiPiHome(),
      onSuccess: (data, _) {
        hoverData.value = data;
      },
      withLoading: false,
    );
  }

  Future<List<MainSectionConfigModel>> _loadSectionLayoutHomeFromCache() async {
    final jsonStr = await rootBundle.loadString('assets/data/main_layout_section_home.json');
    final List<dynamic> jsonList = json.decode(jsonStr);
    return jsonList.map((e) => MainSectionConfigModel.fromJson(e)).toList();
  }

  Future<void> _resolveSectionLayouts(List<MainSectionConfigModel> layouts) async {
    final resolved = layouts.isEmpty ? await _loadSectionLayoutHomeFromCache() : layouts;
    sectionLayouts.assignAll(resolved);
    await _processSections(resolved);
  }

  Future<void> _processSections(List<MainSectionConfigModel> sections) async {
    final futures = <Future<void>>[];
    for (final section in sections) {
      final loader = _sectionLoaders[section.headerSectionType];
      if (loader != null) {
        futures.add(loader(section));
      } else {
        debugPrint('HomeTabViewModel: Unsupported section type ${section.headerSectionType}');
      }
    }
    await Future.wait(futures);
  }

  Future<void> _loadTopButtons(MainSectionConfigModel section) async {
    final res = await client.fetchList<MainServiceModel>(
      section.apiList ?? '',
      (json) => MainServiceModel.fromJson(json as Map<String, dynamic>),
    );
    services.assignAll(res.data ?? []);
  }

  Future<void> _loadBanners(MainSectionConfigModel section) async {
    final res = await client.fetchList<BannerModel>(
      section.apiList ?? '',
      (json) => BannerModel.fromJson(json as Map<String, dynamic>),
    );
    banners.assignAll(res.data ?? []);
  }

  Future<void> _loadCampaigns(MainSectionConfigModel section) async {
    final res = await client.fetchList<AchievementModel>(
      section.apiList ?? '',
      (json) => AchievementModel.fromJson(json as Map<String, dynamic>),
    );
    achievements.assignAll(res.data ?? []);
  }

  Future<void> _loadProducts(MainSectionConfigModel section) async {
    final res = await client.fetchList<ProductModel>(
      section.apiList ?? '',
      (json) => ProductModel.fromJson(json as Map<String, dynamic>),
    );
    products.assignAll(res.data ?? []);
  }

  Future<void> _loadNews(MainSectionConfigModel section) async {
    final res = await client.fetchList<PageItemModel>(
      section.apiList ?? '',
      (json) => PageItemModel.fromJson(json as Map<String, dynamic>),
    );
    news.assignAll(res.data ?? []);
  }

  Future<void> _loadFlashSale(MainSectionConfigModel section) async {
    final res = await client.fetchObject<FlashSaleModel>(
      section.apiList ?? '',
      (json) => FlashSaleModel.fromJson(json as Map<String, dynamic>),
    );
    flashSaleData.value = res.data;
  }

  Future<void> refreshFlashSale() async {
    final section = getMainSectionConfigModel(HeaderSectionType.flashSale);
    if (section == null) return;
    await _loadFlashSale(section);
  }

  Future<void> _loadBrands(MainSectionConfigModel section) async {
    final res = await client.fetchList<BrandModel>(
      section.apiList ?? '',
      (json) => BrandModel.fromJson(json as Map<String, dynamic>),
    );
    brands.assignAll(res.data ?? []);
  }

  Future<void> _loadAffiliateBrands(MainSectionConfigModel section) async {
    final res = await client.fetchList<AffiliateBrandModel>(
      section.apiList ?? '',
      (json) => AffiliateBrandModel.fromJson(json as Map<String, dynamic>),
    );
    affiliates.assignAll((res.data ?? []).take(6).toList());
  }

  Future<void> _loadMyProducts(MainSectionConfigModel section) async {
    final res = await client.fetchList<MyProductModel>(
      section.apiList ?? '',
      (json) => MyProductModel.fromJson(json as Map<String, dynamic>),
    );
    myProducts.assignAll(res.data ?? []);
  }
}
