import 'package:flutter_bloc/flutter_bloc.dart';
import '../../domain/usecases/get_todays_shift_usecase.dart';
import '../../domain/usecases/get_attendance_status_usecase.dart';
import '../../domain/usecases/clock_in_usecase.dart';
import '../../domain/usecases/clock_out_usecase.dart';
import '../../domain/usecases/get_activity_log_usecase.dart';
import '../../domain/arguments/clock_in_arguments.dart';
import '../../domain/arguments/clock_out_arguments.dart';
import 'clock_in_event.dart';
import 'clock_in_state.dart';

class ClockInBloc extends Bloc<ClockInEvent, ClockInState> {
  final GetTodaysShiftUseCase _getTodaysShift;
  final GetAttendanceStatusUseCase _getAttendanceStatus;
  final ClockInUseCase _clockIn;
  final ClockOutUseCase _clockOut;
  final GetActivityLogUseCase _getActivityLog;

  ClockInBloc({
    required GetTodaysShiftUseCase getTodaysShift,
    required GetAttendanceStatusUseCase getAttendanceStatus,
    required ClockInUseCase clockIn,
    required ClockOutUseCase clockOut,
    required GetActivityLogUseCase getActivityLog,
  })  : _getTodaysShift = getTodaysShift,
        _getAttendanceStatus = getAttendanceStatus,
        _clockIn = clockIn,
        _clockOut = clockOut,
        _getActivityLog = getActivityLog,
        super(ClockInState(selectedDate: DateTime.now())) {
    on<ClockInPageLoaded>(_onLoaded);
    on<DateSelected>(_onDateSelected);
    on<CheckInRequested>(_onCheckIn);
    on<CheckOutRequested>(_onCheckOut);
    on<CheckInModeChanged>(_onModeChanged);
  }

  AttendanceStatus _mapToStatus(Map<String, dynamic> map) {
    return AttendanceStatus(
      isCheckedIn: map['isCheckedIn'] as bool? ?? false,
      checkInTime: map['checkInTime'] as DateTime?,
      checkOutTime: map['checkOutTime'] as DateTime?,
      activeShiftId: map['activeShiftId'] as String?,
    );
  }

  Future<void> _onLoaded(
    ClockInPageLoaded event,
    Emitter<ClockInState> emit,
  ) async {
    emit(state.copyWith(status: ClockInStatus.loading));
    try {
      final shift = await _getTodaysShift();
      final statusMap = await _getAttendanceStatus();
      final activity = await _getActivityLog();

      emit(state.copyWith(
        status: ClockInStatus.success,
        todayShift: shift,
        attendance: _mapToStatus(statusMap),
        activityLog: activity,
      ));
    } catch (e) {
      emit(state.copyWith(
        status: ClockInStatus.failure,
        errorMessage: e.toString(),
      ));
    }
  }

  void _onDateSelected(
    DateSelected event,
    Emitter<ClockInState> emit,
  ) {
    emit(state.copyWith(selectedDate: event.date));
  }

  void _onModeChanged(
    CheckInModeChanged event,
    Emitter<ClockInState> emit,
  ) {
    emit(state.copyWith(checkInMode: event.mode));
  }

  Future<void> _onCheckIn(
    CheckInRequested event,
    Emitter<ClockInState> emit,
  ) async {
    emit(state.copyWith(status: ClockInStatus.actionInProgress));
    try {
      final newStatusMap = await _clockIn(
        ClockInArguments(shiftId: event.shiftId, notes: event.notes),
      );
      emit(state.copyWith(
        status: ClockInStatus.success,
        attendance: _mapToStatus(newStatusMap),
      ));
    } catch (e) {
      emit(state.copyWith(
        status: ClockInStatus.failure,
        errorMessage: e.toString(),
      ));
    }
  }

  Future<void> _onCheckOut(
    CheckOutRequested event,
    Emitter<ClockInState> emit,
  ) async {
    emit(state.copyWith(status: ClockInStatus.actionInProgress));
    try {
      final newStatusMap = await _clockOut(
        ClockOutArguments(
          notes: event.notes,
          breakTimeMinutes: 0, // Should be passed from event if supported
        ),
      );
      emit(state.copyWith(
        status: ClockInStatus.success,
        attendance: _mapToStatus(newStatusMap),
      ));
    } catch (e) {
      emit(state.copyWith(
        status: ClockInStatus.failure,
        errorMessage: e.toString(),
      ));
    }
  }
}
