import 'package:get/get.dart';
import 'package:mypoint_flutter_app/core/network/api/location_api.dart' deferred as location_api;
import '../../shared/widgets/base_view/base_response_model.dart';
import '../../core/network/restful_api_viewmodel.dart';
import 'location_address_screen.dart';
import 'models/district_address_model.dart';
import 'models/province_address_model.dart';

class AddressBaseModel {
  final String? code;
  final String? name;
  AddressBaseModel({this.code, this.name});
}

class LocationAddressViewModel extends RestfulApiViewModel {
  List<AddressBaseModel> _allItems = [];
  final RxList<AddressBaseModel> displayItems = <AddressBaseModel>[].obs;
  final RxString selectedCode = ''.obs;
  LocationAddressType type = LocationAddressType.province;
  String provinceCode = '';

  bool _locationApiLoaded = false;

  Future<void> _ensureLocationApiLoaded() async {
    if (_locationApiLoaded) return;
    await location_api.loadLibrary();
    _locationApiLoaded = true;
  }

  Future<BaseResponseModel<T>> _callLocationApi<T>(Future<BaseResponseModel<T>> Function(dynamic api) fn) async {
    await _ensureLocationApiLoaded();
    final api = location_api.LocationApi(client);
    return fn(api);
  }

  LocationAddressViewModel({this.type = LocationAddressType.province, this.provinceCode = ''});

  @override
  void onInit() {
    super.onInit();
    if (type == LocationAddressType.province) {
      callApi<ProvinceAddressResponse>(
        request: () => _callLocationApi((api) => api.locationProvinceGetList()),
        onSuccess: (data, _) {
          _loadFromProvince(data.items ?? []);
        },
        withLoading: false,
      );
    } else {
      callApi<DistrictAddressResponse>(
        request: () => _callLocationApi((api) => api.locationDistrictGetList(provinceCode)),
        onSuccess: (data, _) {
          _loadFromDistrict(data.items ?? []);
        },
        withLoading: false,
      );
    }
  }

  void _loadFromProvince(List<ProvinceAddressModel> provinces) {
    _allItems = provinces.map((e) => AddressBaseModel(code: e.cityCode, name: e.cityName)).toList();
    displayItems.assignAll(_allItems);
  }

  void _loadFromDistrict(List<DistrictAddressModel> districts) {
    _allItems = districts.map((e) => AddressBaseModel(code: e.districtCode, name: e.districtName)).toList();
    displayItems.assignAll(_allItems);
  }

  void search(String query) {
    if (query.isEmpty) {
      displayItems.assignAll(_allItems);
      return;
    }
    final lowerQuery = _removeDiacritics(query).toLowerCase();
    final filteredItems =
        _allItems.where((item) {
          final name = item.name ?? '';
          final normalized = _removeDiacritics(name).toLowerCase();
          return normalized.contains(lowerQuery);
        }).toList();
    displayItems.assignAll(filteredItems);
  }

  void select(AddressBaseModel item) {
    selectedCode.value = item.code ?? '';
    displayItems.refresh();
    Get.back(result: item);
  }

  String _removeDiacritics(String str) {
    const withDiacritics =
        'àáảãạâầấẩẫậăằắẳẵặèéẻẽẹêềếểễệìíỉĩịòóỏõọôồốổỗộơờớởỡợùúủũụưừứửữựỳýỷỹỵđ'
        'ÀÁẢÃẠÂẦẤẨẪẬĂẰẮẲẴẶÈÉẺẼẸÊỀẾỂỄỆÌÍỈĨỊÒÓỎÕỌÔỒỐỔỖỘƠỜỚỞỠỢÙÚỦŨỤƯỪỨỬỮỰỲÝỶỸỴĐ';
    const withoutDiacritics =
        'aaaaaaaaaaaaaaaaaeeeeeeeeeeeiiiiiooooooooooooooooouuuuuuuuuuuyyyyyd'
        'AAAAAAAAAAAAAAAAAEEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOOOUUUUUUUUUUUYYYYYD';

    for (int i = 0; i < withDiacritics.length; i++) {
      str = str.replaceAll(withDiacritics[i], withoutDiacritics[i]);
    }
    return str;
  }
}
