using FruitBank.Common.Dtos;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Directory;
using Nop.Core.Domain.Tax;
using Nop.Core.Domain.Vendors;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
using Nop.Plugin.Misc.FruitBankPlugin.Factories.MgBase;
using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
using Nop.Plugin.Misc.FruitBankPlugin.Models.Products;
using Nop.Services.Catalog;
using Nop.Services.Common;
using Nop.Services.Configuration;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.Discounts;
using Nop.Services.Helpers;
using Nop.Services.Localization;
using Nop.Services.Media;
using Nop.Services.Orders;
using Nop.Services.Seo;
using Nop.Services.Shipping;
using Nop.Services.Stores;
using Nop.Web.Areas.Admin.Factories;
using Nop.Web.Areas.Admin.Models.Catalog;
using Nop.Web.Framework.Factories;

namespace Nop.Plugin.Misc.FruitBankPlugin.Factories;

public class CustomProductModelFactory : MgProductModelFactory<ProductListModelExtended, ProductModelExtended>
{
    private readonly FruitBankDbContext _ctx;

    public CustomProductModelFactory(FruitBankDbContext ctx,CatalogSettings catalogSettings, CurrencySettings currencySettings, IAddressService addressService, IBaseAdminModelFactory baseAdminModelFactory, ICategoryService categoryService, ICurrencyService currencyService, ICustomerService customerService, IDateTimeHelper dateTimeHelper, IDiscountService discountService, IDiscountSupportedModelFactory discountSupportedModelFactory, ILocalizationService localizationService, ILocalizedModelFactory localizedModelFactory, IManufacturerService manufacturerService, IMeasureService measureService, IOrderService orderService, IPictureService pictureService, IPriceFormatter priceFormatter, IProductAttributeFormatter productAttributeFormatter, IProductAttributeParser productAttributeParser, IProductAttributeService productAttributeService, IProductService productService, IProductTagService productTagService, IProductTemplateService productTemplateService, ISettingModelFactory settingModelFactory, ISettingService settingService, IShipmentService shipmentService, IShippingService shippingService, IShoppingCartService shoppingCartService, ISpecificationAttributeService specificationAttributeService, IStoreMappingSupportedModelFactory storeMappingSupportedModelFactory, IStoreContext storeContext, IStoreService storeService, IUrlRecordService urlRecordService, IVideoService videoService, IWorkContext workContext, MeasureSettings measureSettings, NopHttpClient nopHttpClient, TaxSettings taxSettings, VendorSettings vendorSettings, IGenericAttributeService genericAttributeService) : base(catalogSettings, currencySettings, addressService, baseAdminModelFactory, categoryService, currencyService, customerService, dateTimeHelper, discountService, discountSupportedModelFactory, localizationService, localizedModelFactory, manufacturerService, measureService, orderService, pictureService, priceFormatter, productAttributeFormatter, productAttributeParser, productAttributeService, productService, productTagService, productTemplateService, settingModelFactory, settingService, shipmentService, shippingService, shoppingCartService, specificationAttributeService, storeMappingSupportedModelFactory, storeContext, storeService, urlRecordService, videoService, workContext, measureSettings, nopHttpClient, taxSettings, vendorSettings, genericAttributeService)
    {
        _ctx = ctx;
    }

    public override async Task<ProductSearchModel> PrepareProductSearchModelAsync(ProductSearchModel searchModel)
    {
        var baseModel = await base.PrepareProductSearchModelAsync(searchModel);
        return baseModel;
    }

    public override async Task<ProductListModel> PrepareProductListModelAsync(ProductSearchModel searchModel)
        => await base.PrepareProductListModelAsync(searchModel);

    public async Task<ProductListModelExtended> PrepareProductListModelExtendedAsync(ProductSearchModel searchModel)
    {
        Dictionary<int, ProductDto> productDtosById = null;

        var productListModelExtended = await base.PrepareProductListModelExtendedAsync(searchModel, async (productListModel, productModelExtended) =>
        {
            productDtosById ??= await _ctx.ProductDtos.GetAllByIds(productListModel.Data.Select(x => x.Id)).ToDictionaryAsync(k => k.Id, v => v);
            var productDto = productDtosById[productModelExtended.Id];

            productModelExtended.Tare = productDto.Tare;
            productModelExtended.NetWeight = productDto.NetWeight;
            productModelExtended.IsMeasurable = productDto.IsMeasurable;
            productModelExtended.IncomingQuantity = productDto.IncomingQuantity;
            productModelExtended.AvailableQuantity = productDto.AvailableQuantity;

            productModelExtended.StockQuantityStr = productModelExtended.StockQuantity.ToString();

            productModelExtended.AverageWeight = productDto.AverageWeight;
        });
            
        return productListModelExtended;
    }
}