import 'dart:async';
import 'dart:developer';

import 'package:bloc/bloc.dart';
import 'package:dartz/dartz.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:injectable/injectable.dart';

import '../../../domain/category/category.dart';

part 'category_loader_event.dart';
part 'category_loader_state.dart';
part 'category_loader_bloc.freezed.dart';

@injectable
class CategoryLoaderBloc
    extends Bloc<CategoryLoaderEvent, CategoryLoaderState> {
  final ICategoryRepository _categoryRepository;

  Timer? _searchDebounce;
  bool _isLoadingMore = false;

  CategoryLoaderBloc(this._categoryRepository)
    : super(CategoryLoaderState.initial()) {
    on<CategoryLoaderEvent>(_onCategoryLoaderEvent);
  }

  Future<void> _onCategoryLoaderEvent(
    CategoryLoaderEvent event,
    Emitter<CategoryLoaderState> emit,
  ) {
    return event.map(
      getCategories: (e) async {
        emit(state.copyWith(isLoadingMore: true));

        log(
          '📱 Loading categories - isActive: ${e.isActive}, forceRemote: ${e.forceRemote}',
        );

        final result = await _categoryRepository.getCategories(
          page: 1,
          limit: 50,
          isActive: e.isActive,
          search: e.search,
          forceRemote: e.forceRemote,
        );

        await result.fold(
          (failure) async {
            emit(
              state.copyWith(
                isLoadingMore: false,
                failureOptionCategory: optionOf(failure),
              ),
            );
          },
          (response) async {
            final categories = [Category.all(), ...response.categories];

            final totalPages = response.totalPages;
            final hasReachedMax = categories.length < 50 || 1 >= totalPages;

            log(
              '✅ Categories loaded: ${categories.length}, hasReachedMax: $hasReachedMax',
            );

            emit(
              state.copyWith(
                categories: categories,
                page: 1,
                hasReachedMax: hasReachedMax,
                isLoadingMore: false,
                failureOptionCategory: none(),
              ),
            );
          },
        );
      },
      loadMore: (e) async {
        final currentState = state;

        // ❌ HAPUS pengecekan is! _Loaded karena state cuma 1 class doang
        if (currentState.hasReachedMax ||
            _isLoadingMore ||
            currentState.isLoadingMore) {
          log(
            '⏹️ Load more blocked - hasReachedMax: ${currentState.hasReachedMax}, isLoadingMore: $_isLoadingMore',
          );
          return;
        }

        _isLoadingMore = true;
        emit(currentState.copyWith(isLoadingMore: true));

        final nextPage = currentState.page + 1; // ✅ Ganti currentPage jadi page
        log('📄 Loading more categories - page: $nextPage');

        try {
          final result = await _categoryRepository.getCategories(
            page: nextPage,
            limit: 10,
            isActive: true,
            search: currentState.searchQuery,
          );

          await result.fold(
            (failure) async {
              log('❌ Error loading more categories: $failure');
              emit(currentState.copyWith(isLoadingMore: false));
            },
            (response) async {
              final newCategories = response.categories;
              final totalPages = response.totalPages;

              // Prevent duplicate categories
              final currentCategoryIds = currentState.categories
                  .map((c) => c.id)
                  .toSet();
              final filteredNewCategories = newCategories
                  .where(
                    (category) => !currentCategoryIds.contains(category.id),
                  )
                  .toList();

              final allCategories = List<Category>.from(currentState.categories)
                ..addAll(filteredNewCategories);

              final hasReachedMax =
                  newCategories.length < 10 || nextPage >= totalPages;

              log(
                '✅ More categories loaded: ${filteredNewCategories.length} new, total: ${allCategories.length}',
              );

              emit(
                currentState.copyWith(
                  categories: allCategories,
                  hasReachedMax: hasReachedMax,
                  page: nextPage, // ✅ Update page
                  isLoadingMore: false,
                ),
              );
            },
          );
        } catch (e) {
          log('❌ Exception loading more categories: $e');
          emit(currentState.copyWith(isLoadingMore: false));
        } finally {
          _isLoadingMore = false;
        }
      },
      refresh: (e) async {
        final currentState = state;
        bool isActive = true;
        String? searchQuery = currentState.searchQuery;

        _isLoadingMore = false;
        _searchDebounce?.cancel();

        log('🔄 Refreshing categories');

        // Clear local cache
        _categoryRepository.clearCache();

        add(
          CategoryLoaderEvent.getCategories(
            isActive: isActive,
            search: searchQuery,
            forceRemote: true, // Force remote refresh
          ),
        );
      },
      search: (e) async {
        // Cancel previous search
        _searchDebounce?.cancel();

        // Debounce search for better UX
        _searchDebounce = Timer(const Duration(milliseconds: 300), () async {
          emit(state.copyWith(isLoadingMore: true));
          _isLoadingMore = false;

          log('🔍 Searching categories: "${e.query}"');

          final result = await _categoryRepository.getCategories(
            page: 1,
            limit: 20, // More results for search
            isActive: e.isActive,
            search: e.query,
          );

          await result.fold(
            (failure) async {
              log('❌ Search error: $failure');
              emit(
                state.copyWith(
                  isLoadingMore: false,
                  failureOptionCategory: optionOf(failure),
                ),
              );
            },
            (response) async {
              final categories = [Category.all(), ...response.categories];
              final totalPages = response.totalPages;
              final hasReachedMax = categories.length < 20 || 1 >= totalPages;

              log('✅ Search results: ${categories.length} categories found');

              emit(
                state.copyWith(
                  categories: categories,
                  hasReachedMax: hasReachedMax,
                  page: 1,
                  isLoadingMore: false,
                  failureOptionCategory: none(),
                  searchQuery: e.query,
                ),
              );
            },
          );
        });
      },
      syncAll: (e) async {
        emit(state.copyWith(isLoadingMore: true));

        log('🔄 Starting full category sync...');

        final result = await _categoryRepository.syncAllCategories();

        await result.fold(
          (failure) async {
            log('❌ Sync failed: $failure');
            emit(
              state.copyWith(
                isLoadingMore: false,
                failureOptionCategory: optionOf(failure),
              ),
            );

            // After sync error, try to load local data
            Timer(const Duration(seconds: 2), () {
              add(const CategoryLoaderEvent.getCategories());
            });
          },
          (successMessage) async {
            log('✅ Sync completed: $successMessage');
            emit(
              state.copyWith(
                isLoadingMore: false,
                failureOptionCategory: none(),
              ),
            );

            // After successful sync, load the updated data
            Timer(const Duration(seconds: 1), () {
              add(const CategoryLoaderEvent.getCategories());
            });
          },
        );
      },
      getAllCategories: (e) async {
        try {
          log('📋 Loading all categories for dropdown...');

          // final categories = await _categoryRepository.getAllCategories();

          // emit(
          //   state.copyWith(
          //     categories: categories,
          //     isLoadingMore: false,
          //     failureOptionCategory: none(),
          //   ),
          // );
          // log('✅ All categories loaded: ${categories.length}');
        } catch (e) {
          log('❌ Error loading all categories: $e');
          emit(
            state.copyWith(
              isLoadingMore: false,
              failureOptionCategory: optionOf(
                CategoryFailure.dynamicErrorMessage(
                  'Gagal memuat semua kategori: $e',
                ),
              ),
            ),
          );
        }
      },
      getDatabaseStats: (e) async {
        try {
          final stats = await _categoryRepository.getDatabaseStats();
          log('📊 Category database stats retrieved: $stats');

          // You can emit a special state here if needed for UI updates
          // For now, just log the stats
        } catch (e) {
          log('❌ Error getting category database stats: $e');
        }
      },
      clearCache: (e) async {
        log('🧹 Manually clearing category cache');
        _categoryRepository.clearCache();

        // Refresh current data after cache clear
        add(const CategoryLoaderEvent.refresh());
      },
    );
  }

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