import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:enaklo_pos/data/datasources/product_remote_datasource.dart';
import 'package:enaklo_pos/data/models/response/product_response_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

part 'get_products_event.dart';
part 'get_products_state.dart';
part 'get_products_bloc.freezed.dart';

class GetProductsBloc extends Bloc<GetProductsEvent, GetProductsState> {
  final ProductRemoteDatasource _productRemoteDatasource;

  // Debouncing untuk mencegah multiple load more calls
  Timer? _loadMoreDebounce;
  bool _isLoadingMore = false;

  GetProductsBloc(this._productRemoteDatasource)
      : super(GetProductsState.initial()) {
    on<_Fetch>(_onGetProduct);
    on<_LoadMore>(_onLoadMore);
    on<_Refresh>(_onRefresh);
  }

  @override
  Future<void> close() {
    _loadMoreDebounce?.cancel();
    return super.close();
  }

  // Debounce transformer untuk load more
  // EventTransformer<T> _debounceTransformer<T>() {
  //   return (events, mapper) {
  //     return events
  //         .debounceTime(const Duration(milliseconds: 300))
  //         .asyncExpand(mapper);
  //   };
  // }

  // Initial load
  Future<void> _onGetProduct(
    _Fetch event,
    Emitter<GetProductsState> emit,
  ) async {
    emit(const _Loading());
    _isLoadingMore = false; // Reset loading state

    final result = await _productRemoteDatasource.getProducts(
      page: 1,
      limit: 10,
    );

    await result.fold(
      (failure) async => emit(_Error(failure)),
      (response) async {
        final products = response.data?.products ?? [];
        final hasReachedMax = products.length < 10;

        emit(_Success(
          products: products,
          hasReachedMax: hasReachedMax,
          currentPage: 1,
          isLoadingMore: false,
        ));
      },
    );
  }

  // Load more with enhanced debouncing
  Future<void> _onLoadMore(
    _LoadMore event,
    Emitter<GetProductsState> emit,
  ) async {
    final currentState = state;

    // Enhanced validation
    if (currentState is! _Success ||
        currentState.hasReachedMax ||
        _isLoadingMore ||
        currentState.isLoadingMore) {
      return;
    }

    _isLoadingMore = true;

    // Emit loading more state
    emit(currentState.copyWith(isLoadingMore: true));

    final nextPage = currentState.currentPage + 1;

    try {
      final result = await _productRemoteDatasource.getProducts(
        page: nextPage,
        limit: 10,
      );

      await result.fold(
        (failure) async {
          // On error, revert loading state but don't show error
          // Just silently fail and allow retry
          emit(currentState.copyWith(isLoadingMore: false));
          _isLoadingMore = false;
        },
        (response) async {
          final newProducts = response.data?.products ?? [];

          // Prevent duplicate products
          final currentProductIds =
              currentState.products.map((p) => p.id).toSet();
          final filteredNewProducts = newProducts
              .where((product) => !currentProductIds.contains(product.id))
              .toList();

          final allProducts = List<Product>.from(currentState.products)
            ..addAll(filteredNewProducts);

          final hasReachedMax = newProducts.length < 10;

          emit(_Success(
            products: allProducts,
            hasReachedMax: hasReachedMax,
            currentPage: nextPage,
            isLoadingMore: false,
          ));

          _isLoadingMore = false;
        },
      );
    } catch (e) {
      // Handle unexpected errors
      emit(currentState.copyWith(isLoadingMore: false));
      _isLoadingMore = false;
    }
  }

  // Refresh data
  Future<void> _onRefresh(
    _Refresh event,
    Emitter<GetProductsState> emit,
  ) async {
    _isLoadingMore = false;
    _loadMoreDebounce?.cancel();
    add(const _Fetch());
  }
}
