import 'dart:async';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
import 'package:aitrainer_app/model/model_change.dart';
import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
import 'package:aitrainer_app/repository/workout_tree_repository.dart';
import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/util/track.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';

part 'exercise_plan_event.dart';

part 'exercise_plan_state.dart';

class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
  final WorkoutTreeRepository menuTreeRepository;
  ExercisePlanRepository exercisePlanRepository = ExercisePlanRepository();
  late int customerId;

  ExercisePlanBloc({required this.menuTreeRepository}) : super(ExercisePlanInitial()) {
    on<ExercisePlanLoad>(_onLoad);
    on<ExercisePlanUpdateUI>(_onUpdateUI);
    on<ExercisePlanAddExercise>(_onAddExercise);
    on<ExercisePlanRemoveExercise>(_onRemoveExercise);
  }

  void _onLoad(ExercisePlanLoad event, Emitter<ExercisePlanState> emit) async {
    if (Cache().userLoggedIn == null || Cache().userLoggedIn!.customerId == null) {
      throw Exception("Please log in");
    }
    emit(ExercisePlanLoading());
    customerId = Cache().userLoggedIn!.customerId!;
    await this.getData();
    Track().track(TrackingEvent.my_custom_exercise_plan);
    emit(ExercisePlanReady());
  }

  void _onUpdateUI(ExercisePlanUpdateUI event, Emitter<ExercisePlanState> emit) {
    emit(ExercisePlanLoading());
    WorkoutMenuTree workoutTree = event.workoutTree;
    exercisePlanRepository.setActualPlanDetailByExerciseType(workoutTree.exerciseType!);
    workoutTree.selected = true;
    emit(ExercisePlanReady());
  }

  void _onAddExercise(ExercisePlanAddExercise event, Emitter<ExercisePlanState> emit) async {
    emit(ExercisePlanLoading());
    ExercisePlanDetail planDetail = event.exercisePlanDetail;
    exercisePlanRepository.actualPlanDetail = planDetail;

    if (exercisePlanRepository.getExercisePlanDetailSize() != 0) {
      await exercisePlanRepository.saveExercisePlan();
    }

    this.menuTreeRepository.sortedTree.forEach((key, value) {
      List<WorkoutMenuTree> listTreeItem = value;
      listTreeItem.forEach((element) {
        if (element.exerciseType!.exerciseTypeId == planDetail.exerciseTypeId) {
          element.selected = true;
        }
      });
    });
    emit(ExercisePlanReady());
  }

  void _onRemoveExercise(ExercisePlanRemoveExercise event, Emitter<ExercisePlanState> emit) async {
    emit(ExercisePlanLoading());
    ExercisePlanDetail planDetail = event.exercisePlanDetail;
    exercisePlanRepository.removeExerciseTypeFromPlanByExerciseTypeId(planDetail.exerciseTypeId);

    this.menuTreeRepository.sortedTree.forEach((key, value) {
      List<WorkoutMenuTree> listTreeItem = value;
      listTreeItem.forEach((element) {
        if (element.exerciseType!.exerciseTypeId == planDetail.exerciseTypeId) {
          element.selected = false;
        }
      });
    });

    if (exercisePlanRepository.getExercisePlanDetailSize() != 0) {
      await exercisePlanRepository.saveExercisePlan();
      Track().track(TrackingEvent.my_custom_exercise_plan_save);
    }
    emit(ExercisePlanReady());
  }

  Future<void> getData() async {
    exercisePlanRepository.setCustomerId(customerId);
    await exercisePlanRepository.getLastExercisePlan();
    await exercisePlanRepository.getExercisePlanDetails();
    menuTreeRepository.sortedTree.clear();
    menuTreeRepository.sortByMuscleType();

    menuTreeRepository.sortedTree.forEach((key, value) {
      print("menutree $key");
      List<WorkoutMenuTree> listWorkoutTree = value;
      listWorkoutTree.forEach((workoutTree) {
        workoutTree.selected = false;
        if (exercisePlanRepository.getExercisePlanDetailSize() > 0) {
          ExercisePlanDetail? planDetail = exercisePlanRepository.getExercisePlanDetailByExerciseId(workoutTree.exerciseTypeId);
          if (planDetail != null && planDetail.change != ModelChange.deleted) {
            workoutTree.selected = true;
          }
        }
      });
    });
  }

  void setExercisePlanRepository(ExercisePlanRepository repo) => exercisePlanRepository = repo;
}