using Hotline.Caching.Interfaces;
using Hotline.SeedData;
using Hotline.Settings;
using Hotline.Share.Enums.Settings;
using Hotline.Users;
using Microsoft.Extensions.DependencyInjection;
using XF.Domain.Authentications;
using XF.Domain.Cache;
using XF.Domain.Dependency;
using XF.Domain.Entities;
using XF.Domain.Exceptions;
using XF.Domain.Extensions;

namespace Hotline.Repository.SqlSugar.DataPermissions;

public class DataPermissionManager : IDataPermissionManager, IScopeDependency
{
    private readonly IServiceScopeFactory _serviceScopeFactory;
    private readonly ISessionContext _sessionContext;

    public DataPermissionManager(
        IServiceScopeFactory serviceScopeFactory,
        ISessionContext sessionContext
    )
    {
        _serviceScopeFactory = serviceScopeFactory;
        _sessionContext = sessionContext;
    }

    public ETableAccessLevel GetQueryFilter<TEntity>(ISessionContext sessionContext)
        where TEntity : class, IEntity<string>, IDataPermission, new()
    {
        return GetTopTableAccessLevel(sessionContext.Roles, typeof(TEntity).Name.ToSnakeCase());

        ////old
        //ETableAccessLevel queryFilter = GetCurrentQueryFilter(sessionContext.Roles, typeof(TEntity).Name);
        //return new DataPermissionScheme(queryFilter);
        //return queryFilter;
    }

    public (string? creatorId, string? creatorName, string? orgId, string? orgName, int orgLevel, string? areaId) GetDataPermissionOptions()
    {
        return (_sessionContext.UserId, _sessionContext.UserName,
                _sessionContext.OrgId, _sessionContext.OrgName,
                _sessionContext.OrgLevel, _sessionContext.AreaId
            );
    }

    // public (string orgId, string orgCode, string creatorId, string? areaId, string? creatorName, string? creatorOrgName) GetDataPermissionOptions()
    // {
    //     return (_sessionContext.RequiredOrgId, _sessionContext.RequiredOrgCode,
    //         _sessionContext.RequiredUserId, _sessionContext.OrgId,
    //         _sessionContext.UserName, _sessionContext.OrgName);
    // }

    //private ETableAccessLevel GetCurrentQueryFilter(string[] roles, string entityName)
    //{
    //    using var scope = _serviceScopeFactory.CreateScope();
    //    var systemDataTableRepository = scope.ServiceProvider.GetRequiredService<ISystemDataTableRepository>();
    //    var systemDataAuthorityRepository = scope.ServiceProvider.GetRequiredService<ISystemDataAuthorityRepository>();

    //    ////查询对应表配置
    //    var tableModel = systemDataTableRepository.GetAsync(x => x.EntityName == entityName).GetAwaiter().GetResult();
    //    if (tableModel == null)
    //        throw UserFriendlyException.SameMessage($"未配置表{entityName}的查询权限");
    //    ////查询表对应最高数据权限
    //    var auth = systemDataAuthorityRepository.GetMyTopDataAuth(roles, tableModel.Id);
    //    return auth;
    //}

    /// <summary>
    /// 查询最高访问权限
    /// </summary>
    /// <param name="roles"></param>
    /// <param name="tableName"></param>
    /// <returns></returns>
    private ETableAccessLevel GetTopTableAccessLevel(string[] roles, string tableName)
    {
        if (roles.Contains(RoleSeedData.AdminRole))
            return ETableAccessLevel.All;

        using var scope = _serviceScopeFactory.CreateScope();
        var tableAccessLevelCacheManager = scope.ServiceProvider.GetService<ITableAccessLevelCacheManager>();
        var levels = tableAccessLevelCacheManager?.QueryAll() ?? new List<TableAccessLevelCacheItem>();
        var levelInRoles = levels.Where(d => roles.Contains(d.RoleCode) && d.TableName == tableName).ToList();
        if (!levelInRoles.Any())
            return ETableAccessLevel.Deny;
        //get top level
        return levelInRoles.Max(d => d.AccessLevel);
    }
}