import 'package:get/get.dart'; import 'package:on_field_work/helpers/services/app_logger.dart'; import 'package:on_field_work/helpers/services/api_service.dart'; import 'package:on_field_work/model/employees/employee_model.dart'; import 'package:on_field_work/model/employees/employee_details_model.dart'; class EmployeesScreenController extends GetxController { /// ✅ Data lists RxList employees = [].obs; Rxn selectedEmployeeDetails = Rxn(); /// ✅ Loading states RxBool isLoading = false.obs; RxBool isLoadingEmployeeDetails = false.obs; /// ✅ Selection state RxBool isAllEmployeeSelected = false.obs; RxSet selectedEmployeeIds = {}.obs; /// ✅ Upload state tracking (if needed later) RxMap uploadingStates = {}.obs; RxList selectedEmployeePrimaryManagers = [].obs; RxList selectedEmployeeSecondaryManagers = [].obs; @override void onInit() { super.onInit(); fetchAllEmployees(); } /// 🔹 Fetch all employees (no project filter) Future fetchAllEmployees({String? organizationId}) async { isLoading.value = true; update(['employee_screen_controller']); await _handleApiCall( () => ApiService.getAllEmployees(organizationId: organizationId), onSuccess: (data) { employees.assignAll(data.map((json) => EmployeeModel.fromJson(json))); logSafe( "All Employees fetched: ${employees.length} employees loaded.", level: LogLevel.info, ); // Reset selection states when new data arrives selectedEmployeeIds.clear(); isAllEmployeeSelected.value = false; }, onEmpty: () { employees.clear(); selectedEmployeeIds.clear(); isAllEmployeeSelected.value = false; logSafe("No Employee data found or API call failed", level: LogLevel.warning); }, ); isLoading.value = false; update(['employee_screen_controller']); } /// 🔹 Fetch details for a specific employee Future fetchEmployeeDetails(String? employeeId) async { if (employeeId == null || employeeId.isEmpty) return; isLoadingEmployeeDetails.value = true; await _handleSingleApiCall( () => ApiService.getEmployeeDetails(employeeId), onSuccess: (data) { selectedEmployeeDetails.value = EmployeeDetailsModel.fromJson(data); logSafe("Employee details loaded for $employeeId", level: LogLevel.info); }, onEmpty: () { selectedEmployeeDetails.value = null; logSafe("No employee details found for $employeeId", level: LogLevel.warning); }, onError: (e) { selectedEmployeeDetails.value = null; logSafe("Error fetching employee details for $employeeId", level: LogLevel.error, error: e); }, ); isLoadingEmployeeDetails.value = false; } /// Fetch reporting managers for a specific employee from /organization/hierarchy/list/:employeeId Future fetchReportingManagers(String? employeeId) async { if (employeeId == null || employeeId.isEmpty) return; try { // ✅ Always clear before new fetch (to avoid mixing old data) selectedEmployeePrimaryManagers.clear(); selectedEmployeeSecondaryManagers.clear(); // Fetch from existing API helper final data = await ApiService.getOrganizationHierarchyList(employeeId); if (data == null || data.isEmpty) { update(['employee_screen_controller']); return; } for (final item in data) { try { final reportTo = item['reportTo']; if (reportTo == null) continue; final emp = EmployeeModel.fromJson(reportTo); final isPrimary = item['isPrimary'] == true; if (isPrimary) { if (!selectedEmployeePrimaryManagers.any((e) => e.id == emp.id)) { selectedEmployeePrimaryManagers.add(emp); } } else { if (!selectedEmployeeSecondaryManagers.any((e) => e.id == emp.id)) { selectedEmployeeSecondaryManagers.add(emp); } } } catch (_) { // ignore malformed items } } update(['employee_screen_controller']); } catch (e) { logSafe("Error fetching reporting managers for $employeeId", level: LogLevel.error, error: e); } } /// 🔹 Clear all employee data void clearEmployees() { employees.clear(); selectedEmployeeIds.clear(); isAllEmployeeSelected.value = false; logSafe("Employees cleared", level: LogLevel.info); update(['employee_screen_controller']); } /// 🔹 Generic handler for list API responses Future _handleApiCall( Future?> Function() apiCall, { required Function(List) onSuccess, required Function() onEmpty, Function(dynamic error)? onError, }) async { try { final response = await apiCall(); if (response != null && response.isNotEmpty) { onSuccess(response); } else { onEmpty(); } } catch (e) { if (onError != null) { onError(e); } else { logSafe("API call error", level: LogLevel.error, error: e); } } } /// 🔹 Generic handler for single-object API responses Future _handleSingleApiCall( Future?> Function() apiCall, { required Function(Map) onSuccess, required Function() onEmpty, Function(dynamic error)? onError, }) async { try { final response = await apiCall(); if (response != null && response.isNotEmpty) { onSuccess(response); } else { onEmpty(); } } catch (e) { if (onError != null) { onError(e); } else { logSafe("API call error", level: LogLevel.error, error: e); } } } }