import 'package:get/get.dart';
import 'package:get/get_rx/src/rx_types/rx_types.dart';
import 'package:mypoint_flutter_app/core/network/api/product_api.dart' deferred as product_api;
import 'package:mypoint_flutter_app/shared/preferences/data_preference.dart';
import 'package:mypoint_flutter_app/features/topup/models/brand_network_model.dart';
import '../../shared/widgets/base_view/base_response_model.dart';
import '../../core/network/restful_api_viewmodel.dart';
import '../../core/services/contact_storage_service.dart';
import '../voucher/models/product_brand_model.dart';
import '../voucher/models/product_model.dart';
import '../voucher/models/product_type.dart';

class TopUpViewModel extends RestfulApiViewModel {
  final RxList<String> histories = <String>[].obs;
  final RxList<ProductBrandModel> topUpBrands = <ProductBrandModel>[].obs;
  final RxList<ProductModel> products = <ProductModel>[].obs;
  var selectedBrand = Rxn<ProductBrandModel>();
  var selectedProduct = Rxn<ProductModel>();
  final Map<String, List<ProductModel>> _allValue = {};
  var phoneNumber = ''.obs;
  bool _productApiLoaded = false;

  Future<void> _ensureProductApiLoaded() async {
    if (_productApiLoaded) return;
    await product_api.loadLibrary();
    _productApiLoaded = true;
  }

  Future<BaseResponseModel<T>> _callProductApi<T>(Future<BaseResponseModel<T>> Function(dynamic api) fn) async {
    await _ensureProductApiLoaded();
    final api = product_api.ProductApi(client);
    return fn(api);
  }

  @override
  void onInit() {
    super.onInit();
    final myPhone = DataPreference.instance.phone ?? '';
    phoneNumber.value = myPhone;
    ContactStorageService().getUsedContacts().then((value) {
      if (value.isNotEmpty) {
        histories.assignAll(value);
      } else {
        histories.assignAll([myPhone]);
      }
    });
    if (!histories.contains(myPhone)) {
      histories.insert(0, myPhone);
      ContactStorageService().saveUsedContact(myPhone);
    }
  }

  Future<void> firstLoadTopUpData() async {
    _getTopUpBrands();
  }

  Future<void> _getTopUpBrands() async {
    await callApi<List<ProductBrandModel>>(
      request: () => _callProductApi((api) => api.getTopUpBrands(ProductType.topupMobile)),
      onSuccess: (data, _) {
        topUpBrands.assignAll(data);
        checkMobileNetwork();
      },
      showAppNavigatorDialog: true,
    );
  }

  Future<void> checkMobileNetwork() async {
    await callApi<BrandNameCheckResponse>(
      request: () => _callProductApi((api) => api.checkMobileNetwork(phoneNumber.value)),
      onSuccess: (data, _) {
        final brandCode = data.brand ?? '';
        var brand = topUpBrands.isNotEmpty
            ? topUpBrands.firstWhere(
              (brand) => brand.code == brandCode,
          orElse: () => topUpBrands.first,
        ) : topUpBrands.firstOrNull;
        selectedBrand.value = brand;
        getTelcoDetail();
      },
      showAppNavigatorDialog: true,
    );
  }

  Future<void> getTelcoDetail({String? selected}) async {
    final code = selectedBrand.value?.code;
    final id = selectedBrand.value?.id;
    if (code == null || id == null) return;
    void makeSelected(List<ProductModel> list) {
      bool didSelect = false;
      if (selected != null && selected.isNotEmpty) {
        for (var item in list) {
          final isMatch = item.id == int.tryParse(selected);
          if (isMatch) {
            selectedProduct.value = item;
            didSelect = true;
          }
        }
      }
      // Nếu chưa có item nào được chọn → mặc định chọn 100k
      if (!didSelect && selectedProduct.value == null) {
         final item100k = list.isNotEmpty
            ? list.firstWhere(
              (e) => e.amountToBePaid == 100000,
          orElse: () => list.first,
        ) : null;
        selectedProduct.value = item100k;
      }
    }
    // Dùng cache nếu có
    if (_allValue.containsKey(code)) {
      final cached = _allValue[code]!;
      products.assignAll(cached);
      makeSelected(cached);
      return;
    }
    final body = {
      "type": ProductType.topupMobile.value,
      "size": 200,
      "index": 0,
      "brand_id": selectedBrand.value?.id ?? 0,
    };
    await callApi<List<ProductModel>>(
      request: () => _callProductApi((api) => api.getProducts(body)),
      onSuccess: (data, _) {
        _allValue[code] = data;
        products.assignAll(data);
        makeSelected(data);
      },
      showAppNavigatorDialog: true,
    );
  }
}
