using AyCode.Utils.Extensions;
using Microsoft.EntityFrameworkCore;
using TIAM.Database.DbContexts.ServiceProviders;
using TIAM.Entities.Drivers;
using TIAM.Entities.Users;

namespace TIAM.Database.DbSets.Users;

public static class UserProductMappingDbSetExtensions
{
    public static IQueryable<UserProductMapping> UserProductMappingsWithRelations(this IUserProductMappingDbSet ctx, bool autoInclude = true)
        => autoInclude
            ? ctx.UserProductMappings.Include(x => x.User).Include(x => x.Product)
            : ctx.UserProductMappings;


    public static UserProductMapping? GetUserProductMappingById(this IUserProductMappingDbSet ctx, Guid userProductMappingId, bool autoInclude = true)
        => ctx.UserProductMappingsWithRelations(autoInclude).FirstOrDefault(x => x.Id == userProductMappingId);

    public static UserProductMapping? GetUserProductMapping(this IUserProductMappingDbSet ctx, Guid userId, Guid productId, bool autoInclude = true)
        => ctx.UserProductMappingsWithRelations(autoInclude).FirstOrDefault(x => x.UserId == userId && x.ProductId == productId);

    public static IQueryable<UserProductMapping> GetUserProductMappingsByUserId(this IUserProductMappingDbSet ctx, Guid userId, bool autoInclude = true)
        => ctx.UserProductMappingsWithRelations(autoInclude).Where(x => x.UserId == userId);

    public static IQueryable<UserProductMapping> GetUserProductMappingsByProductId(this IUserProductMappingDbSet ctx, Guid productId, bool autoInclude = true)
        => ctx.UserProductMappingsWithRelations(autoInclude).Where(x => x.ProductId == productId);


    public static bool AddUserProductMapping(this IUserProductMappingDbSet ctx, UserProductMapping userProductMapping)
    {
        if (userProductMapping.UserId.IsNullOrEmpty() || userProductMapping.ProductId.IsNullOrEmpty() || userProductMapping.Permissions < 0)
            return false;

        if (userProductMapping.Id.IsNullOrEmpty())
            userProductMapping.Id = Guid.NewGuid();

        return ctx.UserProductMappings.Add(userProductMapping).State == EntityState.Added;
    }

    public static UserProductMapping? AddUserProductMapping(this IUserProductMappingDbSet ctx, Guid userProductMappingId, Guid userId, Guid productId, int permissions = 1, UserProductJsonDetailModel? userProductToCars = null)
    {
        var userProductMapping = new UserProductMapping(userProductMappingId, userId, productId, permissions, userProductToCars);

        return ctx.AddUserProductMapping(userProductMapping) ? userProductMapping : null;
    }

    public static bool UpdateUserProductMapping(this IUserProductMappingDbSet ctx, UserProductMapping userProductMapping)
    {
        if (userProductMapping.Id.IsNullOrEmpty() || userProductMapping.UserId.IsNullOrEmpty() || userProductMapping.ProductId.IsNullOrEmpty() || userProductMapping.Permissions < 0)
            return false;

        return ctx.UserProductMappings.Update(userProductMapping).State == EntityState.Modified;
    }

    public static UserProductMapping? UpdateUserProductMapping(this IUserProductMappingDbSet ctx, Guid userProductMappingId, int permissions = 1, UserProductJsonDetailModel? userProductToCars = null)
    {
        if (userProductMappingId.IsNullOrEmpty() || permissions < 0)
            return null;

        var userProductMapping = ctx.GetUserProductMappingById(userProductMappingId, false);
        if (userProductMapping == null) return null;

        userProductMapping.Permissions = permissions;
        userProductMapping.JsonDetailModel = userProductToCars;

        return ctx.UpdateUserProductMapping(userProductMapping) ? userProductMapping : null;
    }

    public static bool RemoveUserProductMapping(this IUserProductMappingDbSet ctx, UserProductMapping? userProductMapping)
    {
        if (userProductMapping == null) return false;

        return ctx.UserProductMappings.Remove(userProductMapping).State == EntityState.Deleted;
    }

    public static bool RemoveUserProductMapping(this IUserProductMappingDbSet ctx, Guid userProductMappingId)
    {
        var userProductMapping = ctx.GetUserProductMappingById(userProductMappingId, false);

        return userProductMapping == null || ctx.RemoveUserProductMapping(userProductMapping);
    }

    public static bool RemoveUserProductMapping(this IUserProductMappingDbSet ctx, Guid userId, Guid productId)
    {
        var userProductMapping = ctx.GetUserProductMapping(userId, productId, false);

        return userProductMapping == null || ctx.RemoveUserProductMapping(userProductMapping);
    }
}