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))||
                               (step.FlowAssignType == EFlowAssignType.OrgAndRole && !string.IsNullOrEmpty(step.RoleId) && session.Roles.Contains(step.RoleId) && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == session.RequiredOrgId)
							   ))
                    .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> WorkflowViewFilteringAdmin<TEntity>(this ISugarQueryable<TEntity> queryable)
           where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
        {
            return queryable.Where(d => SqlFunc.Subqueryable<WorkflowTrace>()
                    .Where(step => step.ExternalId == d.Id)
                    .Any());
        }

        public static ISugarQueryable<TEntity> WorkflowHandleFiltering<TEntity>(this ISugarQueryable<TEntity> queryable,
            IDataPermissionFilterBuilder dataPermissionFilterBuilder, bool hasHandled, bool? isAdmin = false)
            where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
        {
            //如果是管理员，只查询已办待办
            if (isAdmin.HasValue && isAdmin.Value)
            {
                return queryable.Where(d => SqlFunc.Subqueryable<WorkflowTrace>()
                    .Where(step => step.ExternalId == d.Id &&
                                   (hasHandled || step.Status != EWorkflowStepStatus.Handled) &&
                                   (!hasHandled || step.Status == EWorkflowStepStatus.Handled &&
                                       step.TraceState != EWorkflowTraceState.StepRemoveByPrevious && step.TraceState != EWorkflowTraceState.StepRemoveByRecall))
                    .Any()
                );
            }

            var session = dataPermissionFilterBuilder.SessionContext;
            //非管理员按照常规逻辑
            return queryable.Where(d => SqlFunc.Subqueryable<WorkflowTrace>()
                .Where(step => step.ExternalId == d.Id &&
                               (hasHandled || step.Status != EWorkflowStepStatus.Handled) &&
                               (!hasHandled || step.Status == EWorkflowStepStatus.Handled &&
                                   step.TraceState != EWorkflowTraceState.StepRemoveByPrevious &&
                                   step.TraceState != EWorkflowTraceState.StepRemoveByRecall) &&
                               ((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)) ||
                                (step.FlowAssignType == EFlowAssignType.OrgAndRole && !string.IsNullOrEmpty(step.RoleId) && session.Roles.Contains(step.RoleId) && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == session.RequiredOrgId )
								))
                .Any()
            );
            //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(hasHandled, (d, step) => step.Status == EWorkflowStepStatus.Handled)
            //        .WhereIF(!hasHandled, (d, step) => step.Status != EWorkflowStepStatus.Handled)
            //        .Select((d, step) => d)
            //    ;

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


		public static ISugarQueryable<TEntity> WorkflowHandleStepFiltering<TEntity>(this ISugarQueryable<TEntity> queryable,
			IDataPermissionFilterBuilder dataPermissionFilterBuilder, bool hasHandled, bool? isAdmin = false)
			where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
		{
			//如果是管理员，只查询已办待办
			if (isAdmin.HasValue && isAdmin.Value)
			{
				return queryable.Where(d => SqlFunc.Subqueryable<WorkflowStep>()
					.Where(step => step.ExternalId == d.Id )
                    .WhereIF(hasHandled, step => step.Status == EWorkflowStepStatus.Handled)
					.WhereIF(!hasHandled, step => step.Status != EWorkflowStepStatus.Handled)
					.Any()
				);
			}

			var session = dataPermissionFilterBuilder.SessionContext;
			//非管理员按照常规逻辑
			return queryable.Where(d => SqlFunc.Subqueryable<WorkflowStep>()
			   .WhereIF(hasHandled, step => step.Status == EWorkflowStepStatus.Handled)
			   .WhereIF(!hasHandled, step => step.Status != EWorkflowStepStatus.Handled)
				.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)) ||
								(step.FlowAssignType == EFlowAssignType.OrgAndRole && !string.IsNullOrEmpty(step.RoleId) && session.Roles.Contains(step.RoleId) && !string.IsNullOrEmpty(step.HandlerOrgId) && step.HandlerOrgId == session.RequiredOrgId)
								))
				.Any()
			);
		}

		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;
        //}
    }
}