/// Events for group-related operations in the GroupBloc.
///
/// This file defines all possible events that can be dispatched to the GroupBloc
/// to trigger group-related state changes and operations such as loading groups,
/// creating groups, managing members, and performing CRUD operations.
///
/// Event Categories:
/// - **Loading Events**: LoadGroupsByUserId, LoadGroupsByTrip
/// - **Creation Events**: CreateGroup, CreateGroupWithMembers
/// - **Member Management**: AddMemberToGroup, RemoveMemberFromGroup
/// - **Modification Events**: UpdateGroup, DeleteGroup
///
/// All events extend [GroupEvent] and implement [Equatable] for proper
/// equality comparison in the BLoC pattern.
library;
import 'package:equatable/equatable.dart';
import '../../models/group.dart';
import '../../models/group_member.dart';

/// Base class for all group-related events.
///
/// All group events must extend this class and implement the [props] getter
/// for proper equality comparison in the BLoC pattern.
abstract class GroupEvent extends Equatable {
  const GroupEvent();

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

/// Event to load all groups associated with a specific user.
///
/// This is the primary method for loading groups, as it retrieves all groups
/// where the user is a member, providing a comprehensive view of the user's
/// group memberships across different trips and activities.
///
/// Args:
///   [userId]: The unique identifier of the user whose groups should be loaded
class LoadGroupsByUserId extends GroupEvent {
  /// The unique identifier of the user
  final String userId;

  /// Creates a LoadGroupsByUserId event.
  ///
  /// Args:
  ///   [userId]: The user ID to load groups for
  const LoadGroupsByUserId(this.userId);

  @override
  List<Object?> get props => [userId];
}

// Load groups for a trip (maintained for compatibility)
/// Event to load groups associated with a specific trip.
///
/// This event is maintained for backward compatibility and specific use cases
/// where you need to load groups within the context of a particular trip.
/// Most trips have one primary group, but some may have multiple sub-groups.
///
/// Args:
///   [tripId]: The unique identifier of the trip whose groups should be loaded
class LoadGroupsByTrip extends GroupEvent {
  /// The unique identifier of the trip
  final String tripId;

  /// Creates a LoadGroupsByTrip event.
  ///
  /// Args:
  ///   [tripId]: The trip ID to load groups for
  const LoadGroupsByTrip(this.tripId);

  @override
  List<Object?> get props => [tripId];
}

// Create a simple group
/// Event to create a new group without any initial members.
///
/// This creates a basic group structure that can be populated with members
/// later using AddMemberToGroup events. Useful when setting up a group
/// before knowing all participants.
///
/// Args:
///   [group]: The group object containing basic information (name, description, etc.)
class CreateGroup extends GroupEvent {
  /// The group to be created
  final Group group;

  /// Creates a CreateGroup event.
  ///
  /// Args:
  ///   [group]: The group object to create
  const CreateGroup(this.group);

  @override
  List<Object?> get props => [group];
}

// Create a group with its members
/// Event to create a new group with an initial set of members.
///
/// This is the preferred method for group creation when you know all or most
/// of the participants upfront. It creates the group and adds all specified
/// members in a single operation, ensuring data consistency.
///
/// Args:
///   [group]: The group object containing basic information
///   [members]: List of initial members to add to the group
class CreateGroupWithMembers extends GroupEvent {
  /// The group to be created
  final Group group;
  
  /// Initial members to add to the group
  final List<GroupMember> members;

  /// Creates a CreateGroupWithMembers event.
  ///
  /// Args:
  ///   [group]: The group object to create
  ///   [members]: List of initial group members
  const CreateGroupWithMembers({
    required this.group,
    required this.members,
  });

  @override
  List<Object?> get props => [group, members];
}

// Add a member
/// Event to add a new member to an existing group.
///
/// This allows for dynamic group expansion by adding users to groups after
/// creation. The new member will gain access to group features like expenses,
/// messages, and shared resources.
///
/// Args:
///   [groupId]: The unique identifier of the target group
///   [member]: The group member object containing user information and role
class AddMemberToGroup extends GroupEvent {
  /// The unique identifier of the group
  final String groupId;
  
  /// The member to add to the group
  final GroupMember member;

  /// Creates an AddMemberToGroup event.
  ///
  /// Args:
  ///   [groupId]: The group ID to add the member to
  ///   [member]: The group member to add
  const AddMemberToGroup(this.groupId, this.member);

  @override
  List<Object?> get props => [groupId, member];
}

// Remove a member
/// Event to remove a member from a group.
///
/// This removes a user from the group, revoking their access to group features.
/// The removal will affect expense calculations and the user will no longer
/// receive group-related notifications or updates.
///
/// Args:
///   [groupId]: The unique identifier of the group
///   [userId]: The unique identifier of the user to remove
class RemoveMemberFromGroup extends GroupEvent {
  /// The unique identifier of the group
  final String groupId;
  
  /// The unique identifier of the user to remove
  final String userId;

  /// Creates a RemoveMemberFromGroup event.
  ///
  /// Args:
  ///   [groupId]: The group ID to remove the member from
  ///   [userId]: The user ID to remove
  const RemoveMemberFromGroup(this.groupId, this.userId);

  @override
  List<Object?> get props => [groupId, userId];
}

// Update a group
/// Event to update an existing group's information.
///
/// This allows modification of group properties such as name, description,
/// settings, or other metadata. Member management is handled through
/// separate add/remove member events.
///
/// Args:
///   [groupId]: The unique identifier of the group to update
///   [group]: The updated group object with new information
class UpdateGroup extends GroupEvent {
  /// The unique identifier of the group to update
  final String groupId;
  
  /// The updated group object
  final Group group;

  /// Creates an UpdateGroup event.
  ///
  /// Args:
  ///   [groupId]: The group ID to update
  ///   [group]: The updated group object
  const UpdateGroup(this.groupId, this.group);

  @override
  List<Object?> get props => [groupId, group];
}

// Delete a group
/// Event to permanently delete a group.
///
/// This is a destructive operation that removes the group and all associated
/// data. This action cannot be undone and will affect all group members.
/// Consider archiving instead of deleting for historical records.
///
/// Args:
///   [tripId]: The unique identifier of the trip whose group should be deleted
class DeleteGroup extends GroupEvent {
  /// The unique identifier of the trip (used to identify the group)
  final String tripId;

  /// Creates a DeleteGroup event.
  ///
  /// Args:
  ///   [tripId]: The trip ID whose group should be deleted
  const DeleteGroup(this.tripId);

  @override
  List<Object?> get props => [tripId];
}