import 'package:get/get.dart';
import 'package:mypoint_flutter_app/networking/api/notification_api.dart' deferred as notification_api;
import '../../base/base_response_model.dart';
import '../../networking/restful_api_viewmodel.dart';
import '../../preference/data_preference.dart';
import '../../shared/router_gage.dart';
import 'models/category_notify_item_model.dart';
import 'models/notification_detail_model.dart';
import 'models/notification_item_model.dart';
import 'models/notification_list_data_model.dart';
import 'notification_detail_screen.dart';

class NotificationViewModel extends RestfulApiViewModel {
  final RxList<CategoryNotifyItemModel> categories = <CategoryNotifyItemModel>[].obs;
  final RxList<NotificationItemModel> notifications = <NotificationItemModel>[].obs;
  final RxBool isLoading = false.obs;
  final _pageLimit = 10;
  var _notificationIndex = 0;
  void Function(String message)? onShowAlertError;
  var _hasMoreData = true;

  bool _notificationApiLoaded = false;

  Future<void> _ensureNotificationApiLoaded() async {
    if (_notificationApiLoaded) return;
    await notification_api.loadLibrary();
    _notificationApiLoaded = true;
  }

  Future<BaseResponseModel<T>> _callNotificationApi<T>(Future<BaseResponseModel<T>> Function(dynamic api) fn) async {
    await _ensureNotificationApiLoaded();
    final api = notification_api.NotificationApi(client);
    return fn(api);
  }

  CategoryNotifyItemModel? get selectedCategory =>
      categories.isNotEmpty ? categories.firstWhere((item) => item.isSelected ?? false) : null;

  @override
  void onInit() {
    super.onInit();
    _fetchCategories();
  }

  void _fetchCategories() async {
    await callApi<List<CategoryNotifyItemModel>>(
      request: () => _callNotificationApi((api) => api.getNotificationCategories()),
      onSuccess: (data, _) {
        if (data.isNotEmpty) data[0].isSelected = true;
        categories.assignAll(data);
        fetchNotifications(refresh: true);
      },
      onFailure: (msg, _, _) async {
        onShowAlertError?.call(msg);
      },
    );
  }

  void fetchNotifications({bool refresh = false}) async {
    if (isLoading.value) return;
    if (!refresh && !_hasMoreData) {
      return;
    }
    if (refresh) {
      _notificationIndex = 0;
    }
    isLoading.value = true;
    String? token = DataPreference.instance.token ?? "";
    final body = {
      "access_token": token,
      "start": _notificationIndex,
      "limit": _pageLimit,
      "noti_group_id": selectedCategory?.id ?? "",
    };
    await callApi<NotificationListDataModel>(
      request: () => _callNotificationApi((api) => api.getNotifications(body)),
      onSuccess: (data, _) {
        final items = data.items ?? [];
        if (refresh) {
          notifications.assignAll(items);
        } else {
          notifications.addAll(items);
        }
        _notificationIndex += items.length;
        _hasMoreData = items.length == _pageLimit;
      },
      onFailure: (msg, _, _) async {
        onShowAlertError?.call(msg);
      },
      withLoading: refresh,
      onComplete: () {
        isLoading.value = false;
      },
    );
  }

  void selectCategory(int index) {
    for (var i = 0; i < categories.length; i++) {
      categories[i].isSelected = i == index;
    }
    fetchNotifications(refresh: true);
  }

  void notificationMarkAsSeen() {
    callApi<EmptyCodable>(
      request: () => _callNotificationApi((api) => api.notificationMarkAsSeen()),
      onSuccess: (_, _) => _fetchCategories(),
      onFailure: (msg, _, _) async {
        onShowAlertError?.call(msg);
      },
    );
  }

  void deleteAllNotifications() {
    callApi<EmptyCodable>(
      request: () => _callNotificationApi((api) => api.deleteAllNotifications()),
      onSuccess: (_, _) => _fetchCategories(),
      onFailure: (msg, _, _) async {
        onShowAlertError?.call(msg);
      },
    );
  }

  Future<bool> deleteNotificationItem(NotificationItemModel item) async {
    if (item.notificationId == null) return true;
    var success = true;
    await callApi<EmptyCodable>(
      request: () => _callNotificationApi((api) => api.deleteNotification(item.notificationId ?? "")),
      onSuccess: (_, _) {
        if (notifications.length <= _pageLimit) {
          fetchNotifications(refresh: false);
        }
      },
      onFailure: (msg, _, _) async {
        onShowAlertError?.call(msg);
        success = false;
      },
      withLoading: false,
    );
    return success;
  }

  void handleClickNotification(NotificationItemModel item) {
    callApi<NotificationDetailResponseModel>(
      request: () => _callNotificationApi((api) => api.getNotificationDetail(item.notificationId ?? "")),
      onSuccess: (data, _) {
        final notification = data.notification;
        if (notification == null) return;
        final pushSuccess = notification.directionalScreen?.begin() ?? false;
        if (!pushSuccess) {
          Get.toNamed(
            notificationDetailScreen,
            arguments: {'notification': notification, 'notificationId': item.notificationId},
          );
        }
      },
      onFailure: (msg, _, _) async {
        onShowAlertError?.call(msg);
      },
    );
  }
}
