using Hotline.FlowEngine.Workflows;
using Hotline.Repository.SqlSugar.DataPermissions;
using Hotline.Share.Enums.FlowEngine;
using SqlSugar;
using XF.Domain.Entities;

namespace Hotline.Repository.SqlSugar.Extensions
{
    public static class DataPermissionExtensions
    {
        public static ISugarQueryable<TEntity> DataPermissionFiltering<TEntity>(this ISugarQueryable<TEntity> queryable,
            IDataPermissionFilterBuilder dataPermissionFilterBuilder)
            where TEntity : class, IEntity<string>, IDataPermission, new()
        {
            return queryable.Where(dataPermissionFilterBuilder.Build<TEntity>());
        }

        public static ISugarQueryable<TEntity> WorkflowViewFiltering<TEntity>(this ISugarQueryable<TEntity> queryable,
            IDataPermissionFilterBuilder dataPermissionFilterBuilder)
            where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
        {
            var session = dataPermissionFilterBuilder.SessionContext;

            return queryable.Where(d => SqlFunc.Subqueryable<WorkflowTrace>()
                    .Where(step => step.ExternalId == d.Id &&
                            ((step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == session.RequiredUserId) ||
                               (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == session.RequiredOrgId) ||
                               (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && session.Roles.Contains(step.RoleId))))
                    .Any());

            //return queryable.LeftJoin<WorkflowTrace>((d, step) => d.Id == step.ExternalId)
            //    .Where((d, step) => (step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == session.RequiredUserId) ||
            //                           (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == session.RequiredOrgId) ||
            //                           (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && session.Roles.Contains(step.RoleId)))
            //    .Select((d, step) => d)
            //    ;

            //return queryable.Where(dataPermissionFilterBuilder.BuildWithFlowViewFilter<TEntity>());
        }

        public static ISugarQueryable<TEntity> WorkflowHandleFiltering<TEntity>(this ISugarQueryable<TEntity> queryable,
            IDataPermissionFilterBuilder dataPermissionFilterBuilder, bool canHandle)
            where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
        {
            var session = dataPermissionFilterBuilder.SessionContext;
            return queryable.LeftJoin<WorkflowStep>((d, step) => d.Id == step.ExternalId)
                    .Where((d, step) => (step.FlowAssignType == EFlowAssignType.User && !string.IsNullOrEmpty(step.HandlerId) && step.HandlerId == session.RequiredUserId) ||
                                             (step.FlowAssignType == EFlowAssignType.Org && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == session.RequiredOrgId) ||
                                             (step.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(step.RoleId) && session.Roles.Contains(step.RoleId)))
                    .WhereIF(canHandle, (d, step) => step.Status != EWorkflowStepStatus.Handled)
                    .WhereIF(!canHandle, (d, step) => step.Status == EWorkflowStepStatus.Handled)
                    .Select((d, step) => d)
                ;

            //return queryable.Where(dataPermissionFilterBuilder.BuildWithFlowHandleFilter<TEntity>(canHandle));
        }

        public static TEntity InitDatePermission<TEntity>(this TEntity entity,
            IDataPermissionManager dataPermissionManager)
            where TEntity : class, IEntity<string>, IDataPermission, new()
        {
            var result = dataPermissionManager.GetDataPermissionOptions();
            entity.CreateDataPermission(result.creatorId, result.creatorName, result.orgId, result.orgName,
                result.orgLevel, result.areaId);
            return entity;
        }

        public static TEntity AssignToCreator<TEntity>(this TEntity entity,
            IDataPermissionManager dataPermissionManager)
            where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
        {
            var (creatorId, _, _, _, _, _) = dataPermissionManager.GetDataPermissionOptions();
            entity.Assign(EFlowAssignType.User, creatorId);
            return entity;
        }
    }
}