using Nirvana.Common;
using Nirvana.Common.ApiBase;
using Nirvana.Data;
using Senparc.Weixin;
using Senparc.Weixin.Open.WxaAPIs.Sns;
using Senparc.Weixin.WxOpen.Containers;
using Senparc.Weixin.WxOpen.Entities;
using Senparc.Weixin.WxOpen.Helpers;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using YBDevice.Entity;

namespace YBDevice.Api.DBServices
{
    /// <summary>
    /// 小程序管理
    /// </summary>
    public partial class WxOpenApp : BaseApp
    {
        public static readonly string Component_Token = Senparc.Weixin.Config.SenparcWeixinSetting.Component_Token;
        public static readonly string Component_EncodingAESKey = Senparc.Weixin.Config.SenparcWeixinSetting.Component_EncodingAESKey;
        public static readonly string Component_Appid = Senparc.Weixin.Config.SenparcWeixinSetting.Component_Appid;
        public static readonly string Component_Secret = Senparc.Weixin.Config.SenparcWeixinSetting.Component_Secret;

        /// <summary>
        /// 小程序登录
        /// </summary>
        /// <returns></returns>
        public async Task<ResultInfo> OnLoginAsync(WXOpenLoginSubmitModel model)
        {
            using (var dbClient = ReadDbContext.GetInstance())
            {
                //检查小程序是否已授权
                if (!await dbClient.Queryable<YB_OfficlaAccount>().AnyAsync(x => x.authorizer_appid == model.appid && x.isauthorize == 1))
                {
                    return new ResultInfo(ResultState.FAIL, "此小程序还未授权");
                }
                var jsonResult = await SnsApi.JsCode2JsonAsync(model.appid, Component_Appid, Component_Secret, model.code);
                if (jsonResult.errcode == ReturnCode.请求成功)
                {
                    //得到openid,检查是否绑定有账号,如果有绑定则返回token,否则返回sessionid
                    var openid = jsonResult.openid;
                    if (await dbClient.Queryable<YB_UserWX>().AnyAsync(x => x.openid == openid))
                    {
                        var userwx = await dbClient.Queryable<YB_UserWX>().Where(x => x.openid == openid).FirstAsync();
                        //生成token
                        var token = Token(new WebApiOperaModel
                        {
                            UserId = userwx.UserId
                        });
                        return new ResultInfo(ResultState.SUCCESS, "登录成功", token);
                    }
                    //记录信息
                    var sessionBag = await SessionContainer.UpdateSessionAsync(null, jsonResult.openid, jsonResult.session_key, jsonResult.unionid);
                    return new ResultInfo(ResultState.SUCCESS, "success", new WxOpenLoginData
                    {
                        sessionid = sessionBag.Key
                    });
                }
                return new ResultInfo(ResultState.FAIL, jsonResult.errmsg);
            }
        }

        /// <summary>
        /// 解密用户资料,如果未注册则自动进行注册,否则更新资料
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<ResultInfo> DecryptDataAsync(WxOpenDecryptSubmitModel model)
        {
            using (var dbClient = ReadDbContext.GetInstance())
            {
                DecodeEntityBase decodedEntity = null;
                DecodedUserInfo userinfo = null;
                userinfo = EncryptHelper.DecodeUserInfoBySessionId(
                           model.sessionId,
                           model.encryptedData, model.iv);
                decodedEntity = userinfo;
                //检验水印
                var checkWartmark = false;
                if (decodedEntity != null)
                {
                    checkWartmark = decodedEntity.CheckWatermark(model.sessionId);
                }
                if (!checkWartmark)
                {
                    return new ResultInfo(ResultState.FAIL, "水印验证不通过");
                }
                var sessionbage = await SessionContainer.GetSessionAsync(model.sessionId);
                if (sessionbage == null)
                {
                    return new ResultInfo(ResultState.FAIL, "登录信息已过期");
                }
                //检查此openid是否已绑定用户
                if (!await dbClient.Queryable<YB_UserWX>().AnyAsync(x => x.openid == sessionbage.OpenId))
                {
                    //未注册自动注册
                    var userid = await dbClient.Insertable<YB_RegUser>(new YB_RegUser
                    {
                        Secret = "",
                        Status = 1,
                        CreateTime = DateTime.Now,
                        Headimg = userinfo.avatarUrl.ToStr(),
                        LastVisitIP = Net.Ip,
                        LastVisitTime = DateTime.Now,
                        Name = userinfo.nickName.ToStr(),
                        Password = "",
                        Phone = "",
                        City = userinfo.city.ToStr(),
                        Country = userinfo.country.ToStr(),
                        Gender = userinfo.gender,
                        Province = userinfo.province.ToStr(),
                        UnionId = userinfo.unionId.ToStr()
                    }).ExecuteReturnIdentityAsync();

                    //增加微信绑定记录
                    await dbClient.Insertable<YB_UserWX>(new YB_UserWX
                    {
                        createtime = DateTime.Now,
                        openid = userinfo.openId.ToStr(),
                        unionid = userinfo.unionId.ToStr(),
                        UserId = userid
                    }).ExecuteCommandAsync();
                    //增加一条为自己的家庭成员
                    var birthday = DateTime.Now.AddYears(-18).Date;
                    var family = new YB_Family
                    {
                        Type = (int)FamilyType.Adult,
                        Age = 18,
                        Birthday = birthday,
                        Sex = userinfo.gender,
                        IsSelf = 1,
                        Status = 1,
                        Createtime = DateTime.Now,
                        Height = 175,
                        Name = userinfo.nickName,
                        UserId = userid,
                        Weight = 60
                    };
                    await dbClient.Insertable<YB_Family>(family).ExecuteCommandAsync();
                    var token = Token(new WebApiOperaModel
                    {
                        UserId = userid
                    });
                    return new ResultInfo(ResultState.SUCCESS, "注册成功", token);
                }
                else
                {
                    var userwx = await dbClient.Queryable<YB_UserWX>().Where(x => x.openid == sessionbage.OpenId).OrderBy(x => x.createtime, OrderByType.Desc).FirstAsync();
                    var user = await dbClient.Queryable<YB_RegUser>().Where(x => x.Id == userwx.UserId).FirstAsync();
                    if (user == null)
                    {
                        return new ResultInfo(ResultState.FAIL, "用户未找到");
                    }
                    //更新登录时间,以及最新的资料
                    await dbClient.Updateable<YB_RegUser>().SetColumns(x => new YB_RegUser
                    {
                        LastVisitIP = Net.Ip,
                        LastVisitTime = DateTime.Now,
                        Country = userinfo.country.ToStr(),
                        Gender = userinfo.gender,
                        Province = userinfo.province.ToStr(),
                        City = userinfo.city.ToStr(),
                        Headimg = userinfo.avatarUrl.ToStr(),
                        UnionId = userinfo.unionId.ToStr()
                    }).ExecuteCommandAsync();
                    var token = Token(new WebApiOperaModel
                    {
                        UserId = user.Id
                    });
                    return new ResultInfo(ResultState.SUCCESS, "登录成功", token);
                }
            }
        }

        /// <summary>
        /// 手机号授权,如果未注册会自动进行注册
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<ResultInfo> DecryptPhoneAsync(WxOpenDecryptSubmitModel model)
        {
            using (var dbClient = ReadDbContext.GetInstance())
            {
                var sessionBag = await SessionContainer.GetSessionAsync(model.sessionId);
                if (sessionBag == null)
                {
                    return new ResultInfo(ResultState.FAIL, "sessionId未找到");
                }
                var phone = EncryptHelper.DecryptPhoneNumber(model.sessionId, model.encryptedData, model.iv);
                var user = await dbClient.Queryable<YB_RegUser>().Where(x => x.Phone == phone.phoneNumber).FirstAsync();
                //检查此手机号是否已注册
                if (user != null)
                {
                    //如果未绑定此openid,则增加一条记录
                    if (!await dbClient.Queryable<YB_UserWX>().AnyAsync(x => x.openid == sessionBag.OpenId && x.UserId == user.Id))
                    {
                        await dbClient.Insertable<YB_UserWX>(new YB_UserWX
                        {
                            createtime = DateTime.Now,
                            openid = sessionBag.OpenId,
                            unionid = sessionBag.UnionId.ToStr(),
                            UserId = user.Id
                        }).ExecuteCommandAsync();
                    }
                    var token = Token(new WebApiOperaModel
                    {
                        UserId = user.Id
                    });
                    return new ResultInfo(ResultState.SUCCESS, "登录成功", token);
                }
                else
                {
                    //自动进行注册
                    var userid = await dbClient.Insertable<YB_RegUser>(new YB_RegUser
                    {
                        CreateTime = DateTime.Now,
                        Secret = "",
                        Status = 1,
                        Headimg = "",
                        LastVisitIP = Net.Ip,
                        LastVisitTime = DateTime.Now,
                        Name = phone.phoneNumber,
                        Password = "",
                        Phone = phone.phoneNumber
                    }).ExecuteReturnIdentityAsync();

                    //增加微信绑定记录
                    await dbClient.Insertable<YB_UserWX>(new YB_UserWX
                    {
                        createtime = DateTime.Now,
                        openid = sessionBag.OpenId,
                        unionid = sessionBag.UnionId.ToStr(),
                        UserId = userid
                    }).ExecuteCommandAsync();
                    var token = Token(new WebApiOperaModel
                    {
                        UserId = userid
                    });
                    return new ResultInfo(ResultState.SUCCESS, "注册成功", token);
                }
            }
        }
        /// <summary>
        /// 检查登录状态
        /// </summary>
        /// <param name="sessionId"></param>
        /// <returns></returns>
        public async Task<ResultInfo> CheckLoginAsync(string sessionId)
        {
            using (var dbClient = ReadDbContext.GetInstance())
            {
                var sessionBag = await SessionContainer.GetSessionAsync(sessionId);
                if (sessionBag == null)
                {
                    return new ResultInfo(ResultState.FAIL, "sessionId已失效");
                }
                var user = await dbClient.Queryable<YB_UserWX>().Where(x => x.openid == sessionBag.OpenId).FirstAsync();
                if (user == null)
                {
                    return new ResultInfo(ResultState.FAIL, "此微信还未绑定");
                }
                if (!await dbClient.Queryable<YB_RegUser>().AnyAsync(x => x.Id == user.UserId))
                {
                    return new ResultInfo(ResultState.FAIL, "用户未找到");
                }
                var token = Token(new WebApiOperaModel
                {
                    UserId = user.UserId
                });
                return new ResultInfo(ResultState.SUCCESS, "登录成功", token);
            }
        }
    }
}
