import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../repository/history_repository.dart';
import '../utils/cache_manager.dart';

class TabState extends Equatable {
  final List data;
  final bool isLoading;
  final bool stopLoad;
  final int page;
  final String filter;
  final List<dynamic> activeForum;
  final bool reload;

  const TabState({
    this.data = const [],
    this.isLoading = false,
    this.stopLoad = false,
    this.page = 0,
    this.filter = 'none',
    this.activeForum = const [],
    this.reload = false
  });

  TabState copyWith({
    List? data,
    bool? isLoading,
    bool? stopLoad,
    int? page,
    String? filter,
    List? activeForum,
    bool? reload
  }) {
    return TabState(
      data: data ?? this.data,
      isLoading: isLoading ?? this.isLoading,
      stopLoad: stopLoad ?? this.stopLoad,
      page: page ?? this.page,
      filter: filter ?? this.filter,
      activeForum: activeForum ?? this.activeForum,
      reload: reload ?? this.reload,
    );
  }

  @override
  List<Object?> get props => [data, isLoading, stopLoad, page, filter, activeForum, reload];
}

class ReloadContainer extends TabState {}

// # Cubit for Ongoing Tab
class OngoingCubit extends Cubit<TabState> {
  final HistoryRepository historyRepo = HistoryRepository();

  OngoingCubit() : super(const TabState());

  Future<void> loadOngoing() async {
    if(state.stopLoad) return;

    if(state.data.isNotEmpty){
      emit(state.copyWith(isLoading: false));
    }

    if(state.page == 0) emit(state.copyWith(isLoading: true));

    String filter = '';
    int page = 0;
    int size = 30;
    bool stopLoad = false;

    switch(state.filter){
      case 'none':
        filter = '{"or":[{"f":["currentState","EQ","DIANTRIKAN"]},{"f":["currentState","EQ","DIPROSES"]},{"f":["currentState","EQ","DIMULAI"]}]}';
        break;
      case 'queue':
        filter = '{"or":[{"f":["currentState","EQ","DIANTRIKAN"]},{"f":["currentState","EQ","DIPROSES"]}]}';
        break;
      case 'done':
        filter = '{"f":["currentState","EQ","DIMULAI"]}';
        break;
      case 'hold':
        filter = '{"f":["currentState","EQ","HOLD"]}';
        break;
      default:
        filter = '{"or":[{"f":["currentState","EQ","DIANTRIKAN"]},{"f":["currentState","EQ","DIPROSES"]},{"f":["currentState","EQ","DIMULAI"]}]}';
    }

    if(state.page != 0) page = state.page;

    // cache manager
    String key = '#ongoing#$filter';
    var val = await CacheMan.readData(key);
    if(val != null && page == 0){
      emit(state.copyWith(data: val['data'], isLoading: false, stopLoad: stopLoad));
    }

    try {
      List tempData = List<dynamic>.from(state.data);

      final result = await historyRepo.getData(key, filter, page, size, state.activeForum);
      if(result.length < size) stopLoad = true;

      if(state.page > 0){
        for (var element in result) {
          tempData.add(element);
        }
      } else {
        tempData = result;
      }

      emit(state.copyWith(data: tempData, isLoading: false, stopLoad: stopLoad));
    } catch (e) {
      emit(state.copyWith(data: [], isLoading: false));
    }
  }

  void setFilter(currentFilter) {
    emit(state.copyWith(data: [], filter: currentFilter, page: 0, stopLoad: false));
    loadOngoing();
  }

  void loadNextPage() {
    emit(state.copyWith(page: state.page + 1));
    loadOngoing();
  }
}

// # Cubit for Done Tab
class DoneCubit extends Cubit<TabState> {
  final HistoryRepository historyRepo = HistoryRepository();

  DoneCubit() : super(const TabState());

  Future<void> loadDone() async {
    if(state.stopLoad || state.isLoading) return;
    emit(state.copyWith(isLoading: true));

    if(!state.reload) {
      if (state.data.isNotEmpty) {
        emit(state.copyWith(isLoading: false));
      }

      if (state.page == 0) emit(state.copyWith(isLoading: true));
    }

    String filter = '';
    int page = 0;
    int size = 30;
    bool stopLoad = false;

    switch(state.filter){
      case 'none':
        filter = '{"or":[{"f":["currentState","EQ","DISELESAIKAN"]},{"f":["currentState","EQ","TUNTAS"]},{"f":["currentState","EQ","DIBATALKAN"]}]}';
        break;
      case 'finish':
        filter = '{"or":[{"f":["currentState","EQ","DISELESAIKAN"]},{"f":["currentState","EQ","TUNTAS"]}]}';
        break;
      case 'cancel':
        filter = '{"f":["currentState","EQ","DIBATALKAN"]}';
        break;
      default:
        filter = '{"or":[{"f":["currentState","EQ","DISELESAIKAN"]},{"f":["currentState","EQ","TUNTAS"]},{"f":["currentState","EQ","DIBATALKAN"]}]}';
    }

    if(state.page != 0) page = state.page;

    // # cache manager
    String key = '#done#$filter';
    if(!state.reload) {
      var val = await CacheMan.readData(key);
      if (val != null && page == 0) {
        emit(state.copyWith(
            data: val['data'], isLoading: false, stopLoad: stopLoad));
      }
    }

    try {
      List tempData = List<dynamic>.from(state.data);

      final result = await historyRepo.getData(key, filter, page, size, state.activeForum);

      if(result.length < size) stopLoad = true;

      if(state.page > 0){
        for (var element in result) {
          tempData.add(element);
        }
      } else {
        tempData = result;
      }

      emit(state.copyWith(data: tempData, isLoading: false, stopLoad: stopLoad));
    } catch (e) {
      emit(state.copyWith(data: [], isLoading: false));
    }
  }

  void setFilter(currentFilter) {
    emit(state.copyWith(filter: currentFilter, page: 0, stopLoad: false));
    loadDone();
  }

  void loadNextPage() {
    emit(state.copyWith(page: state.page + 1));
    loadDone();
  }

  void reloadPage(){
    emit(state.copyWith(data: [], page: 0, stopLoad: false, isLoading: true, reload: true));
  }

  void setSatisfaction(int index, int tempRating) {
    emit(state.copyWith(isLoading: true));
    List tempData = List<dynamic>.from(state.data);
    tempData[index]['satisfactionRate'] = tempRating;

    emit(state.copyWith(data: tempData, isLoading: false));
  }
}
