import 'package:drift/drift.dart';
import 'package:niogu_app/core/database/app_database.dart';
import 'package:niogu_app/core/database/tables/customers.dart';
import 'package:niogu_app/core/database/tables/orders.dart';
import 'package:niogu_app/core/database/tables/purchases.dart';
import 'package:niogu_app/core/database/tables/suppliers.dart';
import 'package:niogu_app/core/database/tables/transactions.dart';
import 'package:niogu_app/core/utils/extension_format.dart';
import 'package:niogu_app/core/enums/transaction_reference_type.dart';
import 'package:niogu_app/features/report/transaction/domain/entities/transaction_report.dart';

part 'transaction_dao.g.dart';

@DriftAccessor(tables: [Customers, Suppliers, Transactions, Orders, Purchases])
class TransactionDao extends DatabaseAccessor<AppDatabase>
    with _$TransactionDaoMixin {
  TransactionDao(AppDatabase db) : super(db);

  Stream<List<TransactionReportItem>> watchAllTransactionItems({
    String? outletId,
    TransactionType? type,
    DateTime? startDate,
    DateTime? endDate,
  }) async* {
    final query = selectOnly(transactions)
      ..addColumns([
        transactions.referenceType,
        transactions.referenceId,
        transactions.referenceNumber,
        transactions.stakeholder,
        transactions.transactionType,
        transactions.category,
        transactions.amount,
        transactions.createdAt,
      ])
      ..orderBy([OrderingTerm.desc(transactions.createdAt)])
      ..where(
        outletId != null
            ? transactions.outletId.equals(outletId)
            : const Constant(true),
      )
      ..where(
        type != null
            ? transactions.transactionType.equals(type.type)
            : const Constant(true),
      )
      ..where(
        (startDate != null && endDate != null)
            ? transactions.createdAt.isBiggerOrEqualValue(startDate) &
                  transactions.createdAt.isSmallerThanValue(
                    endDate.add(const Duration(days: 1)),
                  )
            : const Constant(true),
      );

    yield* query.watch().map((rows) {
      return rows.map((row) {
        final String id = row.read(transactions.referenceId)!;

        final String transactionNumber = row.read(
          transactions.referenceNumber,
        )!;

        final String title = row.read(transactions.category) ?? '';

        final bool isIncome =
            (row.read(transactions.transactionType) ?? '') == 'income';

        final String stakeholder = row.read(transactions.stakeholder) != null
            ? "• ${row.read(transactions.stakeholder)}"
            : "";

        final String subtitle =
            "${transactionNumber.toUniqueNumberCleaner()} $stakeholder";

        final double amount = row.read(transactions.amount) ?? 0.0;

        final DateTime date =
            row.read(transactions.createdAt) ?? DateTime.now();

        return TransactionReportItem(
          id: id,
          transactionNumber: transactionNumber,
          title: title,
          subtitle: subtitle,
          amount: amount,
          date: date,
          isIncome: isIncome,
        );
      }).toList();
    });
  }
}
