import 'package:get/get.dart';
import 'package:marco/helpers/services/app_logger.dart';
import 'package:marco/helpers/services/api_service.dart';
import 'package:marco/model/attendance/attendance_model.dart';
import 'package:marco/model/project_model.dart';
import 'package:marco/model/employees/employee_model.dart';
import 'package:marco/model/employees/employee_details_model.dart';
import 'package:marco/controller/project_controller.dart';

class EmployeesScreenController extends GetxController {
  List<AttendanceModel> attendances = [];
  List<ProjectModel> projects = [];
  String? selectedProjectId;
  List<EmployeeDetailsModel> employeeDetails = [];
  RxBool isAllEmployeeSelected = false.obs;
  RxList<EmployeeModel> employees = <EmployeeModel>[].obs;

  RxBool isLoading = false.obs;
  RxMap<String, RxBool> uploadingStates = <String, RxBool>{}.obs;
  Rxn<EmployeeDetailsModel> selectedEmployeeDetails =
      Rxn<EmployeeDetailsModel>();
  RxBool isLoadingEmployeeDetails = false.obs;

  @override
  void onInit() {
    super.onInit();
    isLoading.value = true; 
    fetchAllProjects().then((_) {
      final projectId = Get.find<ProjectController>().selectedProject?.id;
      if (projectId != null) {
        selectedProjectId = projectId;
        fetchEmployeesByProject(projectId);
      } else if (isAllEmployeeSelected.value) {
        fetchAllEmployees();
      } else {
        clearEmployees();
      }
    });
  }

  Future<void> fetchAllProjects() async {
    isLoading.value = true;

    await _handleApiCall(
      ApiService.getProjects,
      onSuccess: (data) {
        projects = data.map((json) => ProjectModel.fromJson(json)).toList();
        logSafe(
          "Projects fetched: ${projects.length} projects loaded.",
          level: LogLevel.info,
        );
      },
      onEmpty: () {
        logSafe("No project data found or API call failed.",
            level: LogLevel.warning);
      },
    );

    isLoading.value = false;
    update();
  }

  void clearEmployees() {
    employees.clear();
    logSafe("Employees cleared", level: LogLevel.info);
    update(['employee_screen_controller']);
  }

  Future<void> fetchAllEmployees() async {
    isLoading.value = true;
    update(['employee_screen_controller']);

    await _handleApiCall(
      ApiService.getAllEmployees,
      onSuccess: (data) {
        employees.assignAll(data.map((json) => EmployeeModel.fromJson(json)));
        logSafe("All Employees fetched: ${employees.length} employees loaded.",
            level: LogLevel.info);
      },
      onEmpty: () {
        employees.clear();
        logSafe("No Employee data found or API call failed.",
            level: LogLevel.warning);
      },
    );

    isLoading.value = false;
    update(['employee_screen_controller']);
  }

  Future<void> fetchEmployeesByProject(String? projectId) async {
    if (projectId == null || projectId.isEmpty) {
      logSafe("Project ID is required but was null or empty.",
          level: LogLevel.error);
      return;
    }

    isLoading.value = true;

    await _handleApiCall(
      () => ApiService.getAllEmployeesByProject(projectId),
      onSuccess: (data) {
        employees.assignAll(data.map((json) => EmployeeModel.fromJson(json)));

        for (var emp in employees) {
          uploadingStates[emp.id] = false.obs;
        }

        logSafe(
          "Employees fetched: ${employees.length} for project $projectId",
          level: LogLevel.info,
        );
      },
      onEmpty: () {
        employees.clear();
        logSafe(
          "No employees found for project $projectId.",
          level: LogLevel.warning,
        );
      },
      onError: (e) {
        logSafe(
          "Error fetching employees for project $projectId",
          level: LogLevel.error,
          error: e,
        );
      },
    );

    isLoading.value = false;
    update(['employee_screen_controller']);
  }

  Future<void> 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;
  }

  Future<void> _handleApiCall(
    Future<List<dynamic>?> Function() apiCall, {
    required Function(List<dynamic>) 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);
      }
    }
  }

  Future<void> _handleSingleApiCall(
    Future<Map<String, dynamic>?> Function() apiCall, {
    required Function(Map<String, dynamic>) 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);
      }
    }
  }
}
