import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:niogu_app/core/providers/app_provider.dart';
import 'package:niogu_app/core/enums/report_type.dart';
import 'package:niogu_app/core/enums/transaction_reference_type.dart';
import 'package:niogu_app/features/report/presentation/providers/report_provider.dart';
import 'package:niogu_app/features/report/transaction/data/repositories/transaction_report_repository_impl.dart';
import 'package:niogu_app/features/report/transaction/domain/entities/transaction_report.dart';
import 'package:niogu_app/features/report/transaction/domain/repositories/i_transaction_report_repository.dart';
import 'package:niogu_app/features/report/transaction/presentation/controllers/transaction_report_controller.dart';

final transactionReportRepositoryProvider =
    Provider<ITransactionReportRepository>((ref) {
      final appDatabase = ref.watch(appDatabaseProvider);
      return TransactionReportRepositoryImpl(appDatabase);
    });

final filteredByTransactionTypeProvider =
    StateProvider.autoDispose<TransactionType?>((ref) => null);

final transactionReportStreamProvider =
    StreamProvider.autoDispose<List<TransactionReportItem>>((ref) {
      final isLoggedIn = ref.watch(currentStatusLoginProvider);

      final transactionReportRepo = ref.watch(
        transactionReportRepositoryProvider,
      );

      final outletId = ref.watch(
        filteredByOutletProvider(ReportType.transaction),
      );

      final type = ref.watch(filteredByTransactionTypeProvider);

      final dateRange = ref.watch(
        filteredByDateTimeProvider(ReportType.transaction),
      );

      final startDate = dateRange?.start;

      final endDate = dateRange?.end;

      if (!isLoggedIn) {
        return Stream<List<TransactionReportItem>>.value([]);
      }

      return transactionReportRepo.watchTransactionItems(
        outletId: outletId,
        type: type,
        startDate: startDate,
        endDate: endDate,
      );
    });

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

final filteredTransactionReportProvider =
    Provider.autoDispose<AsyncValue<List<TransactionReportItem>>>((ref) {
      final transactionReportStreamAsync = ref.watch(
        transactionReportStreamProvider,
      );

      final transactionReportSearchAsync = ref.watch(
        transactionReportSearchProvider,
      );

      return transactionReportStreamAsync.when(
        data: (transactions) {
          if (transactionReportSearchAsync.trim().isEmpty) {
            return AsyncValue.data(transactions);
          }

          final filteredTransaction = transactions.where((transaction) {
            return transaction.transactionNumber.toLowerCase().contains(
              transactionReportSearchAsync.toLowerCase(),
            );
          }).toList();

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

final transactionReportEmptyProvider =
    Provider.autoDispose<TransactionReportItemEmpty>((ref) {
      final transactionReportStreamAsync = ref.watch(
        transactionReportStreamProvider,
      );

      final filteredTransactionReportAsync = ref.watch(
        filteredTransactionReportProvider,
      );

      final transactionReportSearchAsync = ref.watch(
        transactionReportSearchProvider,
      );

      if (transactionReportStreamAsync.isLoading) {
        return TransactionReportItemEmpty.loading;
      }

      final allTransactions = transactionReportStreamAsync.value ?? [];

      if (allTransactions.isEmpty) {
        return TransactionReportItemEmpty.empty_database;
      }

      final filteredTransaction = filteredTransactionReportAsync.value ?? [];

      if (transactionReportSearchAsync.isNotEmpty &&
          filteredTransaction.isEmpty) {
        return TransactionReportItemEmpty.empty_search_result;
      }

      return TransactionReportItemEmpty.has_data;
    });

final transactionReportControllerProvider =
    AsyncNotifierProvider.autoDispose<TransactionReportController, void>(
      TransactionReportController.new,
    );
