import 'package:drift/drift.dart';
import 'package:niogu_app/core/database/app_database.dart'
    hide Product, StockCard;
import 'package:niogu_app/features/goods/domain/entities/stock_card.dart';
import 'package:niogu_app/features/goods/domain/entities/outlet_inventory.dart';
import 'package:niogu_app/features/goods/products/domain/entities/product.dart';
import 'package:niogu_app/features/goods/products/domain/repositories/i_product_repository.dart';

class ProductRepositoryImpl implements IProductRepository {
  final AppDatabase _appDatabase;

  ProductRepositoryImpl(this._appDatabase);

  @override
  Stream<List<Product>> watchProducts(String outletId) {
    return _appDatabase.productDao.watchAllProducts();
  }

  @override
  Future<ProductDetail> fetchProductById(String id, bool isEditing) async {
    return await _appDatabase.productDao.getProductById(id, isEditing);
  }

  @override
  Future<List<ProductWithVariant>> fetchNewVariants(String id) async {
    return await _appDatabase.productDao.getNewVariants(id);
  }

  @override
  Future<DeleteProductSnapshot> fetchDeleteProductSnapshotById(
    String id,
  ) async {
    return await _appDatabase.productDao.getDeleteProductSnapshotById(id);
  }

  @override
  Future<void> saveProduct({
    required UpsertProduct product,
    required List<UpsertProductVariant> productVariants,
    List<DeleteProductVariant>? deleteVariants,
    required List<UpsertOutletInventory> outletInventories,
    required List<StockCard> stockCards,
    bool modeChange = false,
    String? modeBeforeChange,
    String? modeAfterChange,
  }) async {
    final productCompanion = ProductsCompanion(
      localId: Value(product.localId),
      categoryId: Value(product.categoryId),
      unitId: Value(product.unitId),
      name: Value(product.name),
      localImagePath: Value(product.localImagePath),
      hasVariant: Value(product.hasVariant),
      syncStatus: Value(product.syncStatus.status),
    );

    final List<ProductVariantsCompanion> productVariantCompanions = [];

    for (final productVariant in productVariants) {
      productVariantCompanions.add(
        ProductVariantsCompanion(
          localId: Value(productVariant.localId),
          productId: Value(productVariant.productId),
          name: Value(productVariant.name),
          localImagePath: Value(productVariant.localImagePath),
          isProductVariant: Value(productVariant.isProductVariant),
          syncStatus: Value(productVariant.syncStatus.status),
        ),
      );
    }

    final List<OutletInventoriesCompanion> outletInventoryCompanions = [];

    for (final 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 (final 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(
      product: productCompanion,
      variants: productVariantCompanions,
      deleteVariants: deleteVariants,
      inventories: outletInventoryCompanions,
      cards: cards,
      modeChange: modeChange,
      modeBeforeChange: modeBeforeChange,
      modeAfterChange: modeAfterChange,
    );
  }

  @override
  Future<void> deleteProduct(
    String id, {
    String? outletId,
    required bool canDeleteAll,
  }) async {
    await _appDatabase.outletInventoryDao.deleteOutletInventory(
      productId: id,
      outletId: outletId,
      canDeleteAll: canDeleteAll,
    );
  }

  @override
  Future<bool> checkAlreadyProductByOutlet(String id) async {
    return await _appDatabase.productDao.checkAlreadyProductByOutlet(id);
  }

  @override
  Stream<List<ProductChoice>> watchProductChoices() {
    return _appDatabase.productDao.watchAllProductChoices();
  }
}
