using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AyCode.Models.Enums;
using Microsoft.EntityFrameworkCore;
using TIAM.Entities.Permissions;
using TIAM.Entities.Products;
using TIAM.Entities.ServiceProviders;
using TIAM.Entities.Users;
using TIAM.Database.DbContexts.ServiceProviders;
using TIAM.Database.DbSets.Permissions;
using TIAM.Database.DbSets.Users;
using AyCode.Database.DataLayers;
using AyCode.Database.DbSets.Users;
using TIAM.Database.DbSets.Products;
using TIAM.Entities.TransferDestinations;
using TIAM.Models.Dtos.Users;
using Newtonsoft.Json;


namespace TIAM.Database.DataLayers.ServiceProviders
{
    //public class ServiceProviderDal : DalBase<ServiceProviderDbContext>
    //{

    //    public ServiceProviderDal() : base()
    //    {
    //    }

    //    public ServiceProviderDal(ServiceProviderDbContext _object)
    //    {
    //    }

    ////    #region ServiceProviders

    ////    //14. (IserviceProviderDataService) Update service provider
    ////    public Task<bool> UpdateServiceProviderAsync(TiamServiceProvider serviceProvider)
    ////    {
    ////        var dbServiceProvider = Context.ServiceProviders.FirstOrDefault(u => u.Id == serviceProvider.Id);
    ////        if (dbServiceProvider != null)
    ////        {
    ////            dbServiceProvider = serviceProvider;
    ////            Context.ServiceProviders.Update(dbServiceProvider);
    ////            return Context.SaveChangesAsync().ContinueWith(x => x.Result > 0);
    ////        }
    ////        else
    ////        {
    ////            throw new Exception("ServiceProvider not found");
    ////        }
    ////    }

    ////    //13. (IserviceProviderDataService) delete service provider
    ////    public Task<bool> DeleteServiceProviderAsync(Guid id)
    ////    {
    ////        using (var transaction = Context.Database.BeginTransaction())
    ////        {
    ////            var dbServiceProvider = Context.ServiceProviders.FirstOrDefault(u => u.Id == id);
    ////            if (dbServiceProvider != null)
    ////            {
    ////                //get products for this provider
    ////                var products = Context.Products.Where(x => x.ServiceProviderId == id).ToList();

    ////                /*foreach (var productItem in products)
    ////                {
    ////                    //delete products
    ////                    var permissionContextMappings = Context.PermissionContextMappings.Where(x => x.ContextId == productItem.Id).ToList();
    ////                    //iterate through every row
    ////                    foreach (var item in permissionContextMappings)
    ////                    {

    ////                        if (item.SubjectType == (int)PermissionContextMappingSubjectType.Group)
    ////                        {
    ////                            //get users in the permissiongroup
    ////                            var permissionGroupUserMapping = Context.PermissionGroupUserMappings.Where(x => x.PermissionContextMappingId == item.Id).ToList();
    ////                            //remove every row (users) from permissiongroup 
    ////                            foreach (var user in permissionGroupUserMapping)
    ////                            {
    ////                                Context.PermissionGroupUserMappings.Remove(user);
    ////                            }
    ////                        }
    ////                    }                        
    ////                    //remove permissioncontextmappings
    ////                    Context.PermissionContextMappings.RemoveRange(permissionContextMappings);
    ////                }*/
    ////                Context.Products.RemoveRange(products);
    ////                Context.ServiceProviders.Remove(dbServiceProvider);
    ////                return Context.SaveChangesAsync().ContinueWith(x => x.Result > 0);
    ////            }
    ////            else
    ////            {
    ////                return Task.FromResult(false);
    ////            }
    ////        }
    ////    }

    ////    //17. (IServiceProviderDataService) get service provider by ownerId
    ////    public Task<List<TiamServiceProvider>> GetServiceProvidersByOwnerIdAsync()
    ////    {
    ////        throw new NotImplementedException();

    ////    }

    ////    #endregion

    ////    #region PermissionTypes


    ////    //10. (IPermissionService) create permission type
    ////    public Task<bool> CreatePermissionsTypeAsync(PermissionsType permissionsType)
    ////    {
    ////        bool result = false;

    ////        using (var transaction = Context.Database.BeginTransaction())
    ////        {
    ////            var existingPermission = Context.PermissionsTypes
    ////                .FirstOrDefault(x => x.PermissionName == permissionsType.PermissionName)?.PermissionName;

    ////            if (existingPermission == null)
    ////            {
    ////                //get all the permissiontypes for this context
    ////                var permissionTypes = new List<PermissionsType>();
    ////                var nextBitValue = 0.0;
    ////                permissionTypes = Context.PermissionsTypes
    ////                    .Where(x => x.ContextId == permissionsType.ContextId)
    ////                    .ToList();

    ////                //get the max value of the permissiontypes
    ////                if (permissionTypes != null)
    ////                {
    ////                    //next bit value is the power of two of the count of the permissiontypes
    ////                    nextBitValue = Math.Pow(2, permissionTypes.Count);
    ////                }
    ////                else
    ////                {
    ////                    nextBitValue = Math.Pow(2, 0);
    ////                }
    ////                permissionsType.PermissionBit = (int)nextBitValue;
    ////                Context.PermissionsTypes.Add(permissionsType);
    ////                Context.SaveChanges();
    ////                transaction.Commit();
    ////                result = true;
    ////            }
    ////            else
    ////            {
    ////                result = false;
    ////            }

    ////        }
    ////        return Task.FromResult(result);

    ////    }

    ////    //11. (IPermissionService) get permission types for context
    ////    public Task<List<PermissionsType>>? GetPermissionTypesByContextIdAsync(Guid contextId)
    ////    {
    ////        return Context.PermissionsTypes.Where(x => x.ContextId == contextId).ToListAsync();
    ////    }

    ////    public Task<int> GetPermissionFromPermissionType(PermissionsType pType)
    ////    {
    ////        if (Context.PermissionsTypes.FirstOrDefault(x => x.Id == pType.Id) != null)
    ////        {
    ////            return Task.FromResult(pType.PermissionBit);
    ////        }
    ////        else
    ////        {
    ////            return Task.FromResult(0);
    ////        }
    ////    }

    ////    #endregion

    ////    #region PermissionMappings

    ////    public Task<List<AssignedPermissionModel>> GetPermissionsOfUserProductMappingsAndGroupsAsyncByContextId(Guid contextId)
    ////    {
    ////        List<AssignedPermissionModel> result = new List<AssignedPermissionModel>();

    ////        var UserProductMappings = Context.UserProductMappings.Where(x => x.ProductId == contextId).ToListAsync();

    ////        if (UserProductMappings.Result != null)
    ////        {
    ////            foreach (var item in UserProductMappings.Result)
    ////            {
    ////                var mappingRow = Context.PermissionContextMappings.Where(x => x.SubjectId == item.Id).ToListAsync();
    ////                if (mappingRow.Result == null)
    ////                {
    ////                    //user has no permission but is assigned... must be banned

    ////                }
    ////                else if (mappingRow.Result.Count > 1)
    ////                {
    ////                    //user has been assigned more than onece to same context

    ////                }
    ////                else
    ////                {
    ////                    foreach (var mapping in mappingRow.Result)
    ////                    {
    ////                        result.Add(new AssignedPermissionModel(item.ProductId, item.Id, mapping.SubjectType, item.UserId.ToString(), mapping.Permissions));
    ////                    }
    ////                }

    ////            }
    ////        }

    ////        var AssingedGroups = Context.PermissionGroups.Where(x => x.OwnerId == contextId).ToListAsync();

    ////        if (AssingedGroups.Result != null)
    ////        {
    ////            foreach (var group in AssingedGroups.Result)
    ////            {
    ////                var mappingRow = Context.PermissionContextMappings.Where(x => x.SubjectId == group.Id).ToListAsync();
    ////                if (mappingRow.Result == null)
    ////                {
    ////                    //group has no permission but is assigned...

    ////                }
    ////                else if (mappingRow.Result.Count > 1)
    ////                {
    ////                    //group has been assigned more than onece to same context

    ////                }
    ////                else
    ////                {
    ////                    foreach (var mapping in mappingRow.Result)
    ////                    {
    ////                        result.Add(new AssignedPermissionModel(group.OwnerId, group.Id, mapping.SubjectType, group.GroupName, mapping.Permissions));
    ////                    }
    ////                }

    ////            }
    ////        }
    ////        foreach (var row in result)
    ////        {
    ////            Console.WriteLine($"GetPermissionsOfUserProductMappingsAndGroupsAsyncByContextId: {row.ContextId}, {row.SubjectId}, {row.SubjectType}, {row.Name}, {row.PermissionsValue}");
    ////        }
    ////        return Task.FromResult(result);
    ////    }



    ////    //12. (IPermissionService) get permission groups for context
    ////    public Task<List<PermissionContextMapping>> GetPermissionsForContextByContextIdAsync(Guid contextId)
    ////    {
    ////        List<PermissionContextMapping> permissionContextMappings = new List<PermissionContextMapping>();
    ////        //get all Groups where the contextId is the same
    ////        var groups = Context.PermissionGroups.Where(x => x.OwnerId == contextId).Select(x => x.Id).ToHashSet();
    ////        permissionContextMappings = Context.PermissionContextMappings.Where(x => groups.Contains(x.SubjectId)).ToList();

    ////        //foreach (var item in groups.Result)
    ////        //{
    ////        //    //get permissioncontextmapping for the group if there is, so we know what permissions the group has
    ////        //    var pCm = Context.PermissionContextMappings.FirstOrDefault(x => x.SubjectId == item.Id);
    ////        //    permissionContextMappings.Add(pCm);
    ////        //}
    ////        return Task.FromResult(permissionContextMappings);
    ////    }

    ////    //9. (IPermissionService) add user to permission group
    ////    public Task<bool> AddUserToPermissionGroupAsync(Guid permissionGroupId, Guid userId)
    ////    {
    ////        bool result = false;
    ////        using (var transaction = Context.Database.BeginTransaction())
    ////        {
    ////            //do we need to check if PermissionContextMappingId exists?
    ////            var permissionGroupUserMapping = new PermissionGroupUserMapping(userId, permissionGroupId);
    ////            Context.PermissionGroupUserMappings.Add(permissionGroupUserMapping);
    ////            Context.SaveChanges();
    ////            transaction.Commit();
    ////            result = true;
    ////        }
    ////        return Task.FromResult(result);
    ////    }

    ////    //8. (IPermissionService) create permission group
    ////    public Task<bool> CreatePermissionGroupAsync(PermissionGroup permissionGroup, TiamServiceProvider serviceProvider)
    ////    {
    ////        bool result = false;
    ////        using (var transaction = Context.Database.BeginTransaction())
    ////        {
    ////            var existingPermissionGroup = Context.PermissionGroups.FirstOrDefault(x => x.GroupName == permissionGroup.GroupName)?.GroupName;
    ////            if (existingPermissionGroup == null)
    ////            {
    ////                //create permission type 1 for the group
    ////                var permissionType = new PermissionsType(serviceProvider.Id, "View");
    ////                Context.CreatePermissionsType(permissionType);

    ////                //Create PermissionContextMapping for the group

    ////                //create Id for the group
    ////                Guid Id = Guid.NewGuid();
    ////                permissionGroup.Id = Id;
    ////                var permissionContextMapping = new PermissionContextMapping(serviceProvider.Id, Id, PermissionContextMappingSubjectType.Group, 1, true);
    ////                Context.CreatePermissionContextMapping(permissionContextMapping);
    ////                Context.CreatePermissionGroup(permissionGroup);
    ////                Context.SaveChanges();
    ////                transaction.Commit();
    ////                result = true;
    ////            }
    ////            else
    ////            {
    ////                //group with same name already exists
    ////                result = false;
    ////            }
    ////        }
    ////        return Task.FromResult(result);
    ////    }

    ////    public List<UserProductMapping> GetUserProductMappingsInPermissionGroupByGroupId(Guid groupId)
    ////    {
    ////        return Context.GetUserProductMappingsByPermissionGroupId(groupId).ToList();
    ////        //List<UserProductMapping> userProductMappings = new List<UserProductMapping>();

    ////        ////let's get the permissioncontextmapping for the group
    ////        //var pCm = Context.PermissionContextMappings.FirstOrDefault(x => x.SubjectId == groupId);
    ////        //Guid pCmId = pCm.Id;

    ////        ////let's get the permissiongroupusermappings for the permissioncontextmapping
    ////        //var pGum = Context.PermissionGroupUserMappings.Where(x => x.PermissionContextMappingId == pCmId).ToList();
    ////        //if (pGum.Count > 0)
    ////        //{
    ////        //    foreach (var group in pGum)
    ////        //    {
    ////        //        userProductMappings.Add(Context.UserProductMappings.FirstOrDefault(x => x.Id == group.UserProductMappingId)); 
    ////        //    }

    ////        //}

    ////        //return Task.FromResult(userProductMappings);
    ////    }

    ////    #endregion

    ////    #region Products

    ////    //* 20. (IServiceProviderDataService) Update product
    ////    public Product UpdateProduct(Product product)
    ////    {

    ////        var prod = Context.UpdateProduct(product);
    ////        Console.WriteLine($"Saving product to db {product.Id}, {product.Name}, {product.ServiceProviderId}");
    ////        Context.SaveChanges();
    ////        return prod;
    ////    }

    ////    //* 21. (IServiceProviderDataService) delete product
    ////    public Task<bool> DeleteProductByIdAsync(Guid productId)
    ////    {
    ////        return TransactionAsync(ctx =>
    ////        {
    ////            ctx.DeleteProductById(productId);

    ////            return true;
    ////        });
    ////    }

    ////    //4. (IPermissionService) AssignPermissionToUserForContextAsync
    ////    public Task<bool> AssignPermissionToUserForContextAsync(UserProductMapping userProductMapping, PermissionsType permission)
    ////    {
    ////        var _assIgnedUser = Context.UserProductMappings.FirstOrDefault(x => x.Id == userProductMapping.Id);

    ////        if (_assIgnedUser != null)
    ////        {
    ////            //user exists
    ////            var _permissionInt = GetPermissionFromPermissionType(permission);

    ////            var permissionContextMapping = Context.PermissionContextMappings.FirstOrDefault(x => x.SubjectId == userProductMapping.Id);
    ////            var currentPermissions = permissionContextMapping.Permissions;
    ////            var newPermissions = currentPermissions + _permissionInt.Result;
    ////            permissionContextMapping.Permissions = newPermissions;
    ////            return Context.SaveChangesAsync().ContinueWith(x => x.Result > 0);
    ////        }
    ////        else
    ////        {
    ////            //user does not exist, let's create it
    ////            return Task.FromResult(false);
    ////        }
    ////    }

    ////    #endregion


    ////    #region UserProductMappings

    ////    //23. (IServiceProviderDataService) Get Assigned Users By ProductId
    ////    public Task<List<UserProductMapping>> GetUserProductMappingsByProductIdAsync(Guid productId)
    ////    {
    ////        return Context.UserProductMappings.Where(x => x.ProductId == productId).ToListAsync();
    ////    }


    ////    //24 . (IServiceProviderDataService) Remove Assigned Users By Product Id
    ////    public Task RemoveUserProductMappingsByContextId(Guid productId)
    ////    {
    ////        using (var transaction = Context.Database.BeginTransaction())
    ////        {
    ////            var userProductMappings = Context.UserProductMappings.Where(x => x.ProductId == productId).ToList();
    ////            //remove userProductMappings

    ////            return Context.SaveChangesAsync().ContinueWith(x => x.Result > 0);

    ////        }
    ////    }

    ////    //25. (IServiceProviderDataService) Remove Assigned from product by userProductMappingId
    ////    public Task<bool> RemoveUserProductMappingAsync(UserProductMapping userProductMapping, bool removeFromGroups)
    ////    {
    ////        return TransactionAsync(ctx =>
    ////        {
    ////            var result = false;
    ////            var userProductMappingToRemove = ctx.UserProductMappings.FirstOrDefault(x => x.Id == userProductMapping.Id);

    ////            //remove userProductMappings
    ////            if (userProductMappingToRemove == null) return false;


    ////            if (removeFromGroups)
    ////            {
    ////                //remove permissiongroupusermappings
    ////                ctx.RemoveAssingedUserFromPermissionGroups(userProductMappingToRemove.Id);
    ////            }

    ////            ctx.UserProductMappings.Remove(userProductMappingToRemove);


    ////            return result;
    ////        });
    ////    }


    ////    #endregion

    ////}
}
