using Infrastructure;
using Infrastructure.Helpers;
using Microsoft.Extensions.Configuration;
using OpenAuth.App.BaseApp.Base;
using OpenAuth.App.Interface;
using OpenAuth.App.Request;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using SqlSugar;

namespace OpenAuth.App
{
    public class WFSchemeInfoApp : SqlSugarBaseApp<WFSchemeInfo, SugarDbContext>
    {
        ISqlSugarClient client;
        private IConfiguration configuration;

        public WFSchemeInfoApp(
            ISugarUnitOfWork<SugarDbContext> unitWork,
            ISimpleClient<WFSchemeInfo> repository,
            IAuth auth, IConfiguration configuration) : base(unitWork, repository, auth)
        {
            client = base.Repository.AsSugarClient();
            this.configuration = configuration;
        }

        public async Task<PageInfo<List<WFSchemeInfo>>> LoadPage(PageReq pageReq, string category, string ids)
        {
            RefAsync<int> totalCount = 0;

            var idList = new string[0];
            if (!string.IsNullOrEmpty(ids))
            {
                idList = ids.Split(',');
            }

            var list = await client.Queryable<WFSchemeInfo>()
                .LeftJoin<WFScheme>((info, s) => info.SchemeId == s.Id)
                .WhereIF(!string.IsNullOrEmpty(pageReq.key),
                    info => info.Name.Contains(pageReq.key) || info.Code.Contains(pageReq.key))
                .WhereIF(!string.IsNullOrEmpty(category), info => info.Category == category)
                .WhereIF(!string.IsNullOrEmpty(ids), info => idList.Contains(info.Id))
                .OrderByDescending((info, s) => s.CreateDate)
                .Select((info, s) => new WFSchemeInfo()
                {
                    AuthType = info.AuthType,
                    Id = info.Id,
                    Category = info.Category,
                    Code = info.Code,
                    Color = info.Color,
                    Description = info.Description,
                    EnabledMark = info.EnabledMark,
                    Icon = info.Icon,
                    IsInApp = info.IsInApp,
                    Mark = info.Mark,
                    Name = info.Name,
                    SchemeId = info.SchemeId,

                    Type = s.Type,
                    CreateDate = s.CreateDate,
                    CreateUserId = s.CreateUserId,
                    CreateUserName = s.CreateUserName
                }).ToPageListAsync(pageReq.page, pageReq.limit, totalCount);

            return new PageInfo<List<WFSchemeInfo>>
            {
                Items = list,
                Total = totalCount
            };
        }

        public async Task<List<WFSchemeInfo>> Load()
        {
            return await base.Repository.GetListAsync(a => a.EnabledMark == 1);
        }

        public async Task<List<WFSchemeInfo>> GetInfoList()
        {
            var currentUser = _auth.GetCurrentUser();

            var userId = currentUser.User.Id.ToString();
            var postIds = currentUser.Positions.Select(a => a.Id.ToString()).ToList();
            var roleIds = currentUser.Roles.Select(a => a.Id.ToString()).ToList();

            List<string> ids = new List<string>();
            if (!string.IsNullOrEmpty(userId))
            {
                ids.Add(userId);
            }

            ids.AddRange(postIds);
            ids.AddRange(roleIds);
            var list = await client.Queryable<WFSchemeAuth>().Where(t => ids.ToArray().Contains(t.ObjId)).ToListAsync();
            List<string> schemeinfoIds = new List<string>();
            foreach (var item in list)
            {
                schemeinfoIds.Add(item.SchemeInfoId);
            }

            return await client.Queryable<WFSchemeInfo>()
                .LeftJoin<WFScheme>((t, s) => t.SchemeId == s.Id)
                .Where((t, s) =>
                    t.EnabledMark == 1 &&
                    t.Mark == 1 &&
                    (schemeinfoIds.ToArray().Contains(t.Id) || t.AuthType == 1) &&
                    s.Type == 1).ToListAsync();
        }


        public async Task<WFSchemeInfo> GetInfoEntityByCode(string code)
        {
            return await base.Repository.GetFirstAsync(t => t.Code == code);
        }


        public async Task<WFScheme> GetSchemeEntity(string keyValue)
        {
            return await client.Queryable<WFScheme>().FirstAsync(a => a.Id == keyValue);
        }

        public async Task<List<WFSchemeAuth>> GetAuthList(string schemeInfoId)
        {
            return await client.Queryable<WFSchemeAuth>().Where(t => t.SchemeInfoId == schemeInfoId).ToListAsync();
        }


        /// <summary>
        /// 获取模板的实体
        /// </summary>
        /// <param name="keyValue">主键</param>
        /// <returns></returns>
        public async Task<WFScheme> GetScheme(string keyValue)
        {
            return await client.Queryable<WFScheme>().FirstAsync(a => a.Id == keyValue);
        }


        public async Task<Response<bool>> UpdateScheme(string schemeInfoId, string schemeId)
        {
            WFScheme nWFSchemeEntity = await GetScheme(schemeId);

            var flag = false;
            if (nWFSchemeEntity.Type != 1)
            {
                flag = await base.Repository
                    .UpdateSetColumnsTrueAsync(a => new WFSchemeInfo() { SchemeId = schemeId, EnabledMark = 0 },
                        a => a.Id == schemeInfoId);
            }
            else
            {
                flag = await base.Repository
                    .UpdateSetColumnsTrueAsync(a => new WFSchemeInfo() { SchemeId = schemeId },
                        a => a.Id == schemeInfoId);
            }

            return new Response<bool>
            {
                Result = flag,
                Message = flag == true ? "success" : "error"
            };
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="keyValue">主键吧？</param>
        /// <param name="infoEntity"></param>
        /// <param name="schemeEntity"></param>
        /// <param name="authList"></param>
        /// <returns></returns>
        public async Task<Response<bool>> SaveEntity(string keyValue, WFSchemeInfo infoEntity, WFScheme schemeEntity,
            IEnumerable<WFSchemeAuth> authList)
        {
            // 如果存在schemeEntity content 解码
            if (!string.IsNullOrEmpty(schemeEntity.Content))
            {
                var code = configuration.GetSection("AppSetting:ASECode").Value;
                schemeEntity.Content =
                    AESHelper.AesDecrypt(schemeEntity.Content, code); //"12345678901234567890123456789012"
            }

            if (!string.IsNullOrEmpty(keyValue))
            {
                WFScheme oldNWFSchemeEntity = await GetScheme(infoEntity.SchemeId);
                if (oldNWFSchemeEntity.Content == schemeEntity.Content && oldNWFSchemeEntity.Type == schemeEntity.Type)
                {
                    schemeEntity = null;
                }
            }

            using (var uwo = UnitWork.CreateContext())
            {
                if (string.IsNullOrEmpty(keyValue))
                {
                    infoEntity.Id = Guid.NewGuid().ToString();
                    infoEntity.EnabledMark = 1;
                }
                else
                {
                    infoEntity.Id = keyValue;
                }

                #region 模板信息

                if (schemeEntity != null)
                {
                    schemeEntity.SchemeInfoId = infoEntity.Id;
                    schemeEntity.Id = Guid.NewGuid().ToString();
                    schemeEntity.CreateDate = DateTime.Now;
                    schemeEntity.CreateUserId = _auth.GetUserId();
                    schemeEntity.CreateUserName = _auth.GetUserName();
                    await uwo.WFScheme.InsertAsync(schemeEntity);
                    infoEntity.SchemeId = schemeEntity.Id;
                }

                #endregion

                #region 模板基础信息

                if (!string.IsNullOrEmpty(keyValue))
                {
                    await uwo.WFSchemeInfo.UpdateAsync(infoEntity);
                }
                else
                {
                    await uwo.WFSchemeInfo.InsertAsync(infoEntity);
                }

                #endregion

                #region 流程模板权限信息

                string schemeInfoId = infoEntity.Id;
                await uwo.WFSchemeAuth.DeleteAsync(t => t.SchemeInfoId.Equals(schemeInfoId));
                foreach (var item in authList)
                {
                    item.Id = Guid.NewGuid().ToString();
                    item.SchemeInfoId = schemeInfoId;
                    await uwo.WFSchemeAuth.InsertAsync(item);
                }

                #endregion

                var flag = uwo.Commit();

                return new Response<bool>
                {
                    Result = flag,
                    Message = flag == true ? "success" : "error"
                };
            }
        }

        /// <summary>
        /// 更新自定义表单模板状态
        /// </summary>
        /// <param name="schemeInfoId">模板信息主键</param>
        /// <param name="state">状态1启用0禁用</param>
        public async Task<Response<bool>> UpdateState(string schemeInfoId, int state)
        {
            var flag = await base.Repository.UpdateSetColumnsTrueAsync(a => new WFSchemeInfo() { EnabledMark = state },
                a => a.Id == schemeInfoId);
            return new Response<bool>
            {
                Result = flag,
                Message = flag == true ? "success" : "error"
            };
        }

        public async Task<Response<bool>> DeleteEntity(string keyValue)
        {
            using (var uow = base.UnitWork.CreateContext())
            {
                await uow.WFSchemeInfo.DeleteAsync(t => t.Id.Equals(keyValue));
                await uow.WFSchemeAuth.DeleteAsync(t => t.SchemeInfoId.Equals(keyValue));
                await uow.WFScheme.DeleteAsync(t => t.SchemeInfoId.Equals(keyValue));

                var falg = uow.Commit();
                return new Response<bool>
                {
                    Result = falg,
                    Message = (falg == true ? "success" : "error")
                };
            }
        }

        public WFSchemeInfo SelectBySchemeCode(string schemeCode)
        {
            return  Repository.GetFirst(a => a.Code == schemeCode);
        }
    }
}