import 'package:get/get.dart';
import 'package:on_field_work/helpers/services/api_service.dart';
import 'package:on_field_work/helpers/services/app_logger.dart';
import 'package:on_field_work/model/expense/expense_detail_model.dart';
import 'package:on_field_work/model/employees/employee_model.dart';
import 'package:flutter/material.dart';

class ExpenseDetailController extends GetxController {
  final Rx<ExpenseDetailModel?> expense = Rx<ExpenseDetailModel?>(null);
  final RxBool isLoading = false.obs;
  final RxString errorMessage = ''.obs;
  final Rx<EmployeeModel?> selectedReimbursedBy = Rx<EmployeeModel?>(null);
  final RxList<EmployeeModel> allEmployees = <EmployeeModel>[].obs;
  final RxList<EmployeeModel> employeeSearchResults = <EmployeeModel>[].obs;
  late String _expenseId;
  bool _isInitialized = false;
  final employeeSearchController = TextEditingController();
  final isSearchingEmployees = false.obs;

  /// Call this once from the screen (NOT inside build) to initialize
  void init(String expenseId) {
    if (_isInitialized) return;

    _isInitialized = true;
    _expenseId = expenseId;

    // Use Future.wait to fetch details and employees concurrently
    Future.wait([
      fetchExpenseDetails(),
      fetchAllEmployees(),
    ]);
  }

  /// Generic method to handle API calls with loading and error states
  Future<T?> _apiCallWrapper<T>(
      Future<T?> Function() apiCall, String operationName) async {
    isLoading.value = true;
    errorMessage.value = ''; // Clear previous errors

    try {
      logSafe("Initiating $operationName...");
      final result = await apiCall();
      logSafe("$operationName completed successfully.");
      return result;
    } catch (e, stack) {
      errorMessage.value =
          'An unexpected error occurred during $operationName.';
      logSafe("Exception in $operationName: $e", level: LogLevel.error);
      logSafe("StackTrace: $stack", level: LogLevel.debug);
      return null;
    } finally {
      isLoading.value = false;
    }
  }

  /// Fetch expense details by stored ID
  Future<void> fetchExpenseDetails() async {
    final result = await _apiCallWrapper(
        () => ApiService.getExpenseDetailsApi(expenseId: _expenseId),
        "fetch expense details");

    if (result != null) {
      try {
        expense.value = ExpenseDetailModel.fromJson(result);
        logSafe("Expense details loaded successfully: ${expense.value?.id}");
      } catch (e) {
        errorMessage.value = 'Failed to parse expense details: $e';
        logSafe("Parse error in fetchExpenseDetails: $e",
            level: LogLevel.error);
      }
    } else {
      errorMessage.value = 'Failed to fetch expense details from server.';
      logSafe("fetchExpenseDetails failed: null response",
          level: LogLevel.error);
    }
  }

  // This method seems like a utility and might be better placed in a helper or utility class
  // if it's used across multiple controllers. Keeping it here for now as per original code.
  List<String> parsePermissionIds(dynamic permissionData) {
    if (permissionData == null) return [];
    if (permissionData is List) {
      return permissionData
          .map((e) => e.toString().trim())
          .where((e) => e.isNotEmpty)
          .toList();
    }
    if (permissionData is String) {
      final clean = permissionData.replaceAll(RegExp(r'[\[\]]'), '');
      return clean
          .split(',')
          .map((e) => e.trim())
          .where((e) => e.isNotEmpty)
          .toList();
    }
    return [];
  }

  Future<void> searchEmployees(String query) async {
    if (query.trim().isEmpty) return employeeSearchResults.clear();
    isSearchingEmployees.value = true;
    try {
      final data =
          await ApiService.searchEmployeesBasic(searchString: query.trim());
      employeeSearchResults.assignAll(
        (data ?? []).map((e) => EmployeeModel.fromJson(e)),
      );
    } catch (e) {
      logSafe("Error searching employees: $e", level: LogLevel.error);
      employeeSearchResults.clear();
    } finally {
      isSearchingEmployees.value = false;
    }
  }

  /// Fetch all employees
  Future<void> fetchAllEmployees() async {
    final response = await _apiCallWrapper(
        () => ApiService.getAllEmployees(), "fetch all employees");

    if (response != null && response.isNotEmpty) {
      try {
        allEmployees.assignAll(response.map((e) => EmployeeModel.fromJson(e)));
        logSafe("All Employees fetched: ${allEmployees.length}",
            level: LogLevel.info);
      } catch (e) {
        errorMessage.value = 'Failed to parse employee data: $e';
        logSafe("Parse error in fetchAllEmployees: $e", level: LogLevel.error);
      }
    } else {
      allEmployees.clear();
      logSafe("No employees found.", level: LogLevel.warning);
    }
    // `update()` is typically not needed for RxList directly unless you have specific GetBuilder/Obx usage that requires it
    // If you are using Obx widgets, `allEmployees.assignAll` will automatically trigger a rebuild.
  }

  /// Update expense with reimbursement info and status
  Future<bool> updateExpenseStatusWithReimbursement({
    required String comment,
    required String reimburseTransactionId,
    required String reimburseDate,
    required String reimburseById,
    required String statusId,
    double? baseAmount,
    double? taxAmount, 
    double? tdsPercent,
    double? netPayable,
  }) async {
    final success = await _apiCallWrapper(
      () => ApiService.updateExpenseStatusApi(
        expenseId: _expenseId,
        statusId: statusId,
        comment: comment,
        reimburseTransactionId: reimburseTransactionId,
        reimburseDate: reimburseDate,
        reimbursedById: reimburseById,
        baseAmount: baseAmount,
        taxAmount: taxAmount,
        tdsPercent: tdsPercent, 
        netPayable: netPayable, 
      ),
      "submit reimbursement",
    );

    if (success == true) {
      await fetchExpenseDetails();
      return true;
    } else {
      errorMessage.value = "Failed to submit reimbursement.";
      return false;
    }
  }

  /// Update status for this specific expense
  Future<bool> updateExpenseStatus(String statusId, {String? comment}) async {
    final success = await _apiCallWrapper(
      () => ApiService.updateExpenseStatusApi(
        expenseId: _expenseId,
        statusId: statusId,
        comment: comment,
      ),
      "update expense status",
    );

    if (success == true) {
      await fetchExpenseDetails();
      return true;
    } else {
      errorMessage.value = "Failed to update expense status.";
      return false;
    }
  }
}
