using AsbCloudDb.Model;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using MockQueryable.Moq;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace AsbCloudWebApi.Tests
{
    internal static class TestHelpter
    {
        public static IMemoryCache MemoryCache = new MemoryCache(new MemoryCacheOptions());

        public static AsbCloudDbContext MakeRealTestContext()
        {
            var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
                .UseNpgsql("Host=localhost;Database=tests;Username=postgres;Password=q;Persist Security Info=True;Include Error Detail=True")
                .Options;
            var context = new AsbCloudDbContext(options);
            context.Database.EnsureCreated();
            return context;
        }

        public static Mock<IAsbCloudDbContext> AddDbSetMock<T>(this Mock<IAsbCloudDbContext> contextMock, IEnumerable<T> dbSetData)
            where T : class
        {
            var mockDbSet = dbSetData
                .ToList()
                .AsQueryable()
                .BuildMockDbSet();

            contextMock.Setup(o => o.Set<T>())
                .Returns(mockDbSet.Object);

            var dbSetProperty = typeof(IAsbCloudDbContext)
                .GetProperties()
                .FirstOrDefault(p => p.PropertyType.IsPublic && p.PropertyType == typeof(DbSet<T>));

            if (dbSetProperty is not null)
            {
                // https://learn.microsoft.com/ru-ru/dotnet/api/system.linq.expressions.expression?view=net-7.0
                var objParameterExpr = Expression.Parameter(typeof(IAsbCloudDbContext), "instance");
                var propertyExpr = Expression.Property(objParameterExpr, dbSetProperty);
                var expression = Expression.Lambda<Func<IAsbCloudDbContext, DbSet<T>>>(propertyExpr, objParameterExpr);
                contextMock.SetupGet(expression).Returns(mockDbSet.Object);
            }

            return contextMock;
        }
    }
}