import 'package:drift/drift.dart';
import 'package:niogu_app/core/database/app_database.dart' hide Product;
import 'package:niogu_app/core/enums/customer_source.dart';
import 'package:niogu_app/core/enums/stock_card_type.dart';
import 'package:niogu_app/core/enums/stock_type.dart';
import 'package:niogu_app/core/system/system_setting.dart';
import 'package:niogu_app/features/goods/products/domain/entities/product.dart';
import 'package:niogu_app/features/goods/raw_materials/domain/entities/raw_material.dart';
import 'package:niogu_app/features/pos/domain/entities/pos.dart';
import 'package:niogu_app/features/pos/domain/repositories/i_pos_repository.dart';
import 'package:uuid/uuid.dart';

class PosRepositoryImpl implements IPosRepository {
  final AppDatabase _appDatabase;

  PosRepositoryImpl(this._appDatabase);

  @override
  Stream<List<DisplayProductPos>> watchDisplayProductPos(String outletId) {
    return _appDatabase.orderDao.watchAllDisplayProductPos();
  }

  @override
  Stream<List<AlreadyCustomer>> watchAlreadyCustomers(String outletId) {
    return _appDatabase.customerDao.watchAllAlreadyCustomers();
  }

  @override
  Future<bool> checkRawMaterialStockSufficient(
    String productVariantId,
    double productQuantity,
  ) async {
    return await _appDatabase.orderDao.checkRawMaterialStockSufficient(
      productVariantId,
      productQuantity,
    );
  }

  @override
  Future<List<UpdateStockRawMaterial>> getProductUseMaterials(
    String productVariantId,
    double productQuantity,
  ) async {
    return await _appDatabase.orderDao.getProductUseMaterials(
      productVariantId,
      productQuantity,
    );
  }

  @override
  Future<void> addSale(
    CustomerInformation? customerInfo,
    NewSale newSale,
    List<ItemSale> itemSales,
  ) async {
    final outletId = await SystemSetting.getCurrentOutletId();

    final outletName = await SystemSetting.getCurrentOutletName();

    final userId = await SystemSetting.getCurrentUserId();

    final userName = await SystemSetting.getCurrentUserName();

    CustomersCompanion? customer;

    // CustomerAddressesCompanion? customerAddress;

    if (customerInfo != null) {
      customer = CustomersCompanion(
        localId: Value(customerInfo.id),
        outletId: Value(outletId!),
        name: Value(customerInfo.name),
        phoneNumber: Value(customerInfo.phoneNumber),
        source: Value(CustomerSource.offline.source),
      );

      /**
      if (customerInfo.address != null) {
        customerAddress = CustomerAddressesCompanion(
          localId: Value(const Uuid().v7().toString()),
          customerId: Value(customerInfo.id),
          fullAddress: Value(customerInfo.address),
        );
      }
      */
    }

    final order = OrdersCompanion(
      localId: Value(newSale.localId),
      outletId: Value(outletId!),
      outletNameSnapshot: Value(outletName!),
      customerId: Value(newSale.customerId),
      customerNameSnapshot: Value(newSale.customerNameSnapshot),
      customerPhoneNumberSnapshot: Value(newSale.customerPhoneNumberSnapshot),
      userId: Value(userId!),
      adminNameSnapshot: Value(userName!),
      source: Value(newSale.orderSource.source),

      /**
       * dev
      source: Value(OrderSource.online.source),
      alreadyRead: Value(true),
      orderStatus: Value(OrderStatus.pending_confirmation.status),
      deliveryType: Value(DeliveryType.delivery.type),
      deliveryPrefrence: Value("Secepatnya"),
      */
      orderStatus: Value(newSale.orderStatus.status),
      totalOrder: Value(newSale.totalOrder),
      discount: Value(newSale.otherInformation.discount),
      tax: Value(newSale.otherInformation.tax),
      totalAmount: Value(newSale.totalAmount),
      amountPaid: Value(newSale.amountPaid),
      changeAmount: Value(newSale.changeAmount),
      notes: Value(newSale.otherInformation.note),
      paymentProofPath: Value(newSale.paymentProofPath),

      // paymentMethod: Value("COD"), // dev
      customerAddressSnapshot: Value(newSale.customerAddressSnapshot),

      /**
       * dev
      customerAddressSnapshot: Value({
        "full_address": AppTemp.ADDRESS.first.fullAddress,
        "latitude": AppTemp.ADDRESS.first.coordinate.latitude,
        "longitude": AppTemp.ADDRESS.first.coordinate.longitude,
      }),
      */
      syncStatus: Value(newSale.syncStatus.status),
    );

    final List<OrderItemsCompanion> orderItems = itemSales.map((item) {
      return OrderItemsCompanion(
        localId: Value(item.localId),
        orderId: Value(item.orderId),
        productVariantId: Value(item.productVariantId),
        quantity: Value(item.quantity),
        productImageSnapshot: Value(item.productImageSnapshot),
        productNameSnapshot: Value(item.productNameSnapshot),
        productVariantNameSnapshot: Value(item.productVariantNameSnapshot),
        sellingPriceSnapshot: Value(item.sellingPriceSnapshot),
        subtotal: Value(item.subtotal),
        syncStatus: Value(item.syncStatus.status),
      );
    }).toList();

    final List<UpdateTotalSold> totalSolds = itemSales.map((item) {
      return UpdateTotalSold(
        id: item.productVariantId,
        qtySold: item.quantity,
        currentSold: item.currentSold,
      );
    }).toList();

    final List<UpdateStockProduct> stockProducts = itemSales.map((item) {
      return UpdateStockProduct(
        outletInventoryId: item.outletInventoryId,
        productVariantId: item.productVariantId,
        stockType: item.stockType,
        stock: item.stock,
        quantity: item.quantity,
      );
    }).toList();

    final List<StockCardsCompanion> cardProducts = itemSales.map((item) {
      return StockCardsCompanion(
        localId: Value(Uuid().v7().toString()),
        outletInventoryId: Value(item.outletInventoryId),
        userId: Value(userId),
        type: Value(StockCardType.sale.type),
        qtyChange: Value(item.quantity),
        currentStock: Value(
          item.stockType == StockType.fixed
              ? (item.stock - item.quantity)
              : 0.0,
        ),
        stockType: Value(item.stockType.type),
        costPrice: Value(item.costPrice),
        referenceId: order.localId,
        syncStatus: Value(item.syncStatus.status),
      );
    }).toList();

    await _appDatabase.orderDao.addSale(
      customer: customer,
      // customerAddress: customerAddress,
      order: order,
      orderItem: orderItems,
      totalSolds: totalSolds,
      stockProducts: stockProducts,
      cardProducts: cardProducts,
    );
  }
}
