using Furion.DependencyInjection;
using Furion.DistributedIDGenerator;
using Microsoft.AspNetCore.Hosting;
using Nirvana.Common;
using Nirvana.Common.ApiBase;
using Senparc.Weixin.Open;
using Senparc.Weixin.Open.ComponentAPIs;
using Senparc.Weixin.Open.Containers;
using Senparc.Weixin.Open.WxaAPIs;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using YBDevice.Entity;

namespace YBDevice.Application.OfficeialInfo
{
    /// <summary>
    /// 公众号管理
    /// </summary>
    public class OfficialService : IOfficialService, ITransient
    {
        private readonly IWebHostEnvironment _hostingEnvironment;
        private readonly ISqlSugarRepository<YB_OfficlaAccount> repository;
        private readonly IDistributedIDGenerator _idGenerator;
        private readonly SqlSugarClient dbClient;
        public string component_AppId = Senparc.Weixin.Config.SenparcWeixinSetting.Component_Appid;
        public string component_Secret = Senparc.Weixin.Config.SenparcWeixinSetting.Component_Secret;
        public string component_Token = Senparc.Weixin.Config.SenparcWeixinSetting.Component_Token;
        public string component_EncodingAESKey = Senparc.Weixin.Config.SenparcWeixinSetting.Component_EncodingAESKey;
        private readonly OperatorModel currentUser;
        public OfficialService(ISqlSugarRepository<YB_OfficlaAccount> sqlSugarRepository, IWebHostEnvironment hostingEnvironment, IDistributedIDGenerator idGenerator)
        {
            repository = sqlSugarRepository;
            dbClient = repository.Context;
            _hostingEnvironment = hostingEnvironment;
            currentUser = BaseInfoService.GetUserInfo();
            _idGenerator = idGenerator;
        }
        /// <summary>
        /// 公众号列表
        /// </summary>
        /// <param name="param"></param>
        /// <param name="type">0-全部,1-公众号,2-小程序</param>
        /// <returns></returns>
        public async Task<PageParms<OfficialListModel>> GetListAsync(QueryParams param, int type = 1)
        {
            RefAsync<int> totalnum = 0;
            var temquery = dbClient.Queryable<YB_OfficlaAccount, YB_BusinessOffice>((s, c) => new JoinQueryInfos(JoinType.Left, s.authorizer_appid == c.AppId));
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(x =>
                {
                    if (!string.IsNullOrEmpty(x.Value))
                    {
                        conModels.Add(new ConditionalModel()
                        {
                            FieldName = x.Name,
                            ConditionalType = (ConditionalType)x.Type,
                            FieldValue = x.Value.Trim()
                        });
                    }
                });
                if (conModels.Count > 0)
                {
                    temquery = temquery.Where(conModels);
                }
            }
            if (currentUser.AccountType != Entity.AccountType.platform)
            {
                temquery = temquery.Where((s, c) => c.BusinessId == currentUser.BusinessId);
            }
            if (type > 0)
            {
                temquery = temquery.Where((s, c) => s.type == type);
            }
            var query = await temquery.OrderBy((s, c) => s.lastmodifytime, OrderByType.Desc)
                .Select((s, c) => new OfficialListModel
                {
                    authorizer_appid = s.authorizer_appid,
                    service_type_info = s.service_type_info,
                    createtime = s.createtime,
                    func_info = s.func_info,
                    head_img = s.head_img,
                    isauthorize = s.isauthorize,
                    Id = s.Id,
                    lastmodifytime = s.lastmodifytime,
                    nick_name = s.nick_name,
                    qrcode_url = s.qrcode_url,
                    user_name = s.user_name,
                    verify_type_info = s.verify_type_info,
                    BusinessId = c.BusinessId
                })
                .Mapper((it, cache) =>
                {
                    var allbuss = cache.Get(list =>
                    {
                        var ids = list.Select(x => x.BusinessId).ToList();
                        return dbClient.Queryable<YB_Business>().Where(x => ids.Contains(x.Id)).ToList();
                    });
                    it.verify_type_info = $"{it.verify_type_info}{it.service_type_info}";
                    it.BusinessName = allbuss.FirstOrDefault(x => x.Id == it.BusinessId)?.Name;
                })
                 .ToPageListAsync(param.offset, param.limit, totalnum);
            return new PageParms<OfficialListModel>
            {
                page = param.offset,
                Items = query,
                totalnum = totalnum,
                limit = param.limit
            };
        }
        /// <summary>
        /// 小程序模版列表
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<PageParms<YB_MiniProgramsTpl>> GetTplListAsync(QueryParams param)
        {
            RefAsync<int> totalnum = 0;
            var tempquery = dbClient.Queryable<YB_MiniProgramsTpl>();
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(x =>
                {
                    if (!string.IsNullOrEmpty(x.Value))
                    {
                        conModels.Add(new ConditionalModel()
                        {
                            FieldName = x.Name,
                            ConditionalType = (ConditionalType)x.Type,
                            FieldValue = x.Value.Trim()
                        });
                    }
                });
                if (conModels.Count > 0)
                {
                    tempquery = tempquery.Where(conModels);
                }
            }
            var query = await tempquery.OrderBy(x => x.CreateTime, OrderByType.Desc)
                .ToPageListAsync(param.offset, param.limit, totalnum);
            return new PageParms<YB_MiniProgramsTpl>
            {
                page = param.offset,
                Items = query,
                totalnum = totalnum,
                limit = param.limit
            };
        }
        /// <summary>
        /// 小程序草稿列表
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<PageParms<YB_MiniProgramsDraft>> GetDraftListAsync(QueryParams param)
        {
            RefAsync<int> totalnum = 0;
            var tempquery = dbClient.Queryable<YB_MiniProgramsDraft>();
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(x =>
                {
                    if (!string.IsNullOrEmpty(x.Value))
                    {
                        conModels.Add(new ConditionalModel()
                        {
                            FieldName = x.Name,
                            ConditionalType = (ConditionalType)x.Type,
                            FieldValue = x.Value.Trim()
                        });
                    }
                });
                if (conModels.Count > 0)
                {
                    tempquery = tempquery.Where(conModels);
                }
            }
            var query = await tempquery.OrderBy(x => x.CreateTime, OrderByType.Desc)
                .ToPageListAsync(param.offset, param.limit, totalnum);
            return new PageParms<YB_MiniProgramsDraft>
            {
                page = param.offset,
                Items = query,
                totalnum = totalnum,
                limit = param.limit
            };
        }
        /// <summary>
        /// 更新公众号/小程序资料
        /// </summary>
        /// <param name="id">公众号ID</param>
        /// <returns></returns>
        public async Task<ResultInfo> GetInfo(int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "公众号未找到");
            }
            //获取基本信息
            var token = await ComponentContainer.TryGetComponentAccessTokenAsync(component_AppId, component_Secret);
            var result = await ComponentApi.GetAuthorizerInfoAsync(token, component_AppId, office.authorizer_appid);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            var authorization_info = result.authorization_info;
            var authorizer_info = result.authorizer_info;
            //更新公众号信息
            var servicetypeinfo = authorizer_info.service_type_info.id.ToString();
            var verifytypeinfo = authorizer_info.verify_type_info.id.ToString();
            var alias = authorizer_info.alias.ToStr();
            int type = authorizer_info.MiniProgramInfo != null ? 2 : 1;
            var funcinfo = string.Join(",", authorization_info.func_info.Select(x => x.funcscope_category.id.ToString()).ToArray());
            string head_img = authorizer_info.head_img.ToStr();
            await dbClient.Updateable<YB_OfficlaAccount>().SetColumns(x => new YB_OfficlaAccount
            {
                nick_name = authorizer_info.nick_name,
                head_img = head_img,
                service_type_info = servicetypeinfo,
                verify_type_info = verifytypeinfo,
                alias = alias,
                qrcode_url = authorizer_info.qrcode_url,
                type = type,
                func_info = funcinfo
            }).Where(x => x.Id == id).ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "资料更新成功");
        }

        /// <summary>
        /// 获取提交历史
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<PageParms<YB_MiniProgramHistory>> GetHistoryListAsync(QueryParams param)
        {
            RefAsync<int> totalnum = 0;
            var tempquery = dbClient.Queryable<YB_MiniProgramHistory>();
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(x =>
                {
                    if (!string.IsNullOrEmpty(x.Value))
                    {
                        conModels.Add(new ConditionalModel()
                        {
                            FieldName = x.Name,
                            ConditionalType = (ConditionalType)x.Type,
                            FieldValue = x.Value.Trim()
                        });
                    }
                });
                if (conModels.Count > 0)
                {
                    tempquery = tempquery.Where(conModels);
                }
            }
            var query = await tempquery.OrderBy(x => x.CreateTime, OrderByType.Desc)
                .ToPageListAsync(param.offset, param.limit, totalnum);
            return new PageParms<YB_MiniProgramHistory>
            {
                page = param.offset,
                Items = query,
                totalnum = totalnum,
                limit = param.limit
            };
        }

        /// <summary>
        /// 详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<YB_OfficlaAccount> DetailAsync(int id)
        {
            return await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id);
        }

        /// <summary>
        /// 同步代码模版列表
        /// </summary>
        /// <returns></returns>
        public async Task<ResultInfo> SyncTplAsync()
        {
            var token = await ComponentContainer.TryGetComponentAccessTokenAsync(component_AppId, component_Secret);
            var result = await CodeTemplateApi.GetTemplateListAsync(token);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            var list = result.template_list.Select(x => new YB_MiniProgramsTpl
            {
                TemplateId = x.template_id,
                CreateTime = x.create_time.ToDatetimeFromTimeStamp(),
                SyncTime = DateTime.Now,
                UserDesc = x.user_desc.ToStr(),
                UsrVersion = x.user_version.ToStr()
            }).ToList();
            //删除所有模版列表
            await dbClient.Deleteable<YB_MiniProgramsTpl>().ExecuteCommandAsync();
            //添加记录
            if (list.Count > 0)
            {
                await dbClient.Insertable(list).ExecuteCommandAsync();
            }
            return new ResultInfo(ResultState.SUCCESS, "同步完成");
        }

        /// <summary>
        /// 同步代码草稿列表
        /// </summary>
        /// <returns></returns>
        public async Task<ResultInfo> SyncDraftAsync()
        {
            var token = await ComponentContainer.TryGetComponentAccessTokenAsync(component_AppId, component_Secret);
            var result = await CodeTemplateApi.GetTemplateDraftListAsync(token);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            var list = result.draft_list.Select(x => new YB_MiniProgramsDraft
            {
                DraftId = x.draft_id,
                CreateTime = x.create_time.ToDatetimeFromTimeStamp(),
                SyncTime = DateTime.Now,
                UserDesc = x.user_desc.ToStr(),
                UserVersion = x.user_version.ToStr()
            }).ToList();

            //删除所有模版列表
            await dbClient.Deleteable<YB_MiniProgramsDraft>().ExecuteCommandAsync();
            //添加记录
            if (list.Count > 0)
            {
                await dbClient.Insertable<YB_MiniProgramsDraft>(list).ExecuteCommandAsync();
            }
            return new ResultInfo(ResultState.SUCCESS, "同步完成");
        }
        /// <summary>
        /// 将草稿箱的草稿选为小程序代码模版
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultInfo> AddToTEmplateAsync(int id)
        {
            var draft = await dbClient.Queryable<YB_MiniProgramsDraft>().Where(x => x.Id == id).FirstAsync();
            if (draft == null)
            {
                return new ResultInfo(ResultState.FAIL, "草稿未找到");
            }
            var token = await ComponentContainer.TryGetComponentAccessTokenAsync(component_AppId, component_Secret);
            var result = await CodeTemplateApi.AddToTemplateAsync(token, draft.DraftId);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            //重新同步模版
            var results = await SyncTplAsync();
            if (results.code != ResultState.SUCCESS)
            {
                return new ResultInfo(ResultState.FAIL, results.message);
            }
            return new ResultInfo(ResultState.SUCCESS, "设置成功");
        }

        /// <summary>
        /// 删除模版
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultInfo> DeleteTemplateAsync(int id)
        {
            var draft = await dbClient.Queryable<YB_MiniProgramsTpl>().Where(x => x.Id == id).FirstAsync();
            if (draft == null)
            {
                return new ResultInfo(ResultState.FAIL, "模版未找到");
            }
            var token = await ComponentContainer.TryGetComponentAccessTokenAsync(component_AppId, component_Secret);
            var result = await CodeTemplateApi.DeleteTemplateAsync(token, draft.TemplateId);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            //删除模版
            await dbClient.Deleteable<YB_MiniProgramsTpl>().Where(x => x.Id == id).ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "删除成功");
        }

        /// <summary>
        /// 为授权的小程序帐号上传小程序代码
        /// </summary>
        /// <param name="templateid">模版ID</param>
        /// <param name="id">小程序id</param>
        /// <returns></returns>
        public async Task<ResultInfo> CommitAsync(int templateid, int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id && x.type == 2);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            var template = await dbClient.Queryable<YB_MiniProgramsTpl>().FirstAsync(x => x.Id == templateid);
            if (template == null)
            {
                return new ResultInfo(ResultState.FAIL, "模版未找到");
            }
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            var json = new
            {
                extAppid = office.authorizer_appid,
                extEnable = true,
                ext = new
                {
                    appid = office.authorizer_appid,
                    name = office.nick_name
                }
            };
            string ext_json = json.ToJson();
            var result = await CodeApi.CommitAsync(token, template.TemplateId, ext_json, template.UsrVersion, template.UserDesc);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            //记录上传记录
            await dbClient.Insertable<YB_MiniProgramHistory>(new YB_MiniProgramHistory
            {
                appid = office.authorizer_appid,
                UserDesc = template.UserDesc,
                UserVersion = template.UsrVersion,
                Status = -1,//代码已上传
                ScreenShot = "",
                StatusRemark = "",
                auditid = "",
                CreateTime = DateTime.Now
            }).ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "上传成功");
        }

        /// <summary>
        /// 获取最新的提交历史状态
        /// </summary>
        /// <param name="id">小程序id</param>
        /// <returns></returns>
        public async Task<YB_MiniProgramHistory> GetLastCommitStatusAsync(int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().Where(x => x.Id == id).FirstAsync();
            return await dbClient.Queryable<YB_MiniProgramHistory>().Where(x => x.appid == office.authorizer_appid)
                .OrderBy(x => x.CreateTime, OrderByType.Desc)
                .FirstAsync();
        }


        /// <summary>
        /// 获取小程序的体验二维码
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultInfo> GetQRCodeAsync(int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id && x.type == 2);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            string savefolder = _hostingEnvironment.WebRootPath;
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            var rootname = "/qrcode";
            var filepath = Path.Combine($"wwwroot/{rootname}/", $"{office.authorizer_appid}.jpg");
            var virualpath = Path.Combine($"{rootname}/", $"{office.authorizer_appid}.jpg");
            savefolder = $"{savefolder}{rootname}";
            if (!Directory.Exists(savefolder))
            {
                Directory.CreateDirectory(savefolder);
            }
            using (Stream stream = File.Create(filepath))
            {
                var result = await CodeApi.GetQRCodeAsync(token, stream);
                if (result.errcode != 0)
                {
                    return new ResultInfo(ResultState.FAIL, result.errmsg);
                }
            }
            return new ResultInfo(ResultState.SUCCESS, "success", virualpath);
        }

        /// <summary>
        /// 获取小程序的第三方提交代码的页面配置
        /// </summary>
        /// <param name="appid"></param>
        /// <returns></returns>
        public async Task<ResultInfo> GetPageAsync(string appid)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.authorizer_appid == appid && x.type == 2);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            var result = await CodeApi.GetPageAsync(token);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            return new ResultInfo(ResultState.SUCCESS, "success", result.page_list);
        }

        /// <summary>
        /// 查询最新一次提交的审核状态
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultInfo> GetLatestAuditStatusAsync(int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id && x.type == 2);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            //是否有提交记录
            var data = await dbClient.Queryable<YB_MiniProgramHistory>().Where(x => x.appid == office.authorizer_appid).OrderBy(x => x.CreateTime, OrderByType.Desc).FirstAsync();
            if (data == null)
            {
                return new ResultInfo(ResultState.FAIL, "未找到提交的版本");
            }
            if (string.IsNullOrEmpty(data.auditid))
            {
                return new ResultInfo(ResultState.FAIL, "请先提交审核");
            }
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            long auditid = data.auditid.ToLong();
            var result = await CodeApi.GetAuditStatusAsync(token, auditid);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            //更新审核状态
            var errmsg = LatestAuditStatusErrmsg(result);
            await dbClient.Updateable<YB_MiniProgramHistory>().SetColumns(x => new YB_MiniProgramHistory
            {
                Status = result.status,
                ScreenShot = result.screenshot.ToStr(),
                StatusRemark = errmsg
            }).Where(x => x.Id == data.Id).ExecuteCommandAsync();
            if (result.status == 0)
            {
                return new ResultInfo(ResultState.SUCCESS, "审核成功");
            }
            return new ResultInfo(ResultState.FAIL, errmsg);
        }
        /// <summary>
        /// 审核状态描述
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        private string LatestAuditStatusErrmsg(GetAuditResultJson result)
            => (result) switch
            {
                _ when result.status == -1 => "代码已提交",
                _ when result.status == 0 => "审核成功",
                _ when result.status == 1 => result.reason,
                _ when result.status == 2 => "审核中",
                _ when result.status == 3 => "已撤回",
                _ => result.reason
            };


        /// <summary>
        /// 将第三方提交的代码包提交审核,注意：只有上个版本被驳回，才能使用 feedback_info、feedback_stuff 这两个字段，否则忽略处理。
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultInfo> SubmitAuditAsync(int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id && x.type == 2);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            var hdata = await dbClient.Queryable<YB_MiniProgramHistory>().Where(x => x.appid == office.authorizer_appid).OrderBy(x => x.CreateTime, OrderByType.Desc).FirstAsync();
            if (hdata == null)
            {
                return new ResultInfo(ResultState.FAIL, "未找到可用的版本");
            }
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            var result = await CodeApi.SubmitAuditAsync(token, null, null);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            //更新提交记录
            var msg = LatestAuditStatusErrmsg(result);
            await dbClient.Updateable<YB_MiniProgramHistory>().SetColumns(x => new YB_MiniProgramHistory
            {
                Status = 2,
                StatusRemark = msg,
                auditid = result.auditid
            }).Where(x => x.Id == hdata.Id).ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "成功提交审核");
        }

        /// <summary>
        /// 修改域名
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultInfo> ModifyDomainAsync(int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id && x.type == 2);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            var wxurl = Configs.GetString("APIURL");
            var cdnurl = Configs.GetString("CDNURL");
            var urlList = new List<string> { wxurl, cdnurl };
            if (office.authorizer_appid == "wx92a348ac13ae62fb" || office.authorizer_appid == "wxe8f20809156a2e3c")
            {
                urlList.Add(@"https://ttybapi.ybhdmob.com");
            }
            var uploadlist = urlList;
            var downlist = urlList;
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            var result1 = await ModifyDomainApi.ModifyDomainAsync(token, ModifyDomainAction.get, null, null, null, null);
            if (result1.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result1.errmsg);
            }
            result1.requestdomain.ForEach(x =>
            {
                x = x.ToLower();
                if (urlList.Contains(x))
                {
                    urlList.Remove(x);
                }
            });
            result1.uploaddomain.ForEach(x =>
            {
                x = x.ToLower();
                if (uploadlist.Contains(x))
                {
                    uploadlist.Remove(x);
                }
            });
            result1.downloaddomain.ForEach(x =>
            {
                x = x.ToLower();
                if (downlist.Contains(x))
                {
                    downlist.Remove(x);
                }
            });
            if (urlList.Count == 0 && uploadlist.Count == 0 && downlist.Count == 0)
            {
                return new ResultInfo(ResultState.FAIL, "没有可增加的域名");
            }
            if (urlList.Count == 0)
            {
                urlList = null;
            }
            if (uploadlist.Count == 0)
            {
                uploadlist = null;
            }
            if (downlist.Count == 0)
            {
                downlist = null;
            }
            var result = await ModifyDomainApi.ModifyDomainAsync(token, ModifyDomainAction.add, urlList, null, uploadlist, downlist);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg, new
                {
                    urllist = urlList,
                    uploadlist = uploadlist,
                    downlist = downlist
                });
            }
            return new ResultInfo(ResultState.SUCCESS, "域名修改成功");
        }
        /// <summary>
        /// 获取域名列表
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultInfo> GetDomainAsync(int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id && x.type == 2);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            var result = await ModifyDomainApi.ModifyDomainAsync(token, ModifyDomainAction.get, null, null, null, null);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            return new ResultInfo(ResultState.SUCCESS, "success", new
            {
                requestdomain = result.requestdomain,
                wsrequestdomain = result.wsrequestdomain,
                uploaddomain = result.uploaddomain,
                downloaddomain = result.downloaddomain
            });
        }

        /// <summary>
        /// 小程序审核撤回，注意：单个帐号每天审核撤回次数最多不超过 1 次，一个月不超过 10 次
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultInfo> UndoCodeAuditAsync(int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id && x.type == 2);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            var result = await CodeApi.UndoCodeAuditAsync(token);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            return new ResultInfo(ResultState.SUCCESS, "撤回成功");
        }
        /// <summary>
        /// 发布已通过审核的小程序
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultInfo> ReleaseAsync(int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>()
                .Select(x => new YB_OfficlaAccount
                {
                    Id = x.Id,
                    authorizer_appid = x.authorizer_appid
                })
                .FirstAsync(x => x.Id == id && x.type == 2);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            var hdata = await dbClient.Queryable<YB_MiniProgramHistory>().Where(x => x.appid == office.authorizer_appid).OrderBy(x => x.CreateTime, OrderByType.Desc).FirstAsync();
            if (hdata == null)
            {
                return new ResultInfo(ResultState.FAIL, "未找到可用的版本");
            }
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            var result = await CodeApi.ReleaseAsync(token);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            // 更新最新状态
            await dbClient.Updateable<YB_MiniProgramHistory>().SetColumns(x => new YB_MiniProgramHistory
            {
                Status = 5,
                StatusRemark = "已发布",
            }).Where(x => x.Id == hdata.Id).ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "发布成功");
        }
        /// <summary>
        /// 修改小程序线上代码的可见状态
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        public async Task<ResultInfo> ChangeVisitStatusAsync(string appid, int status = 1)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.authorizer_appid == appid && x.type == 2);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            ChangVisitStatusAction action = status == 1 ? ChangVisitStatusAction.open : ChangVisitStatusAction.close;
            var result = await CodeApi.ChangeVisitStatusAsync(token, action);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            return new ResultInfo(ResultState.SUCCESS, status == 1 ? "版本已开启" : "版本已关闭");
        }
        /// <summary>
        /// 查询提交状态
        /// </summary>
        /// <param name="id">提交的状态记录id</param>
        /// <returns></returns>
        public async Task<ResultInfo> GetCommitStatusAsync(int id)
        {
            //是否有提交记录
            var data = await dbClient.Queryable<YB_MiniProgramHistory>().Where(x => x.Id == id).FirstAsync();
            if (data == null)
            {
                return new ResultInfo(ResultState.FAIL, "未找到提交的版本");
            }
            if (string.IsNullOrEmpty(data.auditid))
            {
                return new ResultInfo(ResultState.FAIL, "请先提交审核");
            }
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.authorizer_appid == data.appid && x.type == 2);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            long auditid = data.auditid.ToLong();
            var result = await CodeApi.GetAuditStatusAsync(token, auditid);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            //更新审核状态
            var errmsg = LatestAuditStatusErrmsg(result);
            await dbClient.Updateable<YB_MiniProgramHistory>().SetColumns(x => new YB_MiniProgramHistory
            {
                Status = result.status,
                ScreenShot = result.screenshot.ToStr(),
                StatusRemark = errmsg
            }).Where(x => x.Id == data.Id).ExecuteCommandAsync();
            if (result.status == 0)
            {
                return new ResultInfo(ResultState.SUCCESS, "审核成功");
            }
            return new ResultInfo(ResultState.FAIL, errmsg);
        }
        /// <summary>
        /// 获取所有公众号列表
        /// </summary>
        /// <param name="type">0-全部,1-公众号,2-小程序</param>
        /// <returns></returns>
        public async Task<List<YB_OfficlaAccount>> GetAllListAsync(int type = 1)
        {
            var temquery = dbClient.Queryable<YB_OfficlaAccount, YB_BusinessOffice>((s, c) => new JoinQueryInfos(JoinType.Left, s.authorizer_appid == c.AppId)).Where((s, c) => s.isauthorize == 1);
            if (currentUser.AccountType != Entity.AccountType.platform)
            {
                temquery = temquery.Where((s, c) => c.BusinessId == currentUser.BusinessId);
            }
            if (type > 0)
            {
                temquery = temquery.Where((s, c) => s.type == type);
            }
            var query = await temquery.OrderBy((s, c) => s.lastmodifytime, OrderByType.Desc)
                .Select((s, c) => new YB_OfficlaAccount
                {
                    nick_name = s.nick_name,
                    authorizer_appid = s.authorizer_appid
                })
                 .ToListAsync();
            return query;
        }
        /// <summary>
        /// 手动增加公众号/小程序
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<ResultInfo> SubmitFormAsync(YB_OfficlaAccount data)
        {
            if (await dbClient.Queryable<YB_BusinessOffice>().AnyAsync(x => data.authorizer_appid == x.AppId))
            {
                return new ResultInfo(ResultState.FAIL, "此appid已存在");
            }
            data.componentappid = "";
            data.authorizer_access_token = "";
            data.authorizer_refresh_token = "";
            data.alias = "";
            data.service_type_info = data.type == 2 ? "小程序" : "未授权号";
            data.verify_type_info = "";
            data.verify_type_info = "";
            data.qrcode_url = data.head_img;
            data.isauthorize = 1;
            data.lastmodifytime = DateTime.Now;
            data.authorizeationcode = "";
            data.func_info = "";
            data.createtime = DateTime.Now;
            await dbClient.Insertable(data).ExecuteCommandAsync();
            if (currentUser.AccountType != Entity.AccountType.platform)
            {
                await dbClient.Insertable(new YB_BusinessOffice
                {
                    AppId = data.authorizer_appid,
                    BusinessId = currentUser.BusinessId,
                    CreateTime = DateTime.Now
                }).ExecuteCommandAsync();
            }
            return new ResultInfo(ResultState.SUCCESS, "添加成功");
        }
        /// <summary>
        /// 获取小程序订阅模板
        /// </summary>
        /// <param name="param"></param>
        /// <param name="id">小程序id</param>
        /// <returns></returns>
        public async Task<ResultInfo> GetSubscribeTplListAsync(int id, QueryParams param)
        {
            RefAsync<int> totalnum = 0;
            var temquery = dbClient.Queryable<YB_MiniProgramSubscribeMessageTpl>();
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id);
            temquery = temquery.Where(x => x.AppId == office.authorizer_appid);
            if (param.queryParam != null && param.queryParam.Count > 0)
            {
                List<IConditionalModel> conModels = new List<IConditionalModel>();
                param.queryParam.ForEach(x =>
                {
                    if (!string.IsNullOrEmpty(x.Value))
                    {
                        conModels.Add(new ConditionalModel()
                        {
                            FieldName = x.Name,
                            ConditionalType = (ConditionalType)x.Type,
                            FieldValue = x.Value.ToStr()
                        });
                    }
                });
                if (conModels.Count > 0)
                {
                    temquery = temquery.Where(conModels);
                }
            }
            string sorts = string.Format("{0} {1}", param.sort, param.order);
            var query = await temquery.OrderBy(sorts)
                .Select(x => new MiniSubscribeTplS2CDto
                {
                    Example = x.Example,
                    IsSelected = x.IsSelected,
                    Id = x.Id,
                    KeyWords = x.KeyWords,
                    PriTmplId = x.PriTmplId,
                    Title = x.Title,
                    Type = x.Type
                })
                .ToPageListAsync(param.offset, param.limit, totalnum);
            var result = new PageParms<MiniSubscribeTplS2CDto>
            {
                page = param.offset,
                Items = query,
                totalnum = totalnum,
                limit = param.limit
            };
            return new ResultInfo(ResultState.SUCCESS, "success", result);
        }

        /// <summary>
        /// 获取当前账号下的个人模板列表
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultInfo> GetTemplateListAsync(int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            var token = await AuthorizerContainer.TryGetAuthorizerAccessTokenAsync(component_AppId, office.authorizer_appid);
            var result = await Senparc.Weixin.Open.WxaAPIs.NewTmpl.NewTmplApi.GetTemplateListAsync(token);
            if (result.errcode != 0)
            {
                return new ResultInfo(ResultState.FAIL, result.errmsg);
            }
            var list = result.data;
            if (list == null || list.Count == 0)
            {
                return new ResultInfo(ResultState.FAIL, "未找到可用的模板");
            }
            //添加记录
            var insertlist = new List<YB_MiniProgramSubscribeMessageTpl>();
            list.ForEach(x =>
            {
                string keywords = GetSubscribeTplKeyWords(x.content);
                string content = GetSubscribeTplTitles(x.content);
                insertlist.Add(new YB_MiniProgramSubscribeMessageTpl
                {
                    AppId = office.authorizer_appid,
                    Id = _idGenerator.Create().ToGuid(),
                    Content = content,
                    IsSelected = false,
                    CreateTime = DateTime.Now,
                    Example = "",
                    Title = x.title,
                    Type = x.type,
                    PriTmplId = x.priTmplId,
                    KeyWords = keywords
                });
            });
            await dbClient.Deleteable<YB_MiniProgramSubscribeMessageTpl>()
                .Where(x => x.AppId == office.authorizer_appid)
                .ExecuteCommandAsync();
            if (insertlist.Count > 0)
            {
                await dbClient.Insertable(insertlist).ExecuteCommandAsync();
            }
            return new ResultInfo(ResultState.SUCCESS, "同步成功");
        }
        /// <summary>
        /// 获取模板内容的关键字列表
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        private string GetSubscribeTplKeyWords(string val)
        {
            var reg = new Regex(@"[\w.]+[DATA]");
            var mathes = reg.Matches(val).AsQueryable();
            string str = string.Empty;
            foreach (var item in mathes)
            {
                str += item.ToString().Replace(".DATA", "") + "|";
            }
            str = str.Substring(0, str.Length - 1);
            return str;
        }
        /// <summary>
        /// 获取模板内容的标题列表
        /// </summary>
        static string GetSubscribeTplTitles(string val)
        {
            var reg = new Regex(@"[\w]+[:{]");
            var mathes = reg.Matches(val).AsQueryable();
            string str = string.Empty;
            foreach (var item in mathes)
            {
                str += item.ToString().Replace(":", "") + "|";
            }
            str = str.Substring(0, str.Length - 1);
            return str;
        }
        /// <summary>
        /// 选中模板
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<ResultInfo> SetTplAsMessageAsync(SubscribeTplStatusC2SDto data)
        {
            var currentData = await dbClient.Queryable<YB_MiniProgramSubscribeMessageTpl>()
                .Where(x => x.Id == data.Id)
                .Select(x => new YB_MiniProgramSubscribeMessageTpl
                {
                    AppId = x.AppId
                })
                .FirstAsync();
            if (currentData == null)
            {
                return new ResultInfo(ResultState.FAIL, "模板未找到");
            }
            if (data.IsSelected)
            {
                await dbClient.Updateable<YB_MiniProgramSubscribeMessageTpl>().SetColumns(x => new YB_MiniProgramSubscribeMessageTpl
                {
                    IsSelected = false
                }).Where(x => x.AppId == currentData.AppId && x.IsSelected).ExecuteCommandAsync();
            }
            await dbClient.Updateable<YB_MiniProgramSubscribeMessageTpl>().SetColumns(x => new YB_MiniProgramSubscribeMessageTpl
            {
                IsSelected = data.IsSelected
            }).Where(x => x.Id == data.Id).ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "模板设置成功");
        }
        /// <summary>
        /// 获取小程序订阅模板详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<YB_MiniProgramSubscribeMessageTpl> GetSubscribeTplDetailAsync(Guid id)
        {
            var result = await dbClient.Queryable<YB_MiniProgramSubscribeMessageTpl>().Where(x => x.Id == id).Select(x => new YB_MiniProgramSubscribeMessageTpl
            {
                Id = x.Id,
                Example = x.Example,
                IsSelected = x.IsSelected,
                KeyWords = x.KeyWords,
                PriTmplId = x.PriTmplId,
                Title = x.Title,
                Type = x.Type,
                Content = x.Content
            }).FirstAsync();
            return result;
        }
        /// <summary>
        /// 设置订阅消息模板内容
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<ResultInfo> SetSubscribeTplContentAsync(SubscribeTplContentC2SDto data)
        {
            if (!await dbClient.Queryable<YB_MiniProgramSubscribeMessageTpl>()
               .AnyAsync(x => x.Id == data.Id))
            {
                return new ResultInfo(ResultState.FAIL, "模板未找到");
            }
            await dbClient.Updateable<YB_MiniProgramSubscribeMessageTpl>().SetColumns(x => new YB_MiniProgramSubscribeMessageTpl
            {
                Example = data.Content
            }).Where(x => x.Id == data.Id).ExecuteCommandAsync();
            return new ResultInfo(ResultState.SUCCESS, "内容设置成功");
        }
        /// <summary>
        /// 微信客服设置
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<ResultInfo> SetCustomServiceAsync(CustomServiceC2SDto data)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == data.Id);
            if (office == null)
            {
                return new ResultInfo(ResultState.FAIL, "小程序未找到");
            }
            if (await dbClient.Queryable<YB_WXCustomService>().AnyAsync(x => x.AppId == office.authorizer_appid))
            {
                await dbClient.Updateable<YB_WXCustomService>().SetColumns(x => new YB_WXCustomService
                {
                    QyAppId = data.QyAppId,
                    Url = data.Url
                }).Where(x => x.AppId == office.authorizer_appid).ExecuteCommandAsync();
            }
            else
            {
                var insertdata = new YB_WXCustomService
                {
                    Id = IDGen.NextID(),
                    AppId = office.authorizer_appid,
                    CreateTime = DateTime.Now,
                    QyAppId = data.QyAppId,
                    Url = data.Url
                };
                await dbClient.Insertable(insertdata).ExecuteCommandAsync();
            }
            return new ResultInfo(ResultState.SUCCESS, "客服设置成功");
        }
        /// <summary>
        /// 获取微信客服详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<CustomServiceC2SDto> GetCustomServiceAsync(int id)
        {
            var office = await dbClient.Queryable<YB_OfficlaAccount>().FirstAsync(x => x.Id == id);
            return await dbClient.Queryable<YB_WXCustomService>().Where(x => x.AppId == office.authorizer_appid).Select(x => new CustomServiceC2SDto
            {
                Id = id,
                QyAppId = x.QyAppId,
                Url = x.Url
            }).FirstAsync();
        }
    }
}
