import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
import 'package:syncrow_web/pages/roles_and_permission/model/roles_user_model.dart';
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/bloc/user_table_event.dart';
import 'package:syncrow_web/pages/roles_and_permission/users_page/users_table/bloc/user_table_state.dart';
import 'package:syncrow_web/services/user_permission.dart';
import 'package:syncrow_web/utils/constants/strings_manager.dart';
import 'package:syncrow_web/utils/helpers/shared_preferences_helper.dart';

class UserTableBloc extends Bloc<UserTableEvent, UserTableState> {
  UserTableBloc() : super(TableInitial()) {
    on<GetUsers>(_getUsers);
    on<ChangeUserStatus>(_changeUserStatus);
    on<SortUsersByNameAsc>(_toggleSortUsersByNameAsc);
    on<SortUsersByNameDesc>(_toggleSortUsersByNameDesc);
    on<DateOldestToNewestEvent>(_toggleSortUsersByDateOldestToNewest);
    on<DateNewestToOldestEvent>(_toggleSortUsersByDateNewestToOldest);
    on<SearchUsers>(_searchUsers);
    on<ChangePage>(_handlePageChange);
    on<FilterUsersByRoleEvent>(_filterUsersByRole);
    on<FilterUsersByJobEvent>(_filterUsersByJobTitle);
    on<FilterUsersByCreatedEvent>(_filterUsersByCreated);
    on<FilterUsersByDeActevateEvent>(_filterUserStatus);
    on<DeleteUserEvent>(_deleteUser);
    on<FilterClearEvent>(_filterClear);
  }
  int itemsPerPage = 20;
  int currentPage = 1;
  List<RolesUserModel> users = [];
  List<RolesUserModel> initialUsers = [];

  List<RolesUserModel> totalUsersCount = [];
  String currentSortOrder = '';

  String currentSortJopTitle = '';
  String currentSortRole = '';
  String currentSortCreatedDate = '';
  String currentSortStatus = '';
  String currentSortCreatedBy = '';

  String currentSortOrderDate = '';
  List<String> roleTypes = [];
  List<String> jobTitle = [];
  List<String> createdBy = [];
  List<String> status = ['active', 'invited', 'disabled'];

  Future<void> _getUsers(GetUsers event, Emitter<UserTableState> emit) async {
    emit(UsersLoadingState());
    try {
      final projectUuid = await ProjectManager.getProjectUUID() ?? '';

      roleTypes.clear();
      jobTitle.clear();
      createdBy.clear();
      users = await UserPermissionApi().fetchUsers(projectUuid);
      users.sort((a, b) {
        final dateA = _parseDateTime(a.createdDate);
        final dateB = _parseDateTime(b.createdDate);
        return dateB.compareTo(dateA);
      });
      for (var user in users) {
        roleTypes.add(user.roleType.toString());
      }
      for (var user in users) {
        jobTitle.add(user.jobTitle.toString());
      }
      for (var user in users) {
        createdBy.add(user.invitedBy.toString());
      }
      initialUsers = List.from(users);
      roleTypes = roleTypes.toSet().toList();
      jobTitle = jobTitle.toSet().toList();
      createdBy = createdBy.toSet().toList();
      _handlePageChange(ChangePage(1), emit);
      totalUsersCount = initialUsers;
      add(ChangePage(currentPage));
      emit(UsersLoadedState(users: users));
    } catch (e) {
      emit(ErrorState(e.toString()));
    }
  }

  Future<void> _deleteUser(
      DeleteUserEvent event, Emitter<UserTableState> emit) async {
    emit(UsersLoadingState());
    try {
      bool res = await UserPermissionApi().deleteUserById(event.userId);
      if (res == true) {
        Navigator.of(event.context).pop(true);
      } else {
        emit(const ErrorState('Something error'));
      }
      emit(UsersLoadedState(users: users));
    } catch (e) {
      emit(ErrorState(e.toString()));
    }
  }

  Future<void> _changeUserStatus(
      ChangeUserStatus event, Emitter<UserTableState> emit) async {
    try {
      final projectUuid = await ProjectManager.getProjectUUID() ?? '';

      emit(UsersLoadingState());
      bool res = await UserPermissionApi().changeUserStatusById(event.userId,
          event.newStatus == "disabled" ? false : true, projectUuid);
      if (res == true) {
        add(const GetUsers());
      }
      emit(UsersLoadedState(users: users));
    } catch (e) {
      emit(ErrorState(e.toString()));
    }
  }

  void _toggleSortUsersByNameAsc(
      SortUsersByNameAsc event, Emitter<UserTableState> emit) {
    selectedRoles.clear();
    selectedJobTitles.clear();
    selectedCreatedBy.clear();
    selectedStatuses.clear();
    if (currentSortOrder == "Asc") {
      emit(UsersLoadingState());
      currentSortOrder = "";
      users = List.from(users);
    } else {
      emit(UsersLoadingState());
      currentSortOrder = "Asc";
      users.sort((a, b) => a.firstName
          .toString()
          .toLowerCase()
          .compareTo(b.firstName.toString().toLowerCase()));
    }
    currentSortJopTitle = '';
    currentSortCreatedDate = '';
    currentSortStatus = '';
    currentSortCreatedBy = '';
    emit(UsersLoadedState(users: users));
  }

  void _toggleSortUsersByNameDesc(
      SortUsersByNameDesc event, Emitter<UserTableState> emit) {
    selectedRoles.clear();
    selectedJobTitles.clear();
    selectedCreatedBy.clear();
    selectedStatuses.clear();
    if (currentSortOrder == "Desc") {
      emit(UsersLoadingState());
      currentSortOrder = "";
      users = List.from(initialUsers);
    } else {
      emit(UsersLoadingState());
      currentSortOrder = "Desc";
      users.sort((a, b) => b.firstName!.compareTo(a.firstName!));
    }
    currentSortJopTitle = '';
    currentSortCreatedDate = '';
    currentSortStatus = '';
    currentSortCreatedBy = '';
    emit(UsersLoadedState(users: users));
  }

  void _toggleSortUsersByDateNewestToOldest(
      DateNewestToOldestEvent event, Emitter<UserTableState> emit) {
    selectedRoles.clear();
    selectedJobTitles.clear();
    selectedCreatedBy.clear();
    selectedStatuses.clear();
    if (currentSortOrderDate == "NewestToOldest") {
      emit(UsersLoadingState());
      currentSortOrder = "";
      currentSortOrderDate = "";
      users = List.from(initialUsers);
      emit(UsersLoadedState(users: users));
    } else {
      emit(UsersLoadingState());
      currentSortOrder = "NewestToOldest";
      users.sort((a, b) {
        final dateA = _parseDateTime(a.createdDate);
        final dateB = _parseDateTime(b.createdDate);
        return dateB.compareTo(dateA);
      });
      emit(UsersLoadedState(users: users));
    }
  }

  void _toggleSortUsersByDateOldestToNewest(
      DateOldestToNewestEvent event, Emitter<UserTableState> emit) {
    selectedRoles.clear();
    selectedJobTitles.clear();
    selectedCreatedBy.clear();
    selectedStatuses.clear();
    if (currentSortOrderDate == "OldestToNewest") {
      emit(UsersLoadingState());
      currentSortOrder = "";
      currentSortOrderDate = "";
      users = List.from(initialUsers);
      emit(UsersLoadedState(users: users));
    } else {
      emit(UsersLoadingState());
      users.sort((a, b) {
        final dateA = _parseDateTime(a.createdDate);
        final dateB = _parseDateTime(b.createdDate);
        return dateA.compareTo(dateB);
      });
      currentSortOrder = "OldestToNewest";
      emit(UsersLoadedState(users: users));
    }
  }

  DateTime _parseDateTime(String date) {
    try {
      final dateParts = date.split('/');
      final day = int.parse(dateParts[0]);
      final month = int.parse(dateParts[1]);
      final year = int.parse(dateParts[2]);
      return DateTime(year, month, day);
    } catch (e) {
      throw FormatException('Invalid date or time format: $date ');
    }
  }

  Future<void> _searchUsers(
      SearchUsers event, Emitter<UserTableState> emit) async {
    try {
      emit(TableSearch());
      final query = event.query.toLowerCase();
      final filteredUsers = initialUsers.where((user) {
        final fullName = "${user.firstName} ${user.lastName}".toLowerCase();
        final email = user.email.toLowerCase();
        return fullName.contains(query) || email.contains(query);
      }).toList();
      emit(UsersLoadedState(users: filteredUsers));
    } catch (e) {
      emit(ErrorState(e.toString()));
    }
  }

  void _paginateUsers(
      int pageNumber, int itemsPerPage, Emitter<UserTableState> emit) {
    final startIndex = (pageNumber - 1) * itemsPerPage;
    final endIndex = startIndex + itemsPerPage;
    if (startIndex >= users.length) {
      emit(const UsersLoadedState(users: []));
      return;
    }
    final paginatedUsers = users.sublist(
      startIndex,
      endIndex > users.length ? users.length : endIndex,
    );
    emit(UsersLoadedState(users: paginatedUsers));
  }

  void _handlePageChange(ChangePage event, Emitter<UserTableState> emit) {
    currentPage = event.pageNumber;
    const itemsPerPage = 20;
    final startIndex = (event.pageNumber - 1) * itemsPerPage;
    final endIndex = startIndex + itemsPerPage;
    if (startIndex >= users.length) {
      emit(const UsersLoadedState(users: []));
      return;
    }
    final paginatedUsers = users.sublist(
      startIndex,
      endIndex > users.length ? users.length : endIndex,
    );
    emit(UsersLoadedState(users: paginatedUsers));
  }

  Set<String> selectedRoles = {};
  Set<String> selectedJobTitles = {};
  Set<String> selectedCreatedBy = {};
  Set<String> selectedStatuses = {};

  void _filterUsersByRole(
      FilterUsersByRoleEvent event, Emitter<UserTableState> emit) {
    selectedRoles = event.selectedRoles!.toSet();

    final filteredUsers = initialUsers.where((user) {
      if (selectedRoles.isEmpty) return true;
      return selectedRoles.contains(user.roleType);
    }).toList();

    if (event.sortOrder == "Asc") {
      currentSortOrder = "Asc";
      filteredUsers.sort((a, b) => a.firstName
          .toString()
          .toLowerCase()
          .compareTo(b.firstName.toString().toLowerCase()));
    } else if (event.sortOrder == "Desc") {
      currentSortOrder = "Desc";
      filteredUsers.sort((a, b) => b.firstName!.compareTo(a.firstName!));
    } else {}
    currentSortOrder = "";
    currentSortCreatedDate = '';
    currentSortStatus = '';
    currentSortCreatedBy = '';
    currentSortJopTitle = '';
    currentSortOrderDate = "";

    totalUsersCount = filteredUsers;

    emit(UsersLoadedState(users: filteredUsers));
  }

  void _filterUsersByJobTitle(
      FilterUsersByJobEvent event, Emitter<UserTableState> emit) {
    selectedJobTitles = event.selectedJob!.toSet();
    emit(UsersLoadingState());
    final filteredUsers = initialUsers.where((user) {
      if (selectedJobTitles.isEmpty) return true;
      return selectedJobTitles.contains(user.jobTitle);
    }).toList();
    if (event.sortOrder == "Asc") {
      currentSortOrder = "Asc";
      filteredUsers.sort((a, b) => a.firstName
          .toString()
          .toLowerCase()
          .compareTo(b.firstName.toString().toLowerCase()));
    } else if (event.sortOrder == "Desc") {
      currentSortOrder = "Desc";
      filteredUsers.sort((a, b) => b.firstName!.compareTo(a.firstName!));
    } else {}
    currentSortOrder = "";
    currentSortCreatedDate = '';
    currentSortStatus = '';
    currentSortCreatedBy = '';
    currentSortRole = '';
    currentSortOrderDate = "";

    totalUsersCount = filteredUsers;

    emit(UsersLoadedState(users: filteredUsers));
  }

  void _filterUsersByCreated(
      FilterUsersByCreatedEvent event, Emitter<UserTableState> emit) {
    selectedCreatedBy = event.selectedCreatedBy!.toSet();

    final filteredUsers = initialUsers.where((user) {
      if (selectedCreatedBy.isEmpty) return true;
      return selectedCreatedBy.contains(user.invitedBy);
    }).toList();

    if (event.sortOrder == "Asc") {
      currentSortOrder = "Asc";
      filteredUsers.sort((a, b) => a.firstName
          .toString()
          .toLowerCase()
          .compareTo(b.firstName.toString().toLowerCase()));
    } else if (event.sortOrder == "Desc") {
      currentSortOrder = "Desc";
      filteredUsers.sort((a, b) => b.firstName!.compareTo(a.firstName!));
    } else {}
    currentSortOrder = '';
    currentSortRole = '';
    currentSortCreatedDate = '';
    currentSortStatus = '';
    currentSortOrderDate = "";

    totalUsersCount = filteredUsers;

    emit(UsersLoadedState(users: filteredUsers));
  }

  void _filterUserStatus(
      FilterUsersByDeActevateEvent event, Emitter<UserTableState> emit) {
    selectedStatuses = event.selectedActivate!.toSet();

    final filteredUsers = initialUsers.where((user) {
      if (selectedStatuses.isEmpty) return true;

      return selectedStatuses.any((status) {
        final userStatus = user.status?.toLowerCase() ?? '';
        switch (status.toLowerCase()) {
          case 'active':
            return user.isEnabled == true && userStatus != 'invited';
          case 'disabled':
            return user.isEnabled == false;
          case 'invited':
            return userStatus == 'invited';
          default:
            return false;
        }
      });
    }).toList();
    if (event.sortOrder == "Asc") {
      currentSortOrder = "Asc";
      filteredUsers.sort((a, b) => a.firstName
          .toString()
          .toLowerCase()
          .compareTo(b.firstName.toString().toLowerCase()));
    } else if (event.sortOrder == "Desc") {
      currentSortOrder = "Desc";
      filteredUsers.sort((a, b) => b.firstName!.compareTo(a.firstName!));
      totalUsersCount = filteredUsers;
    } else {}
    currentSortOrder = '';
    currentSortRole = '';
    currentSortCreatedDate = '';
    currentSortCreatedBy = '';
    currentSortOrderDate = "";

    emit(UsersLoadedState(users: filteredUsers));
  }

  void _resetAllFilters(Emitter<UserTableState> emit) {
    selectedRoles.clear();
    selectedJobTitles.clear();
    selectedCreatedBy.clear();
    selectedStatuses.clear();
    emit(UsersLoadedState(users: initialUsers));
  }

  void _filterClear(FilterClearEvent event, Emitter<UserTableState> emit) {
    selectedRoles.clear();
    selectedJobTitles.clear();
    selectedCreatedBy.clear();
    selectedStatuses.clear();
    emit(UsersLoadedState(users: initialUsers));
  }
}
