import 'package:flutter/foundation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow/core/application/di/injectable.dart';
import 'package:krow/features/shifts/domain/blocs/shifts_list_bloc/shifts_event.dart';
import 'package:krow/features/shifts/domain/blocs/shifts_list_bloc/shifts_state.dart';
import 'package:krow/features/shifts/domain/services/force_clockout_service.dart';
import 'package:krow/features/shifts/domain/shift_entity.dart';
import 'package:krow/features/shifts/domain/shifts_repository.dart';

class ShiftsBloc extends Bloc<ShiftsEvent, ShiftsState> {
  var indexToStatus = <int, ShiftStatusFilterType>{
    0: ShiftStatusFilterType.assigned,
    1: ShiftStatusFilterType.confirmed,
    2: ShiftStatusFilterType.ongoing,
    3: ShiftStatusFilterType.completed,
    4: ShiftStatusFilterType.canceled,
  };

  ShiftsBloc()
      : super(const ShiftsState(tabs: {
          0: ShiftTabState(items: [], isLoading: true),
          1: ShiftTabState(items: []),
          2: ShiftTabState(items: []),
          3: ShiftTabState(items: []),
          4: ShiftTabState(items: []),
        })) {
    on<ShiftsInitialEvent>(_onInitial);
    on<ShiftsTabChangedEvent>(_onTabChanged);
    on<LoadTabShiftEvent>(_onLoadTabItems);
    on<LoadMoreShiftEvent>(_onLoadMoreTabItems);
    on<ReloadMissingBreakShift>(_onReloadMissingBreakShift);

    getIt<ShiftsRepository>().statusStream.listen((event) {
      add(LoadTabShiftEvent(status: event.index));
    });
  }

  Future<void> _onInitial(ShiftsInitialEvent event, emit) async {
    add(const LoadTabShiftEvent(status: 0));
    add(const LoadTabShiftEvent(status: 2));

    var missedShifts =
        await getIt<ShiftsRepository>().getMissBreakFinishedShift();
    if (missedShifts.isNotEmpty) {
      emit(state.copyWith(
        missedShifts: missedShifts,
      ));
    }
  }

  Future<void> _onTabChanged(ShiftsTabChangedEvent event, emit) async {
    emit(state.copyWith(tabIndex: event.tabIndex));
    final currentTabState = state.tabs[event.tabIndex]!;
    if (currentTabState.items.isEmpty && !currentTabState.isLoading) {
      add(LoadTabShiftEvent(status: event.tabIndex));
    }
  }

  Future<void> _onLoadTabItems(LoadTabShiftEvent event, emit) async {
    await _fetchShifts(event.status, null, emit);
  }

  Future<void> _onLoadMoreTabItems(LoadMoreShiftEvent event, emit) async {
    final currentTabState = state.tabs[event.status]!;
    if (!currentTabState.hasMoreItems || currentTabState.isLoading) return;
    await _fetchShifts(event.status, currentTabState.items, emit);
  }

  _fetchShifts(int tabIndex, List<ShiftEntity>? previousItems, emit) async {
    if (previousItems != null && previousItems.lastOrNull?.cursor == null) {
      return;
    }
    final currentTabState = state.tabs[tabIndex]!;

    emit(state.copyWith(
      tabs: {
        ...state.tabs,
        tabIndex: currentTabState.copyWith(isLoading: true),
      },
    ));

    try {
      var items = await getIt<ShiftsRepository>().getShifts(
        statusFilter: indexToStatus[tabIndex]!,
        lastItemId: previousItems?.lastOrNull?.cursor,
      );

      // if(items.isNotEmpty){
      //   items = List.generate(20, (i)=>items[0]);
      // }
      var allItems = (previousItems ?? [])..addAll(items);
      emit(state.copyWith(
        tabs: {
          ...state.tabs,
          tabIndex: currentTabState.copyWith(
            items: allItems,
            hasMoreItems: items.isNotEmpty,
            isLoading: false,
          ),
        },
      ));

      if (tabIndex == 2 &&
          allItems.isNotEmpty ) {
        getIt<ForceClockoutService>()
            .startTrackOngoingLocation(allItems.first, () {});
      }
    } catch (e, s) {
      debugPrint(e.toString());
      debugPrint(s.toString());
      emit(state.copyWith(
        tabs: {
          ...state.tabs,
          tabIndex: currentTabState.copyWith(isLoading: false),
        },
      ));
    }
  }

  Future<void> _onReloadMissingBreakShift(
      ReloadMissingBreakShift event, emit) async {
    emit(state.copyWith(missedShifts: []));
    var missedShifts =
        await getIt<ShiftsRepository>().getMissBreakFinishedShift();
    emit(state.copyWith(missedShifts: missedShifts));
  }

  @override
  Future<void> close() {
    getIt<ShiftsRepository>().dispose();
    return super.close();
  }
}
