import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:travel_mate/services/error_service.dart';
import 'group_event.dart';
import 'group_state.dart';
import '../../repositories/group_repository.dart';
import '../../models/group.dart';

class GroupBloc extends Bloc<GroupEvent, GroupState> {
  final GroupRepository _repository;
  StreamSubscription? _groupsSubscription;
  final _errorService = ErrorService();

  GroupBloc(this._repository) : super(GroupInitial()) {
    on<LoadGroupsByUserId>(_onLoadGroupsByUserId);
    on<_GroupsUpdated>(_onGroupsUpdated);
    on<LoadGroupsByTrip>(_onLoadGroupsByTrip);
    on<CreateGroup>(_onCreateGroup);
    on<CreateGroupWithMembers>(_onCreateGroupWithMembers);
    on<AddMemberToGroup>(_onAddMemberToGroup);
    on<RemoveMemberFromGroup>(_onRemoveMemberFromGroup);
    on<UpdateGroup>(_onUpdateGroup);
    on<DeleteGroup>(_onDeleteGroup);
  }

  Future<void> _onLoadGroupsByUserId(
    LoadGroupsByUserId event,
    Emitter<GroupState> emit,
  ) async {    
    try {
      emit(GroupLoading());
      await _groupsSubscription?.cancel();
      _groupsSubscription = _repository.getGroupsByUserId(event.userId).listen(
        (groups) {
          add(_GroupsUpdated(groups));
        },
        onError: (error) {
          add(_GroupsUpdated([], error: error.toString()));
        },
      );
    } catch (e, stackTrace) {
      _errorService.logError(e.toString(), stackTrace);
      emit(GroupError(e.toString()));
    }
  }

  Future<void> _onGroupsUpdated(
    _GroupsUpdated event,
    Emitter<GroupState> emit,
  ) async {
    if (event.error != null) {
      _errorService.logError(event.error!, StackTrace.current);
      emit(GroupError(event.error!));
    } else {
      emit(GroupsLoaded(event.groups));
    }
  }

  Future<void> _onLoadGroupsByTrip(
    LoadGroupsByTrip event,
    Emitter<GroupState> emit,
  ) async {
    try {
      emit(GroupLoading());
      final group = await _repository.getGroupByTripId(event.tripId);
      if (group != null) {
        emit(GroupsLoaded([group]));
      } else {
        emit(const GroupsLoaded([]));
      }
    } catch (e) {
      emit(GroupError(e.toString()));
    }
  }

  Future<void> _onCreateGroup(
    CreateGroup event,
    Emitter<GroupState> emit,
  ) async {
    try {
      emit(GroupLoading());
      final groupId = await _repository.createGroupWithMembers(
        group: event.group,
        members: [],
      );
      emit(GroupCreated(groupId: groupId));
      emit(const GroupOperationSuccess('Groupe créé avec succès'));
    } catch (e) {
      emit(GroupError('Erreur lors de la création: $e'));
    }
  }

  Future<void> _onCreateGroupWithMembers(
    CreateGroupWithMembers event,
    Emitter<GroupState> emit,
  ) async {
    try {
      emit(GroupLoading());
      final groupId = await _repository.createGroupWithMembers(
        group: event.group,
        members: event.members,
      );
      emit(GroupCreated(groupId: groupId));
    } catch (e) {
      emit(GroupError('Erreur lors de la création: $e'));
    }
  }

  Future<void> _onAddMemberToGroup(
    AddMemberToGroup event,
    Emitter<GroupState> emit,
  ) async {
    try {
      await _repository.addMember(event.groupId, event.member);
      emit(const GroupOperationSuccess('Membre ajouté'));
    } catch (e) {
      emit(GroupError('Erreur lors de l\'ajout: $e'));
    }
  }

  Future<void> _onRemoveMemberFromGroup(
    RemoveMemberFromGroup event,
    Emitter<GroupState> emit,
  ) async {
    try {
      await _repository.removeMember(event.groupId, event.userId);
      emit(const GroupOperationSuccess('Membre supprimé'));
    } catch (e) {
      emit(GroupError('Erreur lors de la suppression: $e'));
    }
  }

  Future<void> _onUpdateGroup(
    UpdateGroup event,
    Emitter<GroupState> emit,
  ) async {
    try {
      await _repository.updateGroup(event.groupId, event.group);
      emit(const GroupOperationSuccess('Groupe mis à jour'));
    } catch (e) {
      emit(GroupError('Erreur lors de la mise à jour: $e'));
    }
  }

  Future<void> _onDeleteGroup(
    DeleteGroup event,
    Emitter<GroupState> emit,
  ) async {
    try {
      await _repository.deleteGroup(event.tripId);
      emit(const GroupOperationSuccess('Groupe supprimé'));
    } catch (e) {
      emit(GroupError('Erreur lors de la suppression: $e'));
    }
  }

  @override
  Future<void> close() {
    _groupsSubscription?.cancel();
    return super.close();
  }
}

class _GroupsUpdated extends GroupEvent {
  final List<Group> groups;
  final String? error;

  const _GroupsUpdated(this.groups, {this.error});

  @override
  List<Object?> get props => [groups, error];
}