import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:taafee_mobile/common/const/const.dart';
import 'package:taafee_mobile/core/local_storage/local_storage.dart';
import 'package:taafee_mobile/features/card/data_layer/model/add_card.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_images.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_model.dart';
import 'package:taafee_mobile/features/card/data_layer/model/edit_card.dart';
import 'package:taafee_mobile/features/card/data_layer/source/card_service.dart';
import 'package:rx_future/rx_future.dart';

import '../../../core/utils/pagination_list.dart';

class CardController extends GetxController {
//---------------data source-----------//
  CardService cardService = CardService();
  LocalStorage localStorage = LocalStorage();
//----------- model-----------//
  Rx<AddCardModel> cardModel = AddCardModel.zero().obs;

//-------------add card-------------//

  RxFuture<void> addCardState = RxFuture(null);
  void addImagesToList(File file) {
    cardModel.update((val) {
      val!.images?.add(file);
    });
  }

  Future<void> addCard({void Function(void)? onSuccess, void Function(Object)? onError}) async {
    await addCardState.observe(
      (p0) async {
        await cardService.addCard(cardModel.value);
      },
      onSuccess: (value) {
        onSuccess?.call(value);
      },
      onError: (error) {
        onError?.call(error);
      },
    );
  }

//-------------get cards-----------//
  RxFuture<Pagination<CardModel>> cardState = RxFuture(Pagination<CardModel>.zero());

  Future<void> getCards({void Function(Object e)? onConnectionError}) async {
    await cardState.observe((value) async {
      await value?.nextPage((currentPage) async {
        List<CardModel> cards = await cardService.getCards(page: currentPage, onConnectionError: onConnectionError);
        if (cards.isEmpty) return [];

        return cards;
      });
      return value!;
      //  return await cardService.getCards();
    }, onSuccess: (value) {});
  }

  RxFuture<void> favoriteState = RxFuture(null);
  Future<void> toggleFavorite(int id, bool removeFromFavorite,
      {void Function(void)? onSuccess, void Function(Object)? onError}) async {
    List<CardModel> temp = cardState.result.data;
    for (int i = 0; i < temp.length; i++) {
      if (temp[i].id == id) {
        temp[i].isFav = !cardState.result.data[i].isFav;

        break;
      }
    }
    cardState.update((val) {
      // val!.value = Pagination<CardModel>(data: temp);
      val!.value.data = temp;
    });
    cardState.refresh();
    // cardState.result.data.firstWhere((element) => element.id == id).isFav =
    //     !removeFromFavorite;

    update();
    await favoriteState.observe((p0) async {
      removeFromFavorite ? await cardService.removeFromFavorite(id) : await cardService.addToFavorite(id);
    }, onSuccess: onSuccess, onError: onError);
  }

  ///-------------my cards------------///
  RxFuture<Pagination<CardModel>> myCardState = RxFuture(Pagination.zero());

  Future<void> getMyCards(int userId, {void Function(Object)? onConnectionError}) async {
    myCardState.result.clear();
    await myCardState.observe((value) async {
      await value?.nextPage((currentPage) async {
        List<CardModel> cards =
            await cardService.getMyCards(userId, page: currentPage, onConnectionError: onConnectionError);
        if (cards.isEmpty) return [];
        return cards;
      });
      return value!;

      //  return await cardService.getMyCards(userId);
    });
  }

  //--------edit card--------//

  Rx<EditCardModel> editCardModel = EditCardModel.zero().obs;
  RxFuture<void> editCardState = RxFuture(null);

  Future<void> editCard(int cardId, {void Function(void)? onSuccess, void Function(Object)? onError}) async {
    await editCardState.observe(
      (p0) async {
        await cardService.editCard(cardId, editCardModel.value);
      },
      onSuccess: (value) {
        onSuccess?.call(value);
      },
      onError: (error) {
        onError?.call(error);
      },
    );
  }

  /// add images to card ///
  RxFuture<void> addImagesState = RxFuture(null);
  void editingAddImagesToList(File file) {
    editCardModel.value.images!.add(file);
    cardModel.update((val) {
      val!.images?.add(file);
    });
    cardModel.refresh();
  }

  Future uploadImages({void Function(void)? onSuccess}) async {
    await addImagesState.observe(
      (p0) async {
        await cardService.addImagesToCard(editCardModel.value);
      },
      onSuccess: onSuccess,
    );
  }

  /// ------------delete image from card--------///
  RxList<CardImages> cardModelNetworkImages = <CardImages>[].obs;
  RxFuture<void> deleteImageState = RxFuture(null);
  RxFuture<List<CardImages>> networkImagesState = RxFuture(<CardImages>[]);
  void changeNetworkImages(List<CardImages> cardImages) {
    cardModelNetworkImages.value = cardImages;
    cardModelNetworkImages.refresh();
    cardModelNetworkImages;
  }

  Future updateNetworkImages(int cardId) async {
    networkImagesState.observe(
      (p0) async {
        return cardModelNetworkImages.value = await cardService.getCardImages(cardId);
      },
      onSuccess: (cardImages) {
        cardModelNetworkImages.refresh();
      },
    );
  }

  void removeImageFromNewCard(int index) {
    cardModel.value.images!.removeAt(index);
    cardModel.refresh();
  }

  void deleteImage(int imageId, {void Function(void)? onSuccess, required int cardId}) async {
    if (!addImagesState.loading) {
      deleteImageState.observe(
        (p0) async {
          return await cardService.deleteImage(imageId);
        },
        onSuccess: (value) async {
          await updateNetworkImages(cardId);
        },
      );
    }
  }

  /// ------------delete card -----------///
  RxFuture<void> deleteCardState = RxFuture(null);
  Future<void> deleteCard(int cardId, {void Function(void)? onSuccess}) async {
    deleteCardState.observe(
      (value) async {
        return await cardService.deleteCard(cardId);
      },
      onSuccess: onSuccess,
    );
  }

  /// --------- gallery view network images -----///
  List<String> cardNetworkImagesUrls = <String>[].obs;
  void updateCardNetworkImageUrls(List<CardImages> cardImages) {
    cardNetworkImagesUrls.clear();
    // ignore: avoid_function_literals_in_foreach_calls
    cardImages.forEach((element) {
      cardNetworkImagesUrls.add(Domain.domain + element.url.substring(6));
    });
  }

  Rx<PageController> pageController = PageController().obs;
  int imageIndex = 0;
  void pageControllerInitialValue(int index) {
    pageController.value = PageController(initialPage: index);
    pageController.refresh();
  }

  void changeImageIndex(int newIndex) {
    imageIndex = newIndex;
  }

  /// --------- save images to gallery ------///
  final Random random = Random();

  RxFuture<void> saveCardState = RxFuture(null);
  saveNetworkImage(String imageUrl, {void Function(Object)? onError, void Function(void)? onSuccess}) async {
    saveCardState.observe((p0) async {
      Uint8List image = await cardService.downloadImage(imageUrl);
      await ImageGallerySaver.saveImage(
        image,
        quality: 60,
        name: "yellow pages image ${random.nextInt(500)}",
      );
    }, onError: (e) {
      onError?.call(e);
    }, onSuccess: onSuccess);
  }

  /// ------------ card appointments ---------///
  RxFuture<void> availableAppointmentsState = RxFuture(null);
  void getAvailableAppointments() async {
    return availableAppointmentsState.observe((value) async {
      await Future.delayed(const Duration(seconds: 3));
    });
  }

  //----------rating----------//
  RxInt currentIndex = 1.obs;

  void changeCurrentIndex(int index) {
    currentIndex.value = index;
  }
}
