import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:farm_tpf/custom_model/TbCropDTO.dart';
import 'package:farm_tpf/data/api/app_exception.dart';
import 'package:farm_tpf/data/repository/repository.dart';
import 'package:farm_tpf/presentation/screens/plot/models/area_filter.request.dart';
import 'package:farm_tpf/presentation/screens/plot/models/crop_filter_request.dart';
import 'package:farm_tpf/presentation/screens/task/models/supply_filter.dart';
import 'package:flutter/material.dart';
import 'package:meta/meta.dart';

import '../../../../models/item_dropdown.dart';

part 'plot_event.dart';
part 'plot_state.dart';

class PlotBloc extends Bloc<PlotEvent, PlotState> {
  final Repository repository;
  PlotBloc({required this.repository}) : super(PlotInitial());
  static int pageSize = 20;

  final searchCtl = TextEditingController();
  var supplyRaws = <SupplyFilter>[];
  var supplies = ValueNotifier(<ItemDropDown>[]);
  var selectedSupply = ValueNotifier(<ItemDropDown>[]);

  var areaRaws = <AreaFilter>[];
  var areas = ValueNotifier(<ItemDropDown>[]);
  var selectedArea = ValueNotifier(<ItemDropDown>[]);

  @override
  Stream<PlotState> mapEventToState(
    PlotEvent event,
  ) async* {
    if (event is DataFetched && !(state is PlotSuccess && ((state as PlotSuccess).hasReachedMax ?? false))) {
      try {
        if (state is PlotInitial) {
          yield PlotLoading();
          final response = await getPlots(0);
          yield PlotSuccess(items: response, page: 0, hasReachedMax: true);
        }
        // if (state is PlotSuccess) {
        //   final currentState = state as PlotSuccess;
        //   if (currentState.hasReachedMax ?? false) {
        //     return;
        //   }
        //   int page = (currentState.page ?? 0) + 1;
        //   final response = await getPlots(page);
        //   yield response.isEmpty
        //       ? currentState.copyWith(hasReachedMax: true)
        //       : PlotSuccess(
        //           items: (currentState.items ?? []) + response,
        //           page: (currentState.page ?? 0) + 1,
        //           hasReachedMax: false,
        //         );
        // }
      } catch (e) {
        var errorString = AppException.handleError(e);
        yield PlotFailure(errorString: errorString);
      }
    }
    if (event is OnRefresh) {
      try {
        yield PlotLoading();
        final response = await getPlots(0);
        yield PlotSuccess(items: response, page: 0, hasReachedMax: true);
      } catch (e) {
        yield PlotFailure(errorString: AppException.handleError(e));
      }
    } else if (event is OnSearch) {
      try {
        yield PlotLoading();
        final response = await getPlots(0);
        yield PlotSuccess(items: response, page: 0, hasReachedMax: true);
      } catch (e) {
        yield PlotFailure(errorString: AppException.handleError(e));
      }
    }
  }

  Future<List<TbCropDTO>> getPlots(int page) async {
    var supplyIds = selectedSupply.value.length > 0
        ? selectedSupply.value
            .map(
              (e) => int.tryParse(e.key ?? '') ?? -1,
            )
            .toList()
        : <int>[];
    var areaIds = selectedArea.value.length > 0
        ? selectedArea.value
            .map(
              (e) => int.tryParse(e.key ?? '') ?? -1,
            )
            .toList()
        : <int>[];
    var filter = CropFilterRequest()
      ..supplyIds = supplyIds
      ..netHouseIds = areaIds
      ..code = searchCtl.text;
    return await repository.crops(page: 0, filter: filter);
  }

  Future<void> preparedData() async {
    try {
      await Future.delayed(const Duration(seconds: 0));
      // emit(CreateStampLoading());

      supplyRaws = await repository.getSuppliesFilter();
      supplies.value = supplyRaws
          .map(
            (e) => ItemDropDown(key: e.id?.toString(), value: e.name),
          )
          .toList();

      areaRaws = await repository.getAreasFilter();
      areas.value = areaRaws
          .map(
            (e) => ItemDropDown(key: e.id?.toString(), value: e.name),
          )
          .toList();
      // emit(CreateStampPrepareDataSuccessful());
    } catch (e) {
      print(e);
      // emit(CreateStampFailure(AppException.handleError(e)));
    }
  }
}
