using AyCode.Core.Extensions;
using AyCode.Core.Helpers;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Directory;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Shipping;
using Nop.Core.Domain.Tax;
using Nop.Core.Domain.Vendors;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
using Nop.Plugin.Misc.FruitBankPlugin.Models.Products;
using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Services.Affiliates;
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.Payments;
using Nop.Services.Security;
using Nop.Services.Seo;
using Nop.Services.Shipping;
using Nop.Services.Stores;
using Nop.Services.Tax;
using Nop.Services.Vendors;
using Nop.Web.Areas.Admin.Factories;
using Nop.Web.Areas.Admin.Models.Catalog;
using Nop.Web.Areas.Admin.Models.Orders;
using Nop.Web.Framework.Factories;

namespace Nop.Plugin.Misc.FruitBankPlugin.Factories.MgBase;

public class MgProductModelFactory<TProductListModelExt, TProductModelExt> : ProductModelFactory
    where TProductListModelExt : ProductListModelExtended where TProductModelExt : ProductModelExtended
{
    protected IGenericAttributeService GenericAttributeService;

    #region Ctor

    public MgProductModelFactory(
        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 = genericAttributeService;
    }

    #endregion Cotr

    public override Task<ProductSearchModel> PrepareProductSearchModelAsync(ProductSearchModel searchModel)
        => base.PrepareProductSearchModelAsync(searchModel);

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

    public virtual async Task<TProductListModelExt> PrepareProductListModelExtendedAsync(ProductSearchModel searchModel, Func<ProductListModel, TProductModelExt, Task> dataItemCopiedCallback)
    {
        var productListModel = await PrepareProductListModelAsync(searchModel);
        var extendedRows = new List<TProductModelExt>(productListModel.RecordsFiltered);

        foreach (var productModel in productListModel.Data.ToList())
        {
            var productModelExtended = Activator.CreateInstance<TProductModelExt>();

            PropertyHelper.CopyPublicValueTypeProperties(productModel, productModelExtended);
            extendedRows.Add(productModelExtended);

            if (dataItemCopiedCallback == null) continue;
            await dataItemCopiedCallback.Invoke(productListModel, productModelExtended);
        }

        productListModel.Data = null;

        //var productListModelExtended = productListModel.ToJson().JsonTo<TProductListModelExt>();
        var productListModelExtended = productListModel.CloneTo<TProductListModelExt>();
        productListModelExtended.Data = extendedRows;

        return productListModelExtended;
    }
}