import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:niogu_app/core/providers/app_provider.dart';
import 'package:niogu_app/features/goods/products/domain/entities/product.dart';
import 'package:niogu_app/features/pos/data/repositories/pos_repository_impl.dart';
import 'package:niogu_app/features/pos/domain/entities/pos.dart';
import 'package:niogu_app/features/pos/domain/repositories/i_pos_repository.dart';
import 'package:niogu_app/features/pos/presentation/controllers/pos_controller.dart';

final posRepositoryProvider = Provider<IPosRepository>((ref) {
  final appDatabase = ref.watch(appDatabaseProvider);
  return PosRepositoryImpl(appDatabase);
});

final displayProductPosStreamProvider =
    StreamProvider.autoDispose<List<DisplayProductPos>>((ref) {
      final posRepository = ref.watch(posRepositoryProvider);

      final currentOutletId = ref.watch(currentOutletIdProvider);
      
      if(currentOutletId == null) {
        return Stream<List<DisplayProductPos>>.value([]);
      }

      return posRepository.watchDisplayProductPos(currentOutletId);
    });

final displayProductPosBySearchProvider = StateProvider.autoDispose<String>(
  (ref) => '',
);

final filteredDisplayProductPosProvider =
    Provider.autoDispose<AsyncValue<List<DisplayProductPos>>>((ref) {
      final productStreamAsync = ref.watch(displayProductPosStreamProvider);
      final productSearchAsync = ref.watch(displayProductPosBySearchProvider);
      return productStreamAsync.when(
        data: (products) {
          if (productSearchAsync.trim().isEmpty) {
            return AsyncValue.data(products);
          }

          final filteredProduct = products.where((product) {
            return product.name.toLowerCase().contains(
              productSearchAsync.toLowerCase(),
            );
          }).toList();

          return AsyncValue.data(filteredProduct);
        },
        error: (error, stackTrace) {
          return AsyncValue.error(error, stackTrace);
        },
        loading: () => const AsyncValue.loading(),
      );
    });

final displayProductPosEmptyProvider = Provider.autoDispose<ProductEmpty>((
  ref,
) {
  final productStreamAsync = ref.watch(displayProductPosStreamProvider);
  final filteredProductAsync = ref.watch(filteredDisplayProductPosProvider);
  final productSearchAsync = ref.watch(displayProductPosBySearchProvider);

  if (productStreamAsync.isLoading) {
    return ProductEmpty.loading;
  }

  final allProducts = productStreamAsync.value ?? [];

  if (allProducts.isEmpty) {
    return ProductEmpty.empty_database;
  }

  final filteredProduct = filteredProductAsync.value ?? [];

  if (productSearchAsync.isNotEmpty && filteredProduct.isEmpty) {
    return ProductEmpty.empty_search_result;
  }

  return ProductEmpty.has_data;
});

final cartItemsControllerProvider =
    StateNotifierProvider<CartItemsController, Map<String, CartItems>>((ref) {
      return CartItemsController();
    });

final alreadyCustomerStreamProvider =
    StreamProvider.autoDispose<List<AlreadyCustomer>>((ref) {
      final posRepository = ref.watch(posRepositoryProvider);

      final currentOutletId = ref.watch(currentOutletIdProvider);
      
      if(currentOutletId == null) {
        return Stream<List<AlreadyCustomer>>.value([]);
      }

      return posRepository.watchAlreadyCustomers(currentOutletId);
    });

final alreadyCustomerSearchProvider = StateProvider.autoDispose<String>(
  (ref) => '',
);

final filteredAlreadyCustomerProvider =
    Provider.autoDispose<AsyncValue<List<AlreadyCustomer>>>((ref) {
      final alreadyCustomerStreamAsync = ref.watch(
        alreadyCustomerStreamProvider,
      );
      final alreadyCustomerSearchAsync = ref.watch(
        alreadyCustomerSearchProvider,
      );

      return alreadyCustomerStreamAsync.when(
        data: (customers) {
          if (alreadyCustomerSearchAsync.trim().isEmpty) {
            return AsyncValue.data(customers);
          }

          final filteredCustomers = customers.where((customer) {
            return customer.name.toLowerCase().contains(
              alreadyCustomerSearchAsync.toLowerCase(),
            );
          }).toList();

          return AsyncValue.data(filteredCustomers);
        },
        error: (error, stackTrace) => AsyncValue.error(error, stackTrace),
        loading: () => const AsyncValue.loading(),
      );
    });

final alreadyCustomerEmptyProvider = Provider.autoDispose<AlreadyCustomerEmpty>(
  (ref) {
    final alreadyCustomerStreamAsync = ref.watch(alreadyCustomerStreamProvider);
    final filteredAlreadyCustomerAsync = ref.watch(
      filteredAlreadyCustomerProvider,
    );
    final alreadyCustomerSearchAsync = ref.watch(alreadyCustomerSearchProvider);

    if (alreadyCustomerStreamAsync.isLoading) {
      return AlreadyCustomerEmpty.loading;
    }

    final allCustomers = alreadyCustomerStreamAsync.value ?? [];

    if (allCustomers.isEmpty) {
      return AlreadyCustomerEmpty.empty_database;
    }

    final filteredCustomer = filteredAlreadyCustomerAsync.value ?? [];

    if (alreadyCustomerSearchAsync.isNotEmpty && filteredCustomer.isEmpty) {
      return AlreadyCustomerEmpty.empty_search_result;
    }

    return AlreadyCustomerEmpty.has_data;
  },
);

final expandedAlreadyCustomerProvider = StateProvider.autoDispose
    .family<bool, String>((ref, customerId) => false);

final selectedCustomerProvider = StateProvider.autoDispose<SelectedCustomer?>(
  (ref) => null,
);

final posControllerProvider = AsyncNotifierProvider.autoDispose<PosController, void>(
  PosController.new,
);
