using HiTeachCC.Library.Common;
using HiTeachCC.Model.Core.Dtos;
using HiTeachCC.Model.Core.Models;
using HiTeachCC.Service.Core.Interface;
using IdentityModel;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using TEAMModelOS.SDK.Context.Configuration;
using TEAMModelOS.SDK.Context.Constant.Common;
using TEAMModelOS.SDK.Context.Exception;
using TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest;
using TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse;
using TEAMModelOS.SDK.Extension.HttpClient.Implements;
using TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper;
using TEAMModelOS.SDK.Extension.JwtAuth.Models;
using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
using TEAMModelOS.SDK.Helper.Common.JsonHelper;
using TEAMModelOS.SDK.Helper.Network.HttpHelper;
using TEAMModelOS.SDK.Helper.Security.BCryptHelper;

namespace HiTeachCC.Service.Core.Implement
{
    public class LoginInfoService : BaseService, ILoginInfoService
    {
        private readonly HttpClientUserInfo _httpClientService;
        private readonly IHttpContextAccessor httpContextAccessor;

        public LoginInfoService(HttpClientUserInfo httpClientUserInfo, IHttpContextAccessor _httpContextAccessor)
        {
            _httpClientService = httpClientUserInfo;
            httpContextAccessor = _httpContextAccessor;
        }
        public async Task<object> VerifyWeChat(Dictionary<string, object> dict)
        {
            if (dict.TryGetValue("code", out object code))
            {
                WeChatToken oauth2Token = await GetWeChatAccessToken(code != null ? code.ToString() : "");
                oauth2Token.RowKey = oauth2Token.access_token;
                oauth2Token.PartitionKey = "WeChatOauth2Token";
                oauth2Token = await SaveOrUpdate<WeChatToken>(oauth2Token);


            }
            return null;
        }
        /// <summary>
        /// 获取微信AccessToken
        /// </summary>
        /// <param name="Code"></param>
        /// <returns></returns>
        private async Task<WeChatToken> GetWeChatAccessTokenClient()
        {

            string requestUrl = BaseConfigModel.Configuration["HaBookAuth:WeChatAccessTokenUrlClient"] + "appid={{APPID}}&secret={{SECRET}}&code={{CODE}}&grant_type=client_credential";
            requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppID"]);
            requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppSecret"]);
            string info = await HttpHelper.HttpGetAsync(requestUrl);
            return MessagePackHelper.JsonToObject<WeChatToken>(info);
        }


        /// <summary>
        /// 获取微信AccessToken
        /// </summary>
        /// <param name="Code"></param>
        /// <returns></returns>
        private async Task<WeChatToken> GetWeChatAccessToken(string Code)
        {
            if (string.IsNullOrEmpty(Code))
            {
                return null;
            }
            string requestUrl = BaseConfigModel.Configuration["HaBookAuth:WeChatAccessTokenUrlCode"] + "appid={{APPID}}&secret={{SECRET}}&code={{CODE}}&grant_type=authorization_code";
            requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppID"]);
            requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppSecret"]);
            requestUrl = requestUrl.Replace("{{CODE}}", Code);
            string info = await HttpHelper.HttpGetAsync(requestUrl);
            return MessagePackHelper.JsonToObject<WeChatToken>(info);
        }

        /// <summary>
        /// 获取微信登录跳转链接
        /// </summary>
        /// <param name="time">13位时间戳</param>
        /// <returns></returns>
        public Dictionary<string, object> GetWechatConfig(string Time)
        {
            Dictionary<string, object> config = new Dictionary<string, object>();
            config.Add("WeChatAuthorizeUrlCode", BaseConfigModel.Configuration["HaBookAuth:WeChatAuthorizeUrlCode"] + "?appid=" + BaseConfigModel.Configuration["HaBookAuth:WeChatAppID"] + "&redirect_uri={{redirect_uri}}&response_type=code&scope=snsapi_userinfo&state=" + Time + "#wechat_redirect");
            return config;
        }

        public async Task<MiniAPPLoginInfo> VerifyMiniAPP(Dictionary<string, object> dict)
        {
            MiniAPPLoginInfo loginInfo = null;
            if (dict.TryGetValue("js_code", out object js_code))
            {
                if (string.IsNullOrEmpty(js_code != null ? js_code.ToString() : ""))
                {
                    throw new Exception("Validation failure , js_code is null!");
                }
                string requestUrl = BaseConfigModel.Configuration["HaBookAuth:MiniAPPAuthUrl"];
                requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPID"]);
                requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPSECRET"]);
                requestUrl = requestUrl.Replace("{{JSCODE}}", js_code.ToString());
                string info = await HttpHelper.HttpGetAsync(requestUrl);
                loginInfo = MessagePackHelper.JsonToObject<MiniAPPLoginInfo>(info);
                if (loginInfo != null)
                {
                    if (loginInfo.errcode != 0)
                    {
                        throw new Exception(loginInfo.errmsg);
                    }
                }
                else
                {
                    throw new Exception("Validation failure , loginInfo is null !");
                }
            }
            else
            {
                throw new Exception("js_code is null !");
            }
            return loginInfo;
        }

        /// <summary>
        /// 获取微信AccessToken
        /// </summary>
        /// <param name="Code"></param>
        /// <returns></returns>
        public async Task<MiniAPPToken> GetMiniAPPAccessToken()
        {
            string requestUrl = BaseConfigModel.Configuration["HaBookAuth:MiniAPPAccessTokenUrl"];
            requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPID"]);
            requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPSECRET"]);
            string info = await HttpHelper.HttpGetAsync(requestUrl);
            MiniAPPToken miniAPPToken = MessagePackHelper.JsonToObject<MiniAPPToken>(info);
            if (miniAPPToken != null)
            {
                if (miniAPPToken.errcode != 0)
                {
                    throw new Exception(miniAPPToken.errmsg);
                }
            }
            else
            {
                throw new Exception("Validation failure,miniAPPToken is null!");
            }
            return miniAPPToken;
        }
        /// <summary>
        /// 获取用户登录信息
        /// </summary>
        /// <param name="unionid"></param>
        /// <param name="access_token"></param>
        /// <returns></returns>
        public async Task<WeChatUser> GetWeChatUserInfo(string session_key, Dictionary<string, object> dict)
        {
            string enData = "";
            if (dict.TryGetValue("encryptedData", out object encryptedData) && dict.TryGetValue("iv", out object iv))
            {
                if (encryptedData != null && iv != null)
                {
                    /**
                     *{"openId":"oLaYK45lBS8HWSAXJisDdIlEWj3A",
                     * "nickName":"菁華浮梦、℡",
                     * "gender":1,
                     * "language":"zh_CN",
                     * "city":"Chengdu",
                     * "province":"Sichuan",
                     * "country":"China",
                     * "avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/DYAIOgq83er98z4MsFd1xKML71TwQuR1Bxnt7ib3SGrNsKiaBCLYbLeS7KAT8h0ia8byiaVzurvEpVmmQpSzBQs5Nw/132",
                     * "unionId":"oqADO5qdTR6PItxhmDEPCsWU9PqI",
                     * "watermark":{"timestamp":1562224447,"appid":"wxf4905703824211aa"}}
                     **/
                    enData = WeChatCryptHelper.AESDecrypt(encryptedData.ToString(), session_key, iv.ToString());

                }
            }

            //string requestUrl = BaseConfigModel.Configuration["HaBookAuth:UnionidUserinfo"];
            //requestUrl = requestUrl.Replace("{{openid}}", unionid);
            //WeChatToken weChatToken = await GetWeChatAccessTokenClient();
            //requestUrl = requestUrl.Replace("{{access_token}}", weChatToken.access_token);
            //string info = await HttpHelper.HttpGetAsync(requestUrl);
            MiniAPPUserInfo miniAPPUser = MessagePackHelper.JsonToObject<MiniAPPUserInfo>(enData);
            if (miniAPPUser != null)
            {
                WeChatUser weChatUser = new WeChatUser();
                weChatUser.RowKey = miniAPPUser.unionId;
                weChatUser.PartitionKey = miniAPPUser.country;
                weChatUser.nickName = miniAPPUser.nickName;
                weChatUser.gender = miniAPPUser.gender;
                weChatUser.avatarUrl = miniAPPUser.avatarUrl;
                weChatUser.country = miniAPPUser.country;
                weChatUser.city = miniAPPUser.city;
                weChatUser.province = miniAPPUser.province;
                weChatUser.openId = miniAPPUser.openId;
                weChatUser.unionId = miniAPPUser.unionId;
                weChatUser.appid = miniAPPUser.watermark.appid;
                await SaveOrUpdate<WeChatUser>(weChatUser);
                return weChatUser;
            }
            else
            {
                throw new Exception("Validation failure,miniAPPToken is null!");
            }
        }
        public async Task<JwtResponse> MiniAPPLogin(Dictionary<string, object> dict)
        {
            MiniAPPLoginInfo loginInfo = await VerifyMiniAPP(dict);
            WeChatUser weChatUser = await GetWeChatUserInfo(loginInfo.session_key, dict);
            JwtResponse jwt = CreateJwtToken(weChatUser, loginInfo.session_key);
            LoginInfo login = new LoginInfo();
            login.RowKey = Guid.NewGuid().ToString();
            login.PartitionKey = weChatUser.PartitionKey;
            login.TeamModelId = weChatUser.unionId;
            login.Token = jwt.Access_token;
            login.Scope = jwt.Scope;
            return jwt;
        }
        public JwtResponse CreateJwtToken(WeChatUser user, string sessionKey)
        {
            ClaimModel model = new ClaimModel
            {
                Scope = "MiniAPP"
            };
            if (user != null)
            {
                model.Claims.Add(new Claim(JwtClaimTypes.SessionId, sessionKey));
                model.Claims.Add(new Claim(JwtClaimTypes.Name, user.nickName));
                model.Claims.Add(new Claim(JwtClaimTypes.Id, user.unionId));
                model.Claims.AddRange("Student".Split(',').Select(s => new Claim(JwtClaimTypes.Role, s)));
                model.Roles.Add("Student");
                JwtResponse jwtResponse = JwtHelper.IssueJWT(model, BaseConfigModel.Configuration.GetSection("JwtSetting").Get<JwtSetting>());
                return jwtResponse;
            }
            else
            {
                throw new Exception("Validation failure,user is null !");
            }
        }
        public JwtResponse CreateJwtToken(LoginInfo login, string tiket)
        {
            ClaimModel model = new ClaimModel
            {
                Scope = "WebAPP"
            };
            if (login != null)
            {
                model.Claims.Add(new Claim(JwtClaimTypes.SessionId, tiket));
                model.Claims.Add(new Claim(JwtClaimTypes.Name, login.Name));
                model.Claims.Add(new Claim(JwtClaimTypes.Id, login.TeamModelId));
                model.Claims.AddRange("Teacher".Split(',').Select(s => new Claim(JwtClaimTypes.Role, s)));
                model.Roles.Add("Teacher");
                JwtResponse jwtResponse = JwtHelper.IssueJWT(model, BaseConfigModel.Configuration.GetSection("JwtSetting").Get<JwtSetting>());
                return jwtResponse;
            }
            else
            {
                throw new Exception("Validation failure,user is null !");
            }
        }

        public async Task<JwtResponse> TeamModelLogin(TicketInfo ticketInfo)
        {
            string authorizationCode = HttpContextHelper.GetAuthorizationCode(httpContextAccessor);
            if (string.IsNullOrEmpty(authorizationCode))
            {
                if (ticketInfo != null && string.IsNullOrEmpty(ticketInfo.Ticket))
                {
                    throw new BizException(401, "Unauthorized");
                }
                // string code = BCryptHelper.Ecrypt(ticketInfo.Ticket + ticketInfo.TeamModelId);
                // bool f = BCryptHelper.Verify(ticketInfo.Ticket + ticketInfo.TeamModelId, ticketInfo.Sign);
                LoginInfo login = FindOneByKey<LoginInfo>("Ticket", ticketInfo.Ticket).Result;
                if (login != null && !string.IsNullOrEmpty(login.Token))
                {
                    JwtResponse token = CreateJwtToken(login, ticketInfo.Ticket);
                    login.Token = token.Access_token;
                    await Update<LoginInfo>(login);
                    return token;
                }
                // LoginInfo loginInfo = new LoginInfo
                // {
                //     PartitionKey = "loginInfo",
                //    // Phone = response.result.cellphone,
                //     RowKey = Guid.NewGuid().ToString(),
                //     TeamModelId = ticketInfo.TeamModelId,
                //     Name = ticketInfo.Name,
                //     Ticket = ticketInfo.Ticket,
                //     //CountryCode = response.result.countryCode
                // };
                // TeamModelUser user = await FindOneByKey<TeamModelUser>("TeamModelId", ticketInfo.TeamModelId);
                // if (user == null || string.IsNullOrEmpty(user.RowKey))
                // {
                //     user = new TeamModelUser { RowKey = Guid.NewGuid().ToString(), PartitionKey ="userInfo", RegisterTime = DateTimeHelper.ConvertToTimeStamp13(DateTime.Now) };
                // }
                //// user.Cellphone = response.result.cellphone;
                // user.NickName = ticketInfo.Name;
                // if (string.IsNullOrEmpty(user.FullName))
                // {
                //     user.FullName = ticketInfo.Name;
                // }
                // user.TeamModelId = ticketInfo.TeamModelId;
                // //user.PhoneCode = response.result.countryCode;
                // JwtResponse jwtToken = CreateJwtToken(loginInfo, ticketInfo.Ticket);
                // loginInfo.Token = jwtToken.Access_token;
                // loginInfo.Scope = jwtToken.Scope;
                // await Save<LoginInfo>(loginInfo);
                // await SaveOrUpdate<TeamModelUser>(user);
                // return jwtToken;
                string jwttoken = ticketInfo.Token.Replace("Bearer ", "");
                Dictionary<string, string> headers = new Dictionary<string, string>
                {
                    { Constants.AUTHORIZATION,"Bearer "+jwttoken },
                };
                JosnRPCRequest<Dictionary<string, object>> request = new JosnRPCRequest<Dictionary<string, object>>
                {
                    method = "UserInfoManage"
                };
              
                Dictionary<string, object> ticket = new Dictionary<string, object>
                {
                    { "idToken",ticketInfo.Ticket },
                    { "method", "get" },
                    { "option", "userInfo"},
                    { "extraInfo", new object() }
                };
                request.@params = ticket;
                string data = MessagePackHelper.ObjectToJson(request);
                string jsonStr = HttpHelper.HttpPost(BaseConfigModel.Configuration["HaBookAuth:AccountUrl"], data, headers, Constants.CONTENT_TYPE_JSON,1000, Encoding.UTF8);
                if (!string.IsNullOrEmpty(jsonStr))
                {
                    JosnRPCResponse<TeamModelIdInfo> response = MessagePackHelper.JsonToObject<JosnRPCResponse<TeamModelIdInfo>>(jsonStr);
                    if (response.error == null && response != null)
                    {
                        LoginInfo loginInfo = new LoginInfo
                        {
                            PartitionKey = response.result.cellphone,
                            RowKey = Guid.NewGuid().ToString(),
                            TeamModelId = response.result.id,
                            Name = response.result.name,
                            Ticket = ticketInfo.Ticket,
                        };
                        TeamModelUser user = await FindOneByKey<TeamModelUser>("TeamModelId", response.result.id);
                        if (user == null || string.IsNullOrEmpty(user.RowKey))
                        {
                            user = new TeamModelUser { RowKey = Guid.NewGuid().ToString(), PartitionKey = response.result.countryCode, RegisterTime = DateTimeHelper.ConvertToTimeStamp13(DateTime.Now) };
                        }
                        user.Cellphone = response.result.cellphone;
                        user.FullName= response.result.name;
                        user.NickName = response.result.nickname;
                       // user.HeadImgUrl = response.result.profilePicture;
                        if (string.IsNullOrEmpty(user.FullName))
                        {
                            user.FullName = response.result.name;
                        }
                        user.TeamModelId = response.result.id;
                        user.PhoneCode = response.result.countryCode;
                        JwtResponse jwtToken = CreateJwtToken(loginInfo, ticketInfo.Ticket);
                        loginInfo.Token = jwtToken.Access_token;
                        loginInfo.Scope = jwtToken.Scope;
                        await Save<LoginInfo>(loginInfo);
                        await SaveOrUpdate<TeamModelUser>(user);
                        return jwtToken;
                    }
                    else
                    {
                        throw new BizException(401, "Unauthorized");
                    }
                }
                else
                {
                    throw new BizException(401, "Unauthorized");
                }
            }
            else
            {
                ClaimModel claimModel = JwtHelper.SerializeJWT(authorizationCode);
                var dateTime = DateTimeHelper.ConvertToTimeStamp10(DateTime.Now);
                var expExt = claimModel.Claim.TryGetValue("exp", out var exp);
                if (expExt == false || dateTime > long.Parse(exp.ToString()))
                {
                    throw new BizException(401, "Unauthorized");
                }
                Dictionary<string, object> msp = new Dictionary<string, object>
                {
                    { "Token", authorizationCode }
                };
                LoginInfo loginInfo = FindOneByDict<LoginInfo>(msp).Result;
                if (loginInfo != null && !string.IsNullOrEmpty(loginInfo.Token))
                {
                    return new JwtResponse { Access_token = loginInfo.Token, Scope = loginInfo.Scope };
                }
                else
                {
                    throw new BizException(401, "Unauthorized");
                }
            }
        }
    }
}
