using Grand.Data.Tests.MongoDb;
using Grand.Domain.Customers;
using Grand.Domain.Data;
using Grand.Infrastructure.Caching;
using Grand.Infrastructure.Tests.Caching;
using MediatR;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace Grand.Business.Marketing.Services.Customers.Tests
{
    [TestClass()]
    public class CustomerProductServiceTests
    {
        private CustomerProductService _customerProductService;
        private IRepository<CustomerProductPrice> _repositoryCustomerProductPrice;
        private IRepository<CustomerProduct> _repositoryCustomerProduct;
        private MemoryCacheBase _cacheBase;
        private Mock<IMediator> _mediatorMock;

        [TestInitialize()]
        public void Init()
        {
            _repositoryCustomerProductPrice = new MongoDBRepositoryTest<CustomerProductPrice>();
            _repositoryCustomerProduct = new MongoDBRepositoryTest<CustomerProduct>();
            _mediatorMock = new Mock<IMediator>();

            _cacheBase = new MemoryCacheBase(MemoryCacheTest.Get(), _mediatorMock.Object);
            _customerProductService = new CustomerProductService(_repositoryCustomerProductPrice, _repositoryCustomerProduct, _cacheBase, _mediatorMock.Object);
        }

        [TestMethod()]
        public async Task GetCustomerProductPriceByIdTest()
        {
            //Arrange
            var customerProductPrice = new CustomerProductPrice() { Price = 10 };

            await _repositoryCustomerProductPrice.InsertAsync(customerProductPrice);

            //Act
            var result = await _customerProductService.GetCustomerProductPriceById(customerProductPrice.Id);

            //Assert
            Assert.IsNotNull(result);
            Assert.AreEqual(10, result.Price);
        }

        [TestMethod()]
        public async Task GetPriceByCustomerProductTest()
        {
            //Arrange
            var customerProductPrice = new CustomerProductPrice() { Price = 10, CustomerId = "1", ProductId = "1" };

            await _repositoryCustomerProductPrice.InsertAsync(customerProductPrice);

            //Act
            var result = await _customerProductService.GetPriceByCustomerProduct("1", "1");

            //Assert
            Assert.IsNotNull(result);
            Assert.AreEqual(10, result);
        }

        [TestMethod()]
        public async Task InsertCustomerProductPriceTest()
        {
            //Act
            var customerProductPrice = new CustomerProductPrice() { Price = 10, CustomerId = "1", ProductId = "1" };
            await _customerProductService.InsertCustomerProductPrice(customerProductPrice);

            //Assert
            Assert.IsTrue(_repositoryCustomerProductPrice.Table.Any());
        }

        [TestMethod()]
        public async Task UpdateCustomerProductPriceTest()
        {
            //Arrange
            var customerProductPrice = new CustomerProductPrice() { Price = 10, CustomerId = "1", ProductId = "1" };

            await _repositoryCustomerProductPrice.InsertAsync(customerProductPrice);

            //Act
            customerProductPrice.Price = 20;
            await _customerProductService.UpdateCustomerProductPrice(customerProductPrice);
            var result = await _customerProductService.GetCustomerProductPriceById(customerProductPrice.Id);

            //Assert
            Assert.IsNotNull(result);
            Assert.AreEqual(20, result.Price);
        }

        [TestMethod()]
        public async Task DeleteCustomerProductPriceTest()
        {
            //Arrange
            var customerProductPrice = new CustomerProductPrice() { Price = 10, CustomerId = "1", ProductId = "1" };

            await _repositoryCustomerProductPrice.InsertAsync(customerProductPrice);

            //Act
            await _customerProductService.DeleteCustomerProductPrice(customerProductPrice);
            var result = await _customerProductService.GetCustomerProductPriceById(customerProductPrice.Id);

            //Assert
            Assert.IsNull(result);
        }

        [TestMethod()]
        public async Task GetProductsPriceByCustomerTest()
        {
            //Arrange
            await _repositoryCustomerProductPrice.InsertAsync(new CustomerProductPrice() { CustomerId = "1" });
            await _repositoryCustomerProductPrice.InsertAsync(new CustomerProductPrice() { CustomerId = "1" });
            await _repositoryCustomerProductPrice.InsertAsync(new CustomerProductPrice() { CustomerId = "1" });

            //Act
            var result = await _customerProductService.GetProductsPriceByCustomer("1");

            //Assert
            Assert.AreEqual(3, result.Count);
        }

        [TestMethod()]
        public async Task GetCustomerProductTest()
        {
            //Arrange
            var customerProduct = new CustomerProduct() { CustomerId = "1" };

            await _repositoryCustomerProduct.InsertAsync(customerProduct);

            //Act
            var result = await _customerProductService.GetCustomerProduct(customerProduct.Id);

            //Assert
            Assert.IsNotNull(result);
            Assert.AreEqual("1", result.CustomerId);
        }

        [TestMethod()]
        public async Task GetCustomerProductTest_Customer_Product()
        {
            //Arrange
            var customerProduct = new CustomerProduct() { CustomerId = "1", ProductId = "1" };

            await _repositoryCustomerProduct.InsertAsync(customerProduct);

            //Act
            var result = await _customerProductService.GetCustomerProduct("1", "1");

            //Assert
            Assert.IsNotNull(result);
            Assert.AreEqual("1", result.CustomerId);
        }

        [TestMethod()]
        public async Task InsertCustomerProductTest()
        {
            //Act
            var customerProduct = new CustomerProduct() { CustomerId = "1", ProductId = "1" };
            await _customerProductService.InsertCustomerProduct(customerProduct);

            //Assert
            Assert.IsTrue(_repositoryCustomerProduct.Table.Any());
        }

        [TestMethod()]
        public async Task UpdateCustomerProductTest()
        {
            //Arrange
            var customerProduct = new CustomerProduct() { CustomerId = "1", ProductId = "1", DisplayOrder = 1 };

            await _repositoryCustomerProduct.InsertAsync(customerProduct);

            //Act
            customerProduct.DisplayOrder = 20;
            await _customerProductService.UpdateCustomerProduct(customerProduct);
            var result = await _customerProductService.GetCustomerProduct(customerProduct.Id);

            //Assert
            Assert.IsNotNull(result);
            Assert.AreEqual(20, result.DisplayOrder);
        }

        [TestMethod()]
        public async Task DeleteCustomerProductTest()
        {
            //Arrange
            var customerProduct = new CustomerProduct() { CustomerId = "1", ProductId = "1" };

            await _repositoryCustomerProduct.InsertAsync(customerProduct);

            //Act
            await _customerProductService.DeleteCustomerProduct(customerProduct);
            var result = await _customerProductService.GetCustomerProduct(customerProduct.Id);

            //Assert
            Assert.IsNull(result);
        }

        [TestMethod()]
        public async Task GetProductsByCustomerTest()
        {
            //Arrange
            await _repositoryCustomerProduct.InsertAsync(new CustomerProduct() { CustomerId = "1" });
            await _repositoryCustomerProduct.InsertAsync(new CustomerProduct() { CustomerId = "1" });
            await _repositoryCustomerProduct.InsertAsync(new CustomerProduct() { CustomerId = "1" });

            //Act
            var result = await _customerProductService.GetProductsByCustomer("1");

            //Assert
            Assert.AreEqual(3, result.Count);
        }
    }
}