using SqlSugar;
using XF.Domain.Entities;
using XF.Domain.Events;
using XF.Domain.Extensions;
using XF.Utility.SequentialId;

namespace XF.Domain.Repository;

public abstract class Entity : IEntity<string>, IDomainEvents, IDataPermission, ITable
{
    private List<IAppNotification> _domainEvents = new();

    public string Id { get; set; }

    [SugarColumn(ColumnDescription = "创建人")]
    public string? CreatorId { get; set; }

    public string? CreatorName { get; set; }

    [SugarColumn(ColumnDescription = "组织Id")]
    public string? CreatorOrgId { get; set; }

    public string? CreatorOrgName { get; set; }

    [SugarColumn(DefaultValue = "0")]
    public int CreatorOrgLevel { get; set; } = 0;

    /// <summary>
    /// 一级部门Id
    /// </summary>
    [SugarColumn(ColumnDescription = "数据权限区域Id")]
    public string? AreaId { get; set; }

    public void CreateDataPermission(string? creatorId, string? creatorName, string? orgId, string? orgName, int orgLevel,
        string? areaId)
    {
        CreatorId = creatorId;
        CreatorName = creatorName;
        CreatorOrgId = orgId;
        CreatorOrgName = orgName;
        CreatorOrgLevel = orgLevel;
        AreaId = areaId;
    }

    public void AddEvent(IAppNotification notification)
    {
        if (_domainEvents.Contains(notification)) return;
        _domainEvents.Add(notification);
    }

    public void ClearEvents() => _domainEvents.Clear();

    public ICollection<IAppNotification> QueryAllEvents() => _domainEvents;

    public void InitId() => Id = SequentialStringGenerator.Create();
    public void InitUlid() => Id = SequentialStringGenerator.Create(EStringFormat.Ulid);
}

/// <summary>
/// 实体（带有创建时间）
/// </summary>
public abstract class CreationEntity : Entity, IHasCreationTime
{
    /// <summary>
    /// 创建时间
    /// </summary>
    [SugarColumn(ColumnDescription = "创建时间")]
    public DateTime CreationTime { get; set; }
}

/// <summary>
/// 实体（带有软删除）
/// </summary>
public abstract class SoftDeleteEntity : Entity, IHasDeletionTime, ISoftDelete
{
    /// <summary>
    /// 删除时间
    /// </summary>
    [SugarColumn(ColumnDescription = "删除时间")]
    public DateTime? DeletionTime { get; set; }

    [SugarColumn(ColumnDescription = "是否删除", DefaultValue = "f")]
    public bool IsDeleted { get; set; }

    public void SoftDelete()
    {
        IsDeleted = true;
        DeletionTime = DateTime.Now;
    }
}

/// <summary>
/// 实体（带有创建时间和软删除）
/// </summary>
public abstract class CreationSoftDeleteEntity : CreationEntity, IHasDeletionTime, ISoftDelete
{
    [SugarColumn(ColumnDescription = "是否删除", DefaultValue = "f")]
    public bool IsDeleted { get; set; }

    /// <summary>
    /// 删除时间
    /// </summary>
    [SugarColumn(ColumnDescription = "删除时间")]
    public DateTime? DeletionTime { get; set; }

    public void SoftDelete()
    {
        IsDeleted = true;
        DeletionTime = DateTime.Now;
    }

    public void Recover() => IsDeleted = false;
}

public abstract class CreationModificationEntity : CreationEntity, IHasModificationTime
{
    /// <summary>
    /// 最近更新时间
    /// </summary>
    [SugarColumn(ColumnDescription = "最近更新时间")]
    public DateTime? LastModificationTime { get; set; }

    public void Modified() => LastModificationTime = DateTime.Now;
}

/// <summary>
/// 全状态实体(创建时间、更新时间、软删除)
/// </summary>
public abstract class FullStateEntity : CreationSoftDeleteEntity, IHasModificationTime
{
    /// <summary>
    /// 最近更新时间
    /// </summary>
    [SugarColumn(ColumnDescription = "最近更新时间")]
    public DateTime? LastModificationTime { get; set; }

    public void Modified() => LastModificationTime = DateTime.Now;
}

public abstract class WorkflowEntity : FullStateEntity, IWorkflow
{
    [SugarColumn(IsNullable = true)] public string? WorkflowId { get; set; }

    /// <summary>
    /// 过期时间配置id
    /// </summary>
    [SugarColumn(IsNullable = true)]
    public string? ExpiredTimeConfigId { get; set; }

    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<string>? FlowedOrgIds { get; set; } = new();

    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<string>? FlowedUserIds { get; set; } = new();

    #region 当前办理对象

    /// <summary>
    /// 办理人id
    /// </summary>
    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<HandlerGroupItem>? HandlerUsers { get; set; } = new();

    /// <summary>
    /// 办理部门id
    /// </summary>
    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<HandlerGroupItem>? HandlerOrgs { get; set; } = new();

    #endregion

    //public void Assign(EFlowAssignType type, string handler)
    //{
    //    if (string.IsNullOrEmpty(handler)) return;
    //    handler = handler.ToLower();
    //    switch (type)
    //    {
    //        case EFlowAssignType.Org:
    //            var orgCodes = handler.GetHigherOrgIds(true).ToList();
    //            FlowedOrgIds.AddRange(orgCodes);
    //            FlowedOrgIds = FlowedOrgIds.Distinct().ToList();
    //            break;
    //        case EFlowAssignType.User:
    //            if (!FlowedUserIds.Exists(d => d == handler))
    //                FlowedUserIds.Add(handler);
    //            break;
    //        default:
    //            throw new ArgumentOutOfRangeException(nameof(type), type, null);
    //    }
    //}

    //public void Assign(EFlowAssignType type, IEnumerable<string> handlers)
    //{
    //    if (handlers == null || !handlers.Any()) return;
    //    handlers = handlers.Select(d => d.ToLower());
    //    switch (type)
    //    {
    //        case EFlowAssignType.Org:
    //            var orgCodes = handlers.SelectMany(d => d.GetHigherOrgIds(true)).ToList();
    //            FlowedOrgIds.AddRange(orgCodes);
    //            FlowedOrgIds = FlowedOrgIds.Distinct().ToList();
    //            break;
    //        case EFlowAssignType.User:
    //            FlowedUserIds.AddRange(handlers);
    //            FlowedUserIds = FlowedUserIds.Distinct().ToList();
    //            break;
    //        default:
    //            throw new ArgumentOutOfRangeException(nameof(type), type, null);
    //    }
    //}

    /// <summary>
    /// 是否可查看
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="orgId"></param>
    /// <returns></returns>
    public bool CanView(string userId, string orgId)
    {
        return FlowedUserIds.Any(d => d == userId) ||
               FlowedOrgIds.Any(d => d == orgId);
    }

    /// <summary>
    /// 是否能办理
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="orgId"></param>
    /// <returns></returns>
    public bool CanHandle(string userId, string orgId)
    {
        return CanView(userId, orgId) &&
            HandlerUsers.Any(d => d.Key == userId) ||
            HandlerOrgs.Any(d => d.Key == orgId);
    }

    /// <summary>
    /// 流程每次流转时更新待办对象及流经对象
    /// </summary>
    public void Flowed(List<string> flowedUserIds, List<string> flowedOrgIds, List<HandlerGroupItem> handlerUsers, List<HandlerGroupItem> handlerOrgs)
    {
        FlowedUserIds = flowedUserIds;
        FlowedOrgIds = flowedOrgIds;
        HandlerUsers = handlerUsers;
        HandlerOrgs = handlerOrgs;
    }

    public void Assign(List<string> flowedOrgIds, List<string> flowedUserIds)
    {
        FlowedOrgIds = flowedOrgIds;
        FlowedUserIds = flowedUserIds;
    }
}

public abstract class PositionEntity : FullStateEntity
{
    /// <summary>
    /// 经度
    /// </summary>
    [SugarColumn(ColumnDescription = "经度")]
    public double? Longitude { get; set; }

    /// <summary>
    /// 维度
    /// </summary>
    [SugarColumn(ColumnDescription = "纬度")]
    public double? Latitude { get; set; }

    /// <summary>
    /// 行政区划编码
    /// </summary>
    [SugarColumn(ColumnDescription = "行政区划编码")]
    public string? AreaCode { get; set; }

    /// <summary>
    /// 省
    /// </summary>
    public string? Province { get; set; }

    /// <summary>
    /// 市
    /// </summary>
    public string? City { get; set; }

    /// <summary>
    /// 区/县
    /// </summary>
    public string? County { get; set; }

    /// <summary>
    /// 乡镇(4级行政区划)
    /// </summary>
    public string? Town { get; set; }

    /// <summary>
    /// 村/社区
    /// </summary>
    public string? Village { get; set; }

    /// <summary>
    /// 详细街道
    /// </summary>
    public string? Street { get; set; }

    

    /// <summary>
    /// 行政区划地址
    /// </summary>
    public string? Address { get; set; }

    /// <summary>
    /// 完整地址
    /// </summary>
    public string? FullAddress { get; set; }
}

public abstract class PositionWorkflowEntity : PositionEntity, IWorkflow
{
    [SugarColumn(IsNullable = true)]
    public string? WorkflowId { get; set; }

    /// <summary>
    /// 过期时间配置id
    /// </summary>
    [SugarColumn(IsNullable = true)]
    public string? ExpiredTimeConfigId { get; set; }

    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<string>? FlowedOrgIds { get; set; } = new();

    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<string>? FlowedUserIds { get; set; } = new();

    #region 当前办理对象

    /// <summary>
    /// 办理人id
    /// </summary>
    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<HandlerGroupItem>? HandlerUsers { get; set; } = new();

    /// <summary>
    /// 办理部门id
    /// </summary>
    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<HandlerGroupItem>? HandlerOrgs { get; set; } = new();

    #endregion

    //public void Assign(EFlowAssignType type, string handler)
    //{
    //    if (string.IsNullOrEmpty(handler)) return;
    //    handler = handler.ToLower();
    //    switch (type)
    //    {
    //        case EFlowAssignType.Org:
    //            var orgCodes = handler.GetHigherOrgIds(true).ToList();
    //            FlowedOrgIds.AddRange(orgCodes);
    //            FlowedOrgIds = FlowedOrgIds.Distinct().ToList();
    //            break;
    //        case EFlowAssignType.User:
    //            if (!FlowedUserIds.Exists(d => d == handler))
    //                FlowedUserIds.Add(handler);
    //            break;
    //        default:
    //            throw new ArgumentOutOfRangeException(nameof(type), type, null);
    //    }
    //}

    //public void Assign(EFlowAssignType type, IEnumerable<string> handlers)
    //{
    //    if (handlers == null || !handlers.Any()) return;
    //    handlers = handlers.Select(d => d.ToLower());
    //    switch (type)
    //    {
    //        case EFlowAssignType.Org:
    //            var orgCodes = handlers.SelectMany(d => d.GetHigherOrgIds(true)).ToList();
    //            FlowedOrgIds.AddRange(orgCodes);
    //            FlowedOrgIds = FlowedOrgIds.Distinct().ToList();
    //            break;
    //        case EFlowAssignType.User:
    //            FlowedUserIds.AddRange(handlers);
    //            FlowedUserIds = FlowedUserIds.Distinct().ToList();
    //            break;
    //        default:
    //            throw new ArgumentOutOfRangeException(nameof(type), type, null);
    //    }
    //}

    /// <summary>
    /// 是否可查看
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="orgId"></param>
    /// <returns></returns>
    public bool CanView(string userId, string orgId)
    {
        return FlowedUserIds.Any(d => d == userId) ||
               FlowedOrgIds.Any(d => d == orgId);
    }

    /// <summary>
    /// 是否能办理
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="orgId"></param>
    /// <returns></returns>
    public bool CanHandle(string userId, string orgId)
    {
        return CanView(userId, orgId) &&
               HandlerUsers.Any(d => d.Key == userId) ||
               HandlerOrgs.Any(d => d.Key == orgId);
    }

    /// <summary>
    /// 流程每次流转时更新待办对象及流经对象
    /// </summary>
    public void Flowed(List<string> flowedUserIds, List<string> flowedOrgIds, List<HandlerGroupItem> handlerUsers, List<HandlerGroupItem> handlerOrgs)
    {
        FlowedUserIds = flowedUserIds;
        FlowedOrgIds = flowedOrgIds;
        HandlerUsers = handlerUsers;
        HandlerOrgs = handlerOrgs;
    }

}