import 'package:get/get.dart';
import 'package:on_field_work/helpers/services/api_service.dart';
import 'package:on_field_work/model/finance/payment_request_list_model.dart';
import 'package:on_field_work/model/finance/payment_request_filter.dart';
import 'package:on_field_work/helpers/services/app_logger.dart';

class PaymentRequestController extends GetxController {
  // ---------------- Observables ----------------
  final RxList<PaymentRequest> paymentRequests = <PaymentRequest>[].obs;
  final RxBool isLoading = false.obs;
  final RxString errorMessage = ''.obs;
  final RxBool isFilterApplied = false.obs;

  // ---------------- Pagination ----------------
  int _pageSize = 20;
  int _pageNumber = 1;
  bool _hasMoreData = true;

  // ---------------- Filters ----------------
  RxMap<String, dynamic> appliedFilter = <String, dynamic>{}.obs;
  RxString searchString = ''.obs;

  // ---------------- Filter Options ----------------
  RxList<IdNameModel> projects = <IdNameModel>[].obs;
  RxList<IdNameModel> payees = <IdNameModel>[].obs;
  RxList<IdNameModel> categories = <IdNameModel>[].obs;
  RxList<IdNameModel> currencies = <IdNameModel>[].obs;
  RxList<IdNameModel> statuses = <IdNameModel>[].obs;
  RxList<IdNameModel> createdBy = <IdNameModel>[].obs;

  // ---------------- Fetch Filter Options ----------------
  Future<void> fetchPaymentRequestFilterOptions() async {
    try {
      final response = await ApiService.getExpensePaymentRequestFilterApi();

      if (response != null && response.data != null) {
        projects.assignAll(response.data!.projects ?? []);
        payees.assignAll(response.data!.payees ?? []);
        categories.assignAll(response.data!.expenseCategory ?? []);
        currencies.assignAll(response.data!.currency ?? []);
        statuses.assignAll(response.data!.status ?? []);
        createdBy.assignAll(response.data!.createdBy ?? []);
      } else {
        logSafe("Payment request filter API returned null",
            level: LogLevel.warning);
      }
    } catch (e, stack) {
      logSafe("Exception in fetchPaymentRequestFilterOptions: $e",
          level: LogLevel.error);
      logSafe("StackTrace: $stack", level: LogLevel.debug);
    }
  }

  // ---------------- Fetch Payment Requests ----------------
  Future<void> fetchPaymentRequests({int pageSize = 20}) async {
    isLoading.value = true;
    errorMessage.value = '';
    _pageNumber = 1;
    _pageSize = pageSize;
    _hasMoreData = true;
    paymentRequests.clear();

    await _fetchPaymentRequestsFromApi();
    isLoading.value = false;
  }

  // ---------------- Load More ----------------
  Future<void> loadMorePaymentRequests() async {
    if (isLoading.value || !_hasMoreData) return;

    _pageNumber += 1;
    isLoading.value = true;

    await _fetchPaymentRequestsFromApi();
    isLoading.value = false;
  }

  // ---------------- Internal API Call ----------------
  Future<void> _fetchPaymentRequestsFromApi() async {
    try {
      final response = await ApiService.getExpensePaymentRequestListApi(
        pageSize: _pageSize,
        pageNumber: _pageNumber,
        filter: appliedFilter,
        searchString: searchString.value,
      );

      final data = response?.data;
      final reqList = data?.data ?? [];

      if (response != null && data != null && reqList.isNotEmpty) {
        if (_pageNumber == 1) {
          paymentRequests.assignAll(reqList);
        } else {
          paymentRequests.addAll(reqList);
        }

        if (reqList.length < _pageSize) {
          _hasMoreData = false;
        }
      } else {
        if (_pageNumber == 1) {
          errorMessage.value = 'No payment requests found.';
        }
        _hasMoreData = false;
      }
    } catch (e, stack) {
      errorMessage.value = 'Failed to fetch payment requests.';
      logSafe("Exception in _fetchPaymentRequestsFromApi: $e",
          level: LogLevel.error);
      logSafe("StackTrace: $stack", level: LogLevel.debug);
      _hasMoreData = false;
    }
  }

  // ---------------- Filter Management ----------------
  void setFilterApplied(bool applied) {
    isFilterApplied.value = applied;
  }

  void applyFilter(Map<String, dynamic> filter, {String search = ''}) {
    appliedFilter.assignAll(filter);
    searchString.value = search;
    isFilterApplied.value = filter.isNotEmpty || search.isNotEmpty;
    fetchPaymentRequests();
  }

  void clearFilter() {
    appliedFilter.clear();
    searchString.value = '';
    isFilterApplied.value = false;
    fetchPaymentRequests();
  }
}
