import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:taafee_mobile/common/const/const.dart';
import 'package:taafee_mobile/common/widgets/button.dart';
import 'package:taafee_mobile/common/widgets/text.dart';
import 'package:taafee_mobile/core/local_storage/local_storage.dart';
import 'package:taafee_mobile/core/routing/routing_manager.dart';
import 'package:taafee_mobile/features/card/data_layer/model/appointment.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_model.dart';
import 'package:taafee_mobile/features/home/data_layer/model/city.dart';
import 'package:taafee_mobile/features/home/data_layer/model/search.dart';
import 'package:taafee_mobile/features/home/data_layer/source/home_service.dart';
import 'package:rx_future/rx_future.dart';
import '../../../core/utils/pagination_list.dart';
import '../../auth/data_layer/model/user.dart';

class HomeController extends GetxController {
//---------data source----------///
  LocalStorage storage = LocalStorage();
  HomeService homeService = HomeService();

  //------------navBar------------///
  RxInt selectIndex = 0.obs;

  void onPress(index) {
    if (index == 1 || index == 2) {
      if (storage.getIsGuest() ?? true) {
        Get.defaultDialog(
            title: '',
            content: Column(
              children: [
                BoldTextWidget('you_have_to_sign_in'.tr),
                const SizedBox(
                  height: 20,
                ),
                ButtonWidget(
                    onTap: () {
                      RoutingManager.offAll(RouteName.login);
                      String? languangeCode = storage.getLanguage();
                      storage.clearCache();
                      if (languangeCode != null) {
                        storage.saveLanguage(languangeCode);
                      }
                      storage.savefirstTimeOpened();
                    },
                    title: 'sign_in'.tr)
              ],
            ));
        return;
      }
    }
    selectIndex.value = index;
    selectIndex.refresh();
  }

  //------------read user----------////
  //pick avatar image
  Rx<File?> pickedUserImage = null.obs;
  RxBool isAvatarImagePicked = false.obs;
  RxBool isUserHasAvatar = false.obs;
  Rx<User?> user = User.zero().obs;

  void readUser() {
    user.value = storage.getUser();
    if (user.value!.avatarImage != null) {
      isUserHasAvatar.value = true;
    } else {
      isUserHasAvatar.value = false;
    }
    List<Appointment>? appointments = storage.getAppointments();
    if (appointments != null) {
      user.update((val) {
        val!.appointments = appointments;
      });
    }
    user.refresh();
    isUserHasAvatar.refresh();
  }

  void setPickedUserImage(File? file) async {
    if (file != null) {
      pickedUserImage = file.obs;
      isAvatarImagePicked.value = true;
      isAvatarImagePicked.refresh();
      pickedUserImage.refresh();
      update();
    }
  }

  void clearPickedUserImage() async {
    isAvatarImagePicked.value = false;
    isAvatarImagePicked.refresh();
    pickedUserImage = null.obs;
    pickedUserImage.refresh();
  }

//---------------get cities-----------------//
  RxFuture<List<CityModel>> cityState = RxFuture(<CityModel>[]);

  Future<void> getCities({String? value}) async {
    await cityState.observe((p0) async {
      return await homeService.getCities(value: value);
    });
  }

//----------------search------------------//
  RxFuture<Pagination<CardModel>> searchState = RxFuture(Pagination.zero());
  Rx<SearchModel> searchModel = SearchModel.zero().obs;
  RxBool isUserSearching = false.obs;

  void setCityName(String newCityName) {
    searchModel.value.cityName = newCityName;
    searchModel.refresh();
  }

  void setCategoryName(String newCategoryName) {
    searchModel.value.categoryName = newCategoryName;
    searchModel.refresh();
  }

  void changeUserSearchingState(bool newState) {
    isUserSearching.value = newState;
    if (newState == false) {
      searchModel.value.categoryId = null;
      searchModel.value.cityId = null;
      searchModel.value.categoryName = null;
      searchModel.value.cityName = null;
    }

    isUserSearching.refresh();
    searchModel.refresh();
  }

  void clearSearchFilters() {
    searchModel.value.categoryId = null;
    searchModel.value.cityId = null;
    searchModel.value.categoryName = null;
    searchModel.value.cityName = null;
    searchModel.value.searchWords = null;
    searchModel.refresh();
  }

  Future<void> search({
    void Function(Pagination<CardModel>)? onSuccess,
    void Function(Object)? onError,
  }) async {
    if (searchModel.value.searchWords == '') {
      searchModel.value.searchWords = null;
    }
    changeUserSearchingState(true);
    await searchState.observe(
      (p0) async {
        await p0!.nextPage((currentPage) async {
          searchModel.value.page = currentPage;
          List<CardModel> cards =
              await homeService.searchCards(searchModel.value);
          if (cards.isEmpty) return [];

          return cards;
        });
        return p0;
      },
      onSuccess: onSuccess,
      onError: onError,
    );
  }

  ///------------Ui changes according to language---------///
  RxBool isArabic = false.obs;
  void setUiLanguage(String languageCode) {
    if (languageCode == Languages.arabic.code) {
      isArabic.value = true;
    } else {
      isArabic.value = false;
    }
    isArabic.refresh();
  }

  /// ----------- schedule an appointment -------///
  Rx<Appointment?> currentCardAppointment = null.obs;

  void setCardAppointment(int cardId) {
    currentCardAppointment = getCardAppointment(cardId).obs;
    currentCardAppointment.refresh();
    user.refresh();
  }

  RxFuture<void> appointmentSchedulingState = RxFuture(null);
  void scheduleAnAppointment(Appointment appointment,
      {void Function()? onSuccess}) async {
    appointmentSchedulingState.observe(
      (value) async {
        await Future.delayed(const Duration(seconds: 3));
      },
      onSuccess: (response) async {
        user.update((val) {
          if (val!.appointments != null) {
            val.appointments!.add(appointment);
          } else {
            val.appointments = [];
            val.appointments!.add(appointment);
          }
        });

        await storage.setAppointments(user.value!.appointments!);

        currentCardAppointment = appointment.obs;
        currentCardAppointment.refresh();
        user.refresh();
        onSuccess?.call();
      },
    );
  }

  RxFuture<void> appointmentCancelingState = RxFuture(null);

  void cancelAppointment({void Function()? onSuccess}) {
    appointmentCancelingState.observe(
      (value) async {
        await Future.delayed(const Duration(seconds: 3));
      },
      onSuccess: (response) async {
        user.update((val) {
          int index = val!.appointments!.lastIndexWhere((element) =>
              element.cardId == currentCardAppointment.value!.cardId);
          val.appointments!.removeAt(index);
        });

        await storage.setAppointments(user.value!.appointments!);

        currentCardAppointment = null.obs;
        currentCardAppointment.refresh();
        user.refresh();
        onSuccess?.call();
      },
    );
  }

  Appointment? getCardAppointment(int cardId) {
    if (user.value!.appointments == null || user.value!.appointments!.isEmpty) {
      return null;
    }
    Appointment? appointment = user.value!.appointments!
        .firstWhereOrNull((element) => (element.cardId == cardId));
    return appointment;
  }
}
