import 'package:flutter/foundation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow/core/application/di/injectable.dart';

import '../../invoice_entity.dart';
import '../../invoices_repository.dart';
import 'invoice_event.dart';
import 'invoice_state.dart';

class InvoiceBloc extends Bloc<InvoiceEvent, InvoicesState> {
  var indexToStatus = <int, InvoiceStatusFilterType>{
    0: InvoiceStatusFilterType.all,
    1: InvoiceStatusFilterType.open,
    2: InvoiceStatusFilterType.disputed,
    3: InvoiceStatusFilterType.resolved,
    4: InvoiceStatusFilterType.paid,
    5: InvoiceStatusFilterType.overdue,
    6: InvoiceStatusFilterType.verified,
  };

  InvoiceBloc()
      : super(const InvoicesState(tabs: {
          0: InvoiceTabState(items: [], inLoading: true),
          1: InvoiceTabState(items: []),
          2: InvoiceTabState(items: []),
          3: InvoiceTabState(items: []),
          4: InvoiceTabState(items: []),
          5: InvoiceTabState(items: []),
          6: InvoiceTabState(items: []),
        })) {
    on<InvoiceInitialEvent>(_onInitial);
    on<InvoiceTabChangedEvent>(_onTabChanged);
    on<LoadTabInvoiceEvent>(_onLoadTabItems);
    on<LoadMoreInvoiceEvent>(_onLoadMoreTabItems);

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

  Future<void> _onInitial(InvoiceInitialEvent event, emit) async {
    add(const LoadTabInvoiceEvent(status: 0));
  }

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

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

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

  _fetchInvoices(
      int tabIndex, List<InvoiceListEntity>? 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(inLoading: true),
      },
    ));

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

      // if(items.isNotEmpty){
      //   items = List.generate(20, (i)=>items[0]);
      // }
      emit(state.copyWith(
        tabs: {
          ...state.tabs,
          tabIndex: currentTabState.copyWith(
            items: (previousItems ?? [])..addAll(items),
            hasMoreItems: items.isNotEmpty,
            inLoading: false,
          ),
        },
      ));
    } catch (e, s) {
      debugPrint(e.toString());
      debugPrint(s.toString());
      emit(state.copyWith(
        tabs: {
          ...state.tabs,
          tabIndex: currentTabState.copyWith(inLoading: false),
        },
      ));
    }
  }

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