using DocumentFormat.OpenXml.EMMA;
using Infrastructure.Extensions;
using OpenAuth.App.Interface;
using OpenAuth.Repository;
using OpenAuth.Repository.Core;
using OpenAuth.Repository.Domain;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using OpenAuth.App.BaseApp.Base;

namespace OpenAuth.App.Base
{
    public abstract class TreeApp<T, TDbContext, TIdType> : SqlSugarBaseApp<T, TDbContext>
    where T : TreeEntity<TIdType>, new()
    where TDbContext : SugarUnitOfWork, new()
    {
        protected TreeApp(ISugarUnitOfWork<TDbContext> unitWork, ISimpleClient<T> repository, IAuth auth) : base(unitWork, repository, auth)
        {
        }

        protected abstract TIdType GetDefaultId();
        protected abstract string GetDefaultCascadeId();

        protected virtual void CalculateCascade(T entity)
        {
            if (EqualityComparer<TIdType>.Default.Equals(entity.ParentId, GetDefaultId()))
            {
                var entityType = entity.GetType();
                var baseType = entityType.BaseType;

                if (baseType == typeof(TreeEntity<string>))
                {
                    var parentIdProperty = entityType.GetProperty("ParentId");
                    parentIdProperty.SetValue(entity, "0", null);
                }
                else
                {
                    entity.ParentId = default;
                }

                //entity.ParentId = default;

            }

            string cascadeId;
            int currentCascadeId = 1;
            var sameLevels = GetSameLevelEntities(entity);

            foreach (var obj in sameLevels)
            {
                int objCascadeId = int.Parse(obj.CascadeId.TrimEnd('.').Split('.').Last());
                currentCascadeId = Math.Max(currentCascadeId, objCascadeId + 1);
            }





            //if (!EqualityComparer<TIdType>.Default.Equals(entity.ParentId, GetDefaultId()))
            //{
            //    var parentOrg = GetParentOrganization(entity.ParentId);
            //    cascadeId = parentOrg.CascadeId + currentCascadeId;
            //    entity.ParentName = parentOrg.Name;
            //}
            if (!Object.Equals(entity.ParentId, GetDefaultId()))
            {
                var parentOrg = GetParentOrganization(entity.ParentId);
                cascadeId = parentOrg.CascadeId + "." + currentCascadeId;
                entity.ParentName = parentOrg.Name;
            }
            else
            {
                //cascadeId = GetDefaultCascadeId() + currentCascadeId + ".";
                //cascadeId = GetDefaultCascadeId() + currentCascadeId;
                cascadeId = GetDefaultCascadeId();
                entity.ParentName = "根节点";
            }

            entity.CascadeId = cascadeId;
        }

        //protected virtual IEnumerable<T> GetSameLevelEntities(T entity)
        //{
        //    return Repository
        //        .ChangeRepository<SugarRepositiry<T>>()
        //        .GetList(o => EqualityComparer<TIdType>.Default.Equals(o.ParentId, entity.ParentId) && !o.Id.Equals(entity.Id));
        //}

        protected virtual IEnumerable<T> GetSameLevelEntities(T entity)
        {
            var parentId = entity.ParentId;
            return Repository
                .ChangeRepository<SugarRepositiry<T>>()
                .GetList(o => Object.Equals(o.ParentId, parentId) && !o.Id.Equals(entity.Id));
        }


        protected virtual T GetParentOrganization(TIdType parentId)
        {
            //var parentOrg = Repository
            //    .ChangeRepository<SugarRepositiry<T>>()
            //    .GetFirst(o => EqualityComparer<TIdType>.Default.Equals(o.Id, parentId));

            var parentOrg = Repository
                    .ChangeRepository<SugarRepositiry<T>>()
                    .GetFirst(o => Object.Equals(o.Id, parentId));


            if (parentOrg == null)
            {
                throw new Exception("未能找到该组织的父节点信息");
            }

            return parentOrg;
        }

        public void UpdateTreeObj(T obj)
        {
            //CalculateCascade(obj);

            //var cascadeId = Repository.GetFirst(o => object.Equals(o.Id, obj.Id)).CascadeId;
            //var objs = Repository.GetList(u => u.CascadeId.Contains(cascadeId) && !object.Equals(u.Id, obj.Id))
            //        .OrderBy(u => u.CascadeId).ToList();

            Repository.Update(obj);

            //foreach (var a in objs)
            //{
            //    a.CascadeId = a.CascadeId.Replace(cascadeId, obj.CascadeId);
            //    if (EqualityComparer<TIdType>.Default.Equals(a.ParentId, obj.Id))
            //    {
            //        a.ParentName = obj.Name;
            //    }

            //    Repository.Update(a);
            //}
        }

      
    }
}
