import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:tugas_akhir_supabase/domain/entities/crop_schedule.dart';
import 'package:tugas_akhir_supabase/domain/usecases/get_schedules.dart';

part 'crop_schedule_event.dart';
part 'crop_schedule_state.dart';

class CropScheduleBloc extends Bloc<CropScheduleEvent, CropScheduleState> {
  final GetSchedules getSchedules;
  final GetActiveSchedule getActiveSchedule;
  final CreateSchedule createSchedule;
  final UpdateSchedule updateSchedule;
  final DeleteSchedule deleteSchedule;

  CropScheduleBloc({
    required this.getSchedules,
    required this.getActiveSchedule,
    required this.createSchedule,
    required this.updateSchedule,
    required this.deleteSchedule,
  }) : super(CropScheduleInitial()) {
    on<LoadSchedules>(_onLoadSchedules);
    on<LoadActiveSchedule>(_onLoadActiveSchedule);
    on<AddSchedule>(_onAddSchedule);
    on<EditSchedule>(_onEditSchedule);
    on<RemoveSchedule>(_onRemoveSchedule);
  }

  Future<void> _onLoadSchedules(
    LoadSchedules event,
    Emitter<CropScheduleState> emit,
  ) async {
    emit(CropScheduleLoading());
    
    final result = await getSchedules(event.userId);
    
    result.fold(
      (failure) => emit(CropScheduleError(message: failure.message)),
      (schedules) => emit(CropScheduleLoaded(schedules: schedules)),
    );
  }

  Future<void> _onLoadActiveSchedule(
    LoadActiveSchedule event,
    Emitter<CropScheduleState> emit,
  ) async {
    emit(ActiveScheduleLoading());
    
    final result = await getActiveSchedule(event.userId);
    
    result.fold(
      (failure) => emit(CropScheduleError(message: failure.message)),
      (activeSchedule) => emit(ActiveScheduleLoaded(activeSchedule: activeSchedule)),
    );
  }

  Future<void> _onAddSchedule(
    AddSchedule event,
    Emitter<CropScheduleState> emit,
  ) async {
    emit(CropScheduleOperationInProgress());
    
    final params = CreateScheduleParams(
      userId: event.userId,
      schedule: event.schedule,
    );
    
    final result = await createSchedule(params);
    
    result.fold(
      (failure) => emit(CropScheduleOperationFailure(message: failure.message)),
      (schedule) {
        if (state is CropScheduleLoaded) {
          final currentSchedules = (state as CropScheduleLoaded).schedules;
          emit(CropScheduleLoaded(schedules: [...currentSchedules, schedule]));
        }
        emit(CropScheduleOperationSuccess());
      },
    );
  }

  Future<void> _onEditSchedule(
    EditSchedule event,
    Emitter<CropScheduleState> emit,
  ) async {
    emit(CropScheduleOperationInProgress());
    
    final params = UpdateScheduleParams(
      userId: event.userId,
      schedule: event.schedule,
    );
    
    final result = await updateSchedule(params);
    
    result.fold(
      (failure) => emit(CropScheduleOperationFailure(message: failure.message)),
      (updatedSchedule) {
        if (state is CropScheduleLoaded) {
          final currentSchedules = (state as CropScheduleLoaded).schedules;
          final updatedSchedules = currentSchedules.map((schedule) {
            return schedule.id == updatedSchedule.id ? updatedSchedule : schedule;
          }).toList();
          
          emit(CropScheduleLoaded(schedules: updatedSchedules));
        }
        emit(CropScheduleOperationSuccess());
      },
    );
  }

  Future<void> _onRemoveSchedule(
    RemoveSchedule event,
    Emitter<CropScheduleState> emit,
  ) async {
    emit(CropScheduleOperationInProgress());
    
    final params = DeleteScheduleParams(
      userId: event.userId,
      scheduleId: event.scheduleId,
    );
    
    final result = await deleteSchedule(params);
    
    result.fold(
      (failure) => emit(CropScheduleOperationFailure(message: failure.message)),
      (success) {
        if (state is CropScheduleLoaded) {
          final currentSchedules = (state as CropScheduleLoaded).schedules;
          final updatedSchedules = currentSchedules
              .where((schedule) => schedule.id != event.scheduleId)
              .toList();
          
          emit(CropScheduleLoaded(schedules: updatedSchedules));
        }
        emit(CropScheduleOperationSuccess());
      },
    );
  }
} 