import 'package:flutter/cupertino.dart';
import 'package:rasadyar_chicken/data/models/request/create_steward_free_bar/create_steward_free_bar.dart';
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_bar/steward_free_bar.dart';
import 'package:rasadyar_chicken/presentation/pages/steward/buy/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/steward/root/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/steward/sale/logic.dart';
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
import 'package:rasadyar_core/core.dart';

class BuyOutOfProvinceLogic extends GetxController {
  late List<String> routesName;
  RxBool isSubmitButtonEnabled = false.obs;
  RxInt expandedListIndex = (-1).obs;

  final RxInt currentPage = 1.obs;
  final RxBool isLoadingMoreAllocationsMade = false.obs;
  final RxBool isOnLoadingSubmitOrEdit = false.obs;

  //TODO add this to Di
  ImagePicker imagePicker = ImagePicker();

  Rx<Resource<PaginationModel<StewardFreeBar>>> purchaseOutOfProvinceList =
      Resource<PaginationModel<StewardFreeBar>>.loading().obs;
  Rxn<ProductModel> selectedProduct = Rxn();

  RxList<IranProvinceCityModel> cites = <IranProvinceCityModel>[].obs;
  Rxn<IranProvinceCityModel> selectedProvince = Rxn();
  Rxn<IranProvinceCityModel> selectedCity = Rxn();
  Rxn<XFile> selectedImage = Rxn<XFile>();
  RxnString _base64Image = RxnString();
  RxnString editImageUrl = RxnString();
  RxnString editFreeBarKey = RxnString();

  StewardRootLogic rootLogic = Get.find<StewardRootLogic>();

  BuyLogic buyLogic = Get.find<BuyLogic>();

  SaleLogic outOfTheProvinceLogic = Get.find<SaleLogic>();

  GlobalKey<FormState> formKey = GlobalKey<FormState>();
  TextEditingController sellerNameController = TextEditingController();
  TextEditingController sellerPhoneController = TextEditingController();
  TextEditingController carcassWeightController = TextEditingController();
  TextEditingController carcassCountController = TextEditingController();

  Rx<Jalali> fromDateFilter = Jalali.now().obs;
  Rx<Jalali> toDateFilter = Jalali.now().obs;
  RxnString searchedValue = RxnString();

  @override
  void onInit() {
    super.onInit();
    routesName = [...buyLogic.routesName, 'خارج استان'].toList();
  }

  @override
  void onReady() {
    super.onReady();
    getStewardPurchaseOutOfProvince();
    selectedProvince.listen((p0) => getCites());

    selectedProduct.value = rootLogic.rolesProductsModel.first;
    setupListeners();

    debounce(
      searchedValue,
      (callback) => getStewardPurchaseOutOfProvince(),
      time: Duration(milliseconds: timeDebounce),
    );
  }

  @override
  void onClose() {
    sellerNameController.dispose();
    sellerPhoneController.dispose();
    carcassWeightController.dispose();

    super.onClose();
  }

  void setSearchValue(String? data) {
    searchedValue.value = data?.trim();
  }

  Future<void> getStewardPurchaseOutOfProvince([bool isLoadingMore = false]) async {
    if (isLoadingMore) {
      isLoadingMoreAllocationsMade.value = true;
    } else {
      purchaseOutOfProvinceList.value = Resource<PaginationModel<StewardFreeBar>>.loading();
    }

    if (searchedValue.value != null &&
        searchedValue.value!.trim().isNotEmpty &&
        currentPage.value > 1) {
      currentPage.value = 1; // Reset to first page if search value is set
    }
    await safeCall(
      call: () => rootLogic.chickenRepository.getStewardPurchasesOutSideOfTheProvince(
        token: rootLogic.tokenService.accessToken.value!,
        queryParameters: buildQueryParams(
          pageSize: 20,
          page: currentPage.value,
          search: 'filter',
          role: 'Steward',
          value: searchedValue.value,
          fromDate: fromDateFilter.value.toDateTime(),
          toDate: toDateFilter.value.toDateTime(),
        ),
      ),
      onSuccess: (res) async {
        await Future.delayed(Duration(milliseconds: 500));
        if ((res?.count ?? 0) == 0) {
          purchaseOutOfProvinceList.value = Resource<PaginationModel<StewardFreeBar>>.empty();
        } else {
          purchaseOutOfProvinceList.value = Resource<PaginationModel<StewardFreeBar>>.success(
            PaginationModel<StewardFreeBar>(
              count: res?.count ?? 0,
              next: res?.next,
              previous: res?.previous,
              results: [
                ...(purchaseOutOfProvinceList.value.data?.results ?? []),
                ...(res?.results ?? []),
              ],
            ),
          );
        }
      },
    );
  }

  Future<void> getCites() async {
    await safeCall(
      call: () =>
          rootLogic.chickenRepository.getCity(provinceName: selectedProvince.value?.name ?? ''),
      onSuccess: (result) {
        if (result != null && result.isNotEmpty) {
          cites.value = result;
        }
      },
    );
  }

  void setupListeners() {
    sellerNameController.addListener(() {
      checkFormValid();
      if (!isSubmitButtonEnabled.value) {
        isSubmitButtonEnabled.value = !isSubmitButtonEnabled.value;
      }
    });
    sellerPhoneController.addListener(checkFormValid);
    carcassWeightController.addListener(checkFormValid);
    carcassCountController.addListener(checkFormValid);

    ever(selectedProvince, (_) => checkFormValid());
    ever(selectedCity, (_) => checkFormValid());
    ever(selectedProduct, (_) => checkFormValid());
    ever(selectedImage, (data) async {
      checkFormValid();
      if (data?.path != null) {
        _base64Image.value = await convertImageToBase64(data!.path);
      }
    });
  }

  void checkFormValid() {
    isSubmitButtonEnabled.value =
        sellerNameController.text.isNotEmpty &&
        sellerPhoneController.text.isNotEmpty &&
        carcassWeightController.text.isNotEmpty &&
        carcassCountController.text.isNotEmpty &&
        selectedProvince.value != null &&
        selectedCity.value != null &&
        selectedProduct.value != null &&
        (selectedImage.value != null || editImageUrl.value != null);

    if (isSubmitButtonEnabled.value) {
      isOnLoadingSubmitOrEdit.value = false;
    }
  }

  Future<bool> createStewardPurchaseOutOfProvince() async {
    bool res = false;
    isOnLoadingSubmitOrEdit.value = true;
    if (!(formKey.currentState?.validate() ?? false)) {
      isOnLoadingSubmitOrEdit.value = false;
      return res;
    }
    await safeCall(
      showError: true,
      call: () async {
        CreateStewardFreeBar createStewardFreeBar = CreateStewardFreeBar(
          productKey: selectedProduct.value!.key,
          killHouseName: sellerNameController.text,
          killHouseMobile: sellerPhoneController.text,
          province: selectedProvince.value!.name,
          city: selectedCity.value!.name,
          weightOfCarcasses: int.parse(carcassWeightController.text.clearComma),
          numberOfCarcasses: int.parse(carcassCountController.text.clearComma),
          barImage: _base64Image.value,
          date: DateTime.now().formattedYHMS,
        );
        await rootLogic.chickenRepository.createStewardPurchasesOutSideOfTheProvince(
          token: rootLogic.tokenService.accessToken.value!,
          body: createStewardFreeBar,
        );
      },
      onSuccess: (result) {
        getStewardPurchaseOutOfProvince();
        resetSubmitForm();
        toggleExpansion();
        res = true;
      },
    );
    isOnLoadingSubmitOrEdit.value = false;
    return res;
  }

  void resetSubmitForm() {
    sellerNameController.clear();
    sellerPhoneController.clear();
    carcassWeightController.clear();
    selectedProvince.value = null;
    selectedCity.value = null;
    selectedImage.value = null;
    _base64Image.value = null;
    editImageUrl.value = null;

    isSubmitButtonEnabled.value = false;
  }

  void setEditData(StewardFreeBar item) async {
    editImageUrl.value = item.barImage;
    sellerNameController.text = item.killHouseName ?? '';
    sellerPhoneController.text = item.killHouseMobile ?? '';
    carcassWeightController.text = item.weightOfCarcasses.separatedByComma;
    carcassCountController.text = item.numberOfCarcasses.separatedByComma;
    editFreeBarKey.value = item.key;
    selectedProvince.value = IranProvinceCityModel(name: item.province);
    selectedCity.value = IranProvinceCityModel(name: item.city);
    selectedProduct.value = rootLogic.rolesProductsModel.firstWhere(
      (element) => element.key == item.product!.key,
    );

    isSubmitButtonEnabled.value = true;
  }

  Future<void> editStewardPurchaseOutOfProvince() async {
    CreateStewardFreeBar edit = CreateStewardFreeBar(
      productKey: selectedProduct.value!.key,
      key: editFreeBarKey.value,
      killHouseName: sellerNameController.text,
      killHouseMobile: sellerPhoneController.text,
      province: selectedProvince.value!.name,
      city: selectedCity.value!.name,
      weightOfCarcasses: int.parse(carcassWeightController.text.clearComma),
      numberOfCarcasses: int.parse(carcassCountController.text.clearComma),
      date: DateTime.now().formattedYHMS,
    );

    if (_base64Image.value != null) {
      edit = edit.copyWith(barImage: _base64Image.value);
    }

    await safeCall(
      showError: true,
      call: () => rootLogic.chickenRepository.editStewardPurchasesOutSideOfTheProvince(
        token: rootLogic.tokenService.accessToken.value!,
        body: edit,
      ),
      onSuccess: (result) {
        onRefresh();
        rootLogic.onRefresh();
        toggleExpansion();
      },
    );
  }

  Future<void> deleteStewardPurchaseOutOfProvince(String key) async {
    await safeCall(
      call: () => rootLogic.chickenRepository.deleteStewardPurchasesOutSideOfTheProvince(
        token: rootLogic.tokenService.accessToken.value!,
        queryParameters: buildRawQueryParams(queryParams: {'key': key}),
      ),
    );
  }

  Future<void> onRefresh() async {
    currentPage.value = 1;
    await rootLogic.onRefresh();
    await getStewardPurchaseOutOfProvince();
  }

  void toggleExpansion({int? index}) {
    if (expandedListIndex.value == index || index == null) {
      expandedListIndex.value = -1;
    } else {
      expandedListIndex.value = index;
    }
  }
}
