import 'package:flutter/widgets.dart';
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/global_project_model.dart';
import 'package:on_field_work/model/employees/assigned_projects_model.dart';
import 'package:on_field_work/controller/project_controller.dart';

class AssignProjectController extends GetxController {
  final String employeeId;
  final String jobRoleId;

  AssignProjectController({
    required this.employeeId,
    required this.jobRoleId,
  });

  final ProjectController projectController = Get.put(ProjectController());

  RxBool isLoading = false.obs;
  RxBool isAssigning = false.obs;

  RxList<String> assignedProjectIds = <String>[].obs;
  RxList<String> selectedProjects = <String>[].obs;
  RxList<GlobalProjectModel> allProjects = <GlobalProjectModel>[].obs;
  RxList<GlobalProjectModel> filteredProjects = <GlobalProjectModel>[].obs;

  @override
  void onInit() {
    super.onInit();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      fetchAllProjectsAndAssignments();
    });
  }

  /// Fetch all projects and assigned projects
  Future<void> fetchAllProjectsAndAssignments() async {
    isLoading.value = true;
    try {
      await projectController.fetchProjects();
      allProjects.assignAll(projectController.projects);
      filteredProjects.assignAll(allProjects); // initially show all

      final responseList = await ApiService.getAssignedProjects(employeeId);
      if (responseList != null) {
        final assignedProjects =
            responseList.map((e) => AssignedProject.fromJson(e)).toList();

        assignedProjectIds.assignAll(
          assignedProjects.map((p) => p.id).toList(),
        );
        selectedProjects.assignAll(assignedProjectIds);
      }

      logSafe("All Projects: ${allProjects.map((e) => e.id)}");
      logSafe("Assigned Project IDs: $assignedProjectIds");
    } catch (e, stack) {
      logSafe("Error fetching projects or assignments: $e",
          level: LogLevel.error);
      logSafe("StackTrace: $stack", level: LogLevel.debug);
    } finally {
      isLoading.value = false;
    }
  }

  /// Assign selected projects
  Future<bool> assignProjectsToEmployee() async {
    if (selectedProjects.isEmpty) {
      logSafe("No projects selected for assignment.", level: LogLevel.warning);
      return false;
    }

    final List<Map<String, dynamic>> projectPayload =
        selectedProjects.map((id) {
      return {"projectId": id, "jobRoleId": jobRoleId, "status": true};
    }).toList();

    isAssigning.value = true;
    try {
      final success = await ApiService.assignProjects(
        employeeId: employeeId,
        projects: projectPayload,
      );

      if (success) {
        logSafe("Projects assigned successfully.");
        assignedProjectIds.assignAll(selectedProjects);
        return true;
      } else {
        logSafe("Failed to assign projects.", level: LogLevel.error);
        return false;
      }
    } catch (e, stack) {
      logSafe("Error assigning projects: $e", level: LogLevel.error);
      logSafe("StackTrace: $stack", level: LogLevel.debug);
      return false;
    } finally {
      isAssigning.value = false;
    }
  }

  /// Toggle project selection
  void toggleProjectSelection(String projectId, bool isSelected) {
    if (isSelected) {
      if (!selectedProjects.contains(projectId)) {
        selectedProjects.add(projectId);
      }
    } else {
      selectedProjects.remove(projectId);
    }
  }

  /// Check if project is selected
  bool isProjectSelected(String projectId) {
    return selectedProjects.contains(projectId);
  }

  /// Select all / deselect all
  void toggleSelectAll() {
    if (areAllSelected()) {
      selectedProjects.clear();
    } else {
      selectedProjects.assignAll(allProjects.map((p) => p.id.toString()));
    }
  }

  /// Are all selected?
  bool areAllSelected() {
    return selectedProjects.length == allProjects.length &&
        allProjects.isNotEmpty;
  }

  /// Filter projects by search text
  void filterProjects(String query) {
    if (query.isEmpty) {
      filteredProjects.assignAll(allProjects);
    } else {
      filteredProjects.assignAll(
        allProjects
            .where((p) => p.name.toLowerCase().contains(query.toLowerCase()))
            .toList(),
      );
    }
  }
}
