import 'package:drift/drift.dart';
import 'package:niogu_app/core/database/app_database.dart'
    hide Product, PurchaseItem;
import 'package:niogu_app/core/database/tables/purchase_items.dart';
import 'package:niogu_app/core/database/tables/purchases.dart';
import 'package:niogu_app/core/utils/extension_format.dart';
import 'package:niogu_app/core/enums/payment_status.dart';
import 'package:niogu_app/core/enums/purchase_status.dart';
import 'package:niogu_app/core/enums/sync_status.dart';
import 'package:niogu_app/features/report/transaction/domain/entities/transaction_report.dart';

part 'purchase_dao.g.dart';

@DriftAccessor(
  tables: [
    Purchases,
    PurchaseItems,
  ],
)
class PurchaseDao extends DatabaseAccessor<AppDatabase>
    with _$PurchaseDaoMixin {
  PurchaseDao(AppDatabase db) : super(db);

  Future<PurchaseDetail> getPurchaseDetail(String purchaseId) async {
    final query =
        selectOnly(purchases).join([
            innerJoin(
              purchaseItems,
              purchaseItems.purchaseId.equalsExp(purchases.localId),
            )
          ])
          ..addColumns([
            purchases.localId,
            purchases.purchaseNumber,
            purchases.createdAt,
            purchases.paymentStatus,
            purchases.purchaseStatus,
            purchases.outletNameSnapshot,
            purchases.supplierNameSnapshot,
            purchases.supplierPhoneNumberSnapshot,
            purchases.adminNameSnapshot,
            purchases.notes,
            purchaseItems.itemNameSnapshot,
            purchaseItems.itemVariantNameSnapshot,
            purchaseItems.purchasePriceSnaphot,
            purchaseItems.quantity,
            purchaseItems.subtotal,
            purchases.totalPurchase,
            purchases.discount,
            purchases.tax,
            purchases.totalAmount,
            purchases.amountPaid,
            purchases.changeAmount,
            purchases.underPaymentAmount,
            purchases.debtAmount,
            purchases.paymentProofPath,
          ])
          ..where(purchases.localId.equals(purchaseId));

    final results = await query.get();

    final Map<String, PurchaseDetail> groupedMap = {};

    for (final row in results) {
      final String purchaseId = row.read(purchases.localId) ?? '';

      final String purchaseNumber = (row.read(purchases.purchaseNumber) ?? '')
          .toUniqueNumberCleaner();

      final DateTime purchaseDate =
          row.read(purchases.createdAt) ?? DateTime.now();

      final String status = row.read(purchases.paymentStatus) ?? '';

      final PaymentStatus paymentStatus = PaymentStatus.values.byName(status);

      final String outletName = row.read(purchases.outletNameSnapshot) ?? '';

      final String userName = row.read(purchases.adminNameSnapshot) ?? '';

      final PurchaseStatus purchaseStatus = PurchaseStatus.values.byName(
        (row.read(purchases.purchaseStatus)) ?? '',
      );

      final String? supplierName = row.read(purchases.supplierNameSnapshot);

      final String? supplierPhone = row.read(purchases.supplierPhoneNumberSnapshot);

      final String? note = row.read(purchases.notes);

      final double totalPurchase = row.read(purchases.totalPurchase) ?? 0.0;

      final double discount = row.read(purchases.discount) ?? 0.0;

      final double tax = row.read(purchases.tax) ?? 0.0;

      final double totalAmount = row.read(purchases.totalAmount) ?? 0.0;

      final double payAmount = row.read(purchases.amountPaid) ?? 0.0;

      final double changeAmount = row.read(purchases.changeAmount) ?? 0.0;

      final double underPaymentAmount =
          row.read(purchases.underPaymentAmount) ?? 0.0;

      final double debtAmount = row.read(purchases.debtAmount) ?? 0.0;

      final String? paymentProofPath = row.read(purchases.paymentProofPath);

      groupedMap.putIfAbsent(purchaseId, () {
        return PurchaseDetail(
          purchaseId: purchaseId,
          purchaseNumber: purchaseNumber,
          purchaseDate: purchaseDate,
          outletName: outletName,
          userName: userName,
          purchaseStatus: purchaseStatus,
          supplierName: supplierName,
          supplierPhone: supplierPhone,
          note: note,
          items: [],
          totalPurchase: totalPurchase,
          discount: discount,
          tax: tax,
          paymentStatus: paymentStatus,
          totalAmount: totalAmount,
          payAmount: payAmount,
          changeAmount: changeAmount,
          underPaymentAmount: underPaymentAmount,
          debtAmount: debtAmount,
          paymentProofPath: paymentProofPath,
        );
      });

      final String name = row.read(purchaseItems.itemNameSnapshot) ?? '';

      final String? variantName = row.read(purchaseItems.itemVariantNameSnapshot);


      final double purchasePrice =
          row.read(purchaseItems.purchasePriceSnaphot) ?? 0.0;

      final double quantity = row.read(purchaseItems.quantity) ?? 0.0;

      final double subtotal = row.read(purchaseItems.subtotal) ?? 0.0;

      groupedMap[purchaseId]!.items.add(
        PurchaseItem(
          name: name,
          variantName: variantName,
          purchasePrice: purchasePrice,
          quantity: quantity,
          subtotal: subtotal,
        ),
      );
    }

    return groupedMap.values.single;
  }

  Future<int> cancelPurchase(String purchaseId) async {
    return (await update(purchases)
          ..where((purchase) => purchase.localId.equals(purchaseId)))
        .write(
          PurchasesCompanion(
            purchaseStatus: Value(PurchaseStatus.cancelled.status),
            syncStatus: Value(SyncStatus.dirty.status),
            updatedAt: Value(DateTime.now()),
          ),
        );
  }
}
