import 'package:drift/drift.dart';
import 'package:niogu_app/core/database/app_database.dart'
    hide RawMaterial, StockCard;
import 'package:niogu_app/features/goods/domain/entities/stock_card.dart';
import 'package:niogu_app/features/goods/raw_materials/domain/entities/raw_material.dart';
import 'package:niogu_app/features/goods/raw_materials/domain/repositories/i_raw_material_repository.dart';
import 'package:niogu_app/features/goods/domain/entities/outlet_inventory.dart';

class RawMaterialRepositoryImpl implements IRawMaterialRepository {
  final AppDatabase _appDatabase;

  RawMaterialRepositoryImpl(this._appDatabase);

  @override
  Stream<List<RawMaterial>> watchMaterials(String currentOutlet) {
    return _appDatabase.rawMaterialDao.watchAllMaterials();
  }

  @override
  Future<RawMaterialDetail> fetchRawMaterialById(
    String id,
    bool isEditing,
  ) async {
    return await _appDatabase.rawMaterialDao.getRawMaterialById(id, isEditing);
  }

  @override
  Stream<List<ProductUsageMaterial>> watchProductUsageMaterials(
    String currentOutlet,
    bool isEditing,
  ) {
    return _appDatabase.rawMaterialDao.watchAllProductUsageMaterials(isEditing);
  }

  @override
  Future<DeleteRawMaterialSnapshot> fetchDeleteRawMaterialSnapshotById(
    String id,
  ) async {
    return await _appDatabase.rawMaterialDao.getRawMaterialSnapshotById(id);
  }

  @override
  Future<bool> checkAlreadyRawMaterialByOutlet(String id) async {
    return await _appDatabase.rawMaterialDao.checkAlreadyRawMaterialByOutlet(
      id,
    );
  }

  @override
  Stream<List<RawMaterialChoice>> watchRawMaterialChoices() {
    return _appDatabase.rawMaterialDao.watchAllRawMaterialChoices();
  }

  @override
  Future<void> saveRawMaterial({
    required UpsertRawMaterial rawMaterial,
    required List<UpsertReceiptItem> receiptItems,
    List<DeleteProductUsageMaterial>? deleteItems,
    required List<UpsertOutletInventory> outletInventories,
    required List<StockCard> stockCards,
  }) async {
    final rawMaterialCompanions = RawMaterialsCompanion(
      localId: Value(rawMaterial.localId),
      unitId: Value(rawMaterial.unitId),
      name: Value(rawMaterial.name),
    );

    final List<ReceiptItemsCompanion> receiptItemCompanions = [];

    for (var item in receiptItems) {
      receiptItemCompanions.add(
        ReceiptItemsCompanion(
          localId: Value(item.localId),
          productVariantId: Value(item.productUsageId),
          rawMaterialId: Value(item.rawMaterialId),
          quantity: Value(item.quantity),
        ),
      );
    }

    final List<OutletInventoriesCompanion> outletInventoryCompanions = [];

    for (var outletInventory in outletInventories) {
      outletInventoryCompanions.add(
        OutletInventoriesCompanion(
          localId: Value(outletInventory.localId),
          outletId: Value(outletInventory.outletId),
          itemType: Value(outletInventory.itemType.type),
          itemId: Value(outletInventory.itemId),
          stockType: Value(outletInventory.stockType.type),
          stock: Value(outletInventory.stock),
          sellingPrice: Value(outletInventory.sellingPrice),
          costPrice: Value(outletInventory.costPrice),
          purchasePrice: Value(outletInventory.purchasePrice),
          syncStatus: Value(outletInventory.syncStatus.status),
        ),
      );
    }

    final List<StockCardsCompanion> cards = [];

    if (stockCards.isNotEmpty) {
      for (var stockCard in stockCards) {
        cards.add(
          StockCardsCompanion(
            localId: Value(stockCard.localId),
            outletInventoryId: Value(stockCard.outletInventoryId),
            userId: Value(stockCard.userId),
            type: Value(stockCard.stockCardType.type),
            qtyChange: Value(stockCard.qtyChange),
            currentStock: Value(stockCard.currentStock),
            costPrice: Value(stockCard.costPrice),
            stockType: Value(stockCard.stockType.type),
            modeChange: Value(stockCard.modeChange),
            modeBeforeChange: Value(stockCard.modeBeforeChange),
            modeAfterChange: Value(stockCard.modeAfterChange),
            syncStatus: Value(stockCard.syncStatus.status),
          ),
        );
      }
    }

    await _appDatabase.outletInventoryDao.saveOutletInventory(
      rawMaterial: rawMaterialCompanions,
      items: receiptItemCompanions,
      deleteItems: deleteItems,
      inventories: outletInventoryCompanions,
      cards: cards,
    );
  }

  @override
  Future<void> deleteRawMaterial(
    String id, {
    String? outletId,
    bool canDeleteAll = false,
  }) async {
    await _appDatabase.outletInventoryDao.deleteOutletInventory(
      rawMaterialId: id,
      outletId: outletId,
      canDeleteAll: canDeleteAll,
    );
  }
}
