using Hotline.Share.Enums.Settings;
using System.Linq.Expressions;
using Hotline.FlowEngine.Workflows;
using Hotline.SeedData;
using SqlSugar;
using XF.Domain.Authentications;
using XF.Domain.Dependency;
using XF.Domain.Entities;

namespace Hotline.Repository.SqlSugar.DataPermissions;

public class DataPermissionFilterBuilder : IDataPermissionFilterBuilder, IScopeDependency
{

    public DataPermissionFilterBuilder(ISessionContext sessionContext, IDataPermissionManager dataPermissionManager)
    {
        DataPermissionManager = dataPermissionManager;
        SessionContext = sessionContext;
    }

    public ISessionContext SessionContext { get; }
    public IDataPermissionManager DataPermissionManager { get; }

    public Expression<Func<TEntity, bool>> Build<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, new()
    {
        var queryFilterType = DataPermissionManager.GetQueryFilter<TEntity>(SessionContext);
        switch (queryFilterType)
        {
            case ETableAccessLevel.Creator:
                return d => d.CreatorId == SessionContext.RequiredUserId;
            case ETableAccessLevel.Org:
                return d => d.CreatorOrgId == SessionContext.RequiredOrgId;
            case ETableAccessLevel.OrgAndBelow:
                return d => d.CreatorOrgId.StartsWith(SessionContext.RequiredOrgId); //d.AreaId == _sessionContext.AreaId && _sessionContext.OrgLevel <= d.CreatorOrgLevel;
            case ETableAccessLevel.All:
                return d => true;
            case ETableAccessLevel.Deny:
            default:
                return d => false;
        }
    }

    public Expression<Func<TEntity, bool>> BuildWithFlowViewFilter<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
    {
        var roles = SessionContext.Roles;
        if (roles != null && roles.Contains(RoleSeedData.AdminRole))
            return d => true;

        return d => SqlFunc.JsonArrayAny(d.FlowedUserIds, SessionContext.RequiredUserId) ||
                    SqlFunc.JsonArrayAny(d.FlowedOrgIds, SessionContext.RequiredOrgId);
    }

    public Expression<Func<TEntity, bool>> BuildWithFlowHandleFilter<TEntity>(bool canHandle)
        where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
    {
        var userId = SessionContext.RequiredUserId;
        var orgId = SessionContext.RequiredOrgId;
        var roles = SessionContext.Roles;
        if (roles != null && roles.Contains(RoleSeedData.AdminRole))
            return d => true;

        if (canHandle)
        {
            return d =>
                ((SqlFunc.JsonArrayAny(d.FlowedUserIds, userId) || SqlFunc.JsonArrayAny(d.FlowedOrgIds, orgId)) &&
                 SqlFunc.JsonListObjectAny(d.HandlerUsers, "Key", userId) ||
                 SqlFunc.JsonListObjectAny(d.HandlerOrgs, "Key", orgId));
        }
        else
        {
            return d =>
                (SqlFunc.JsonArrayAny(d.FlowedUserIds, userId) || SqlFunc.JsonArrayAny(d.FlowedOrgIds, orgId)) &&
                 !(SqlFunc.JsonListObjectAny(d.HandlerUsers, "Key", userId) ||
                   SqlFunc.JsonListObjectAny(d.HandlerOrgs, "Key", orgId));
        }
    }

    public Expression<Func<TEntity, Workflow, bool>> BuildIncludeFlowData1<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
    {
        var userId = SessionContext.RequiredUserId;
        var orgCode = SessionContext.RequiredOrgId;
        var roles = SessionContext.Roles;
        if (roles != null && roles.Contains(RoleSeedData.AdminRole))
            return (d, w) => true;

        return (d, w) => SqlFunc.JsonArrayAny(w.FlowedUserIds, userId) ||
                         SqlFunc.JsonArrayAny(w.FlowedOrgIds, orgCode);
    }
}