import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/krow_domain.dart';
import '../../domain/arguments/get_emergency_contacts_arguments.dart';
import '../../domain/arguments/save_emergency_contacts_arguments.dart';
import '../../domain/usecases/get_emergency_contacts_usecase.dart';
import '../../domain/usecases/save_emergency_contacts_usecase.dart';

// Events
abstract class EmergencyContactEvent extends Equatable {
  const EmergencyContactEvent();

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

class EmergencyContactsLoaded extends EmergencyContactEvent {}

class EmergencyContactAdded extends EmergencyContactEvent {}

class EmergencyContactRemoved extends EmergencyContactEvent {
  final int index;

  const EmergencyContactRemoved(this.index);

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

class EmergencyContactUpdated extends EmergencyContactEvent {
  final int index;
  final EmergencyContact contact;

  const EmergencyContactUpdated(this.index, this.contact);

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

class EmergencyContactsSaved extends EmergencyContactEvent {}

// State
enum EmergencyContactStatus { initial, loading, success, saving, failure }

class EmergencyContactState extends Equatable {
  final EmergencyContactStatus status;
  final List<EmergencyContact> contacts;
  final String? errorMessage;

  const EmergencyContactState({
    this.status = EmergencyContactStatus.initial,
    this.contacts = const [],
    this.errorMessage,
  });

  EmergencyContactState copyWith({
    EmergencyContactStatus? status,
    List<EmergencyContact>? contacts,
    String? errorMessage,
  }) {
    return EmergencyContactState(
      status: status ?? this.status,
      contacts: contacts ?? this.contacts,
      errorMessage: errorMessage ?? this.errorMessage,
    );
  }

  bool get isValid {
    if (contacts.isEmpty) return false;
    // Check if at least one contact is valid (or all?) 
    // Usually all added contacts should be valid.
    return contacts.every((c) => c.name.isNotEmpty && c.phone.isNotEmpty);
  }

  @override
  List<Object?> get props => [status, contacts, errorMessage];
}

// BLoC
class EmergencyContactBloc
    extends Bloc<EmergencyContactEvent, EmergencyContactState> {
  final GetEmergencyContactsUseCase getEmergencyContacts;
  final SaveEmergencyContactsUseCase saveEmergencyContacts;
  final String staffId;

  EmergencyContactBloc({
    required this.getEmergencyContacts,
    required this.saveEmergencyContacts,
    required this.staffId,
  }) : super(const EmergencyContactState()) {
    on<EmergencyContactsLoaded>(_onLoaded);
    on<EmergencyContactAdded>(_onAdded);
    on<EmergencyContactRemoved>(_onRemoved);
    on<EmergencyContactUpdated>(_onUpdated);
    on<EmergencyContactsSaved>(_onSaved);
  }

  Future<void> _onLoaded(
    EmergencyContactsLoaded event,
    Emitter<EmergencyContactState> emit,
  ) async {
    emit(state.copyWith(status: EmergencyContactStatus.loading));
    try {
      final contacts = await getEmergencyContacts(
        GetEmergencyContactsArguments(staffId: staffId),
      );
      emit(state.copyWith(
        status: EmergencyContactStatus.success,
        contacts: contacts.isNotEmpty
            ? contacts
            : [const EmergencyContact(name: '', phone: '', relationship: 'family')],
      ));
    } catch (e) {
      emit(state.copyWith(
        status: EmergencyContactStatus.failure,
        errorMessage: e.toString(),
      ));
    }
  }

  void _onAdded(
    EmergencyContactAdded event,
    Emitter<EmergencyContactState> emit,
  ) {
    final updatedContacts = List<EmergencyContact>.from(state.contacts)
      ..add(const EmergencyContact(name: '', phone: '', relationship: 'family'));
    emit(state.copyWith(contacts: updatedContacts));
  }

  void _onRemoved(
    EmergencyContactRemoved event,
    Emitter<EmergencyContactState> emit,
  ) {
    final updatedContacts = List<EmergencyContact>.from(state.contacts)
      ..removeAt(event.index);
    emit(state.copyWith(contacts: updatedContacts));
  }

  void _onUpdated(
    EmergencyContactUpdated event,
    Emitter<EmergencyContactState> emit,
  ) {
    final updatedContacts = List<EmergencyContact>.from(state.contacts);
    updatedContacts[event.index] = event.contact;
    emit(state.copyWith(contacts: updatedContacts));
  }

  Future<void> _onSaved(
    EmergencyContactsSaved event,
    Emitter<EmergencyContactState> emit,
  ) async {
    emit(state.copyWith(status: EmergencyContactStatus.saving));
    try {
      await saveEmergencyContacts(
        SaveEmergencyContactsArguments(
          staffId: staffId,
          contacts: state.contacts,
        ),
      );
      emit(state.copyWith(status: EmergencyContactStatus.success));
    } catch (e) {
      emit(state.copyWith(
        status: EmergencyContactStatus.failure,
        errorMessage: e.toString(),
      ));
    }
  }
}
