using Microsoft.AspNetCore.Mvc.Rendering;
using Nop.Core;
using Nop.Core.Domain.Stores;
using Nop.Services.Stores;
using Nop.Web.Framework.Models;

namespace Nop.Web.Framework.Factories;

/// <summary>
/// Represents the base store mapping supported model factory implementation
/// </summary>
public partial class StoreMappingSupportedModelFactory : IStoreMappingSupportedModelFactory
{
    #region Fields

    protected readonly IStoreMappingService _storeMappingService;
    protected readonly IStoreService _storeService;

    #endregion

    #region Ctor

    public StoreMappingSupportedModelFactory(IStoreMappingService storeMappingService,
        IStoreService storeService)
    {
        _storeMappingService = storeMappingService;
        _storeService = storeService;
    }

    #endregion

    #region Methods

    /// <summary>
    /// Prepare selected and all available stores for the passed model
    /// </summary>
    /// <typeparam name="TModel">Store mapping supported model type</typeparam>
    /// <param name="model">Model</param>
    /// <returns>A task that represents the asynchronous operation</returns>
    public virtual async Task PrepareModelStoresAsync<TModel>(TModel model) where TModel : IStoreMappingSupportedModel
    {
        ArgumentNullException.ThrowIfNull(model);

        //prepare available stores
        var availableStores = await _storeService.GetAllStoresAsync();
        model.AvailableStores = availableStores.Select(store => new SelectListItem
        {
            Text = store.Name,
            Value = store.Id.ToString(),
            Selected = model.SelectedStoreIds.Contains(store.Id)
        }).ToList();
    }

    /// <summary>
    /// Prepare selected and all available stores for the passed model by store mappings
    /// </summary>
    /// <typeparam name="TModel">Store mapping supported model type</typeparam>
    /// <typeparam name="TEntity">Store mapping supported entity type</typeparam>
    /// <param name="model">Model</param>
    /// <param name="entity">Entity</param>
    /// <param name="ignoreStoreMappings">Whether to ignore existing store mappings</param>
    /// <returns>A task that represents the asynchronous operation</returns>
    public virtual async Task PrepareModelStoresAsync<TModel, TEntity>(TModel model, TEntity entity, bool ignoreStoreMappings)
        where TModel : IStoreMappingSupportedModel where TEntity : BaseEntity, IStoreMappingSupported
    {
        ArgumentNullException.ThrowIfNull(model);

        //prepare stores with granted access
        if (!ignoreStoreMappings && entity != null)
            model.SelectedStoreIds = (await _storeMappingService.GetStoresIdsWithAccessAsync(entity)).ToList();

        await PrepareModelStoresAsync(model);
    }

    #endregion
}