using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Mall.Common.API;
using Mall.Model.Extend.User;
using Mall.Module.User;
using Mall.WebApi.Filter;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Mall.Common.Plugin;
using Mall.Common.Enum.User;
using Mall.CacheManager.User;
using Newtonsoft.Json.Linq;
using Mall.Common;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Mall.Common.Enum;
using Mall.CacheKey;
using Mall.Common.Pay.WeChatPat;
using Mall.Module.MarketingCenter;

namespace Mall.WebApi.Controllers.User
{
    [Route("api/[controller]/[action]")]
    [ApiExceptionFilter]
    [ApiController]
    [EnableCors("AllowCors")]
    public class AppletLoginController : ControllerBase
    {

        private readonly UserModule userModule = new UserModule();
        private readonly CouponModule couponModule = new CouponModule();
        //private readonly Module.BaseSetUp.MallBaseModule MallBaseModule = new Module.BaseSetUp.MallBaseModule();
        /// <summary>
        /// 商户小程序处理类
        /// </summary>
        private readonly MiniProgramModule programModule = new MiniProgramModule();
        private readonly Module.Education.EducationModule educationModule = new Module.Education.EducationModule();

        private readonly Module.Reserve.ReserveModule reserveModule = new Module.Reserve.ReserveModule();
        #region 小程序登录
        /// <summary>
        /// 登录注册
        /// </summary>
        /// <param name="requestMsg"></param>
        /// <returns></returns>
        [HttpPost]
        public ApiResult Login(object requestMsg)
        {
            var requestParm = JsonConvert.DeserializeObject<RequestParm>(requestMsg.ToString());
            JObject parms = JObject.Parse(requestParm.msg.ToString());
            RB_Member_User_Extend demodel = new RB_Member_User_Extend()
            {
                Source = (UserSourceEnum)parms.GetInt("Source"),
                OpenId = parms.GetStringValue("OpenId"),
                Name = parms.GetStringValue("Name"),
                Photo = parms.GetStringValue("Photo"),
                Moblie = parms.GetStringValue("Moblie"),
                SuperiorId = parms.GetInt("SuperiorId"),
                SmallShopId = parms.GetInt("SmallShopId"),
                UserPageType = (Common.Enum.Goods.GoodsPageTypeEnum)parms.GetInt("UserPageType", 0),
                CounponPassword = parms.GetInt("CounponPassword", 3),
                KeyWord = parms.GetStringValue("KeyWord"),
            };
            if (requestParm.TenantId <= 0)
            {
                return ApiResult.ParamIsNull("请传递商户号");
            }
            if (requestParm.MallBaseId <= 0)
            {
                return ApiResult.ParamIsNull("请传递小程序id");
            }
            if (!demodel.Source.HasValue)
            {
                return ApiResult.ParamIsNull("请传递来源平台");
            }
            if (string.IsNullOrEmpty(demodel.OpenId))
            {
                return ApiResult.ParamIsNull("请传递唯一码");
            }

            Model.Extend.MarketingCenter.RB_DiscountCoupon_Extend couponResult = new Model.Extend.MarketingCenter.RB_DiscountCoupon_Extend();

            Model.Extend.Education.RB_Education_Coupon_Extend educationCouponResult = new Model.Extend.Education.RB_Education_Coupon_Extend();

            Model.Extend.Reserve.RB_Reserve_Coupon_Extend reserveCouponResult = new Model.Extend.Reserve.RB_Reserve_Coupon_Extend();
            string couponName = string.Empty;
            bool isGiveCoupon = false;
            //验证是否新用户
            if (!userModule.ValidateUserOpenId(demodel.OpenId, demodel.Source, requestParm.TenantId, requestParm.MallBaseId))
            {
                LogHelper.WriteInfo(demodel.OpenId + "，SuperiorId:" + (demodel.SuperiorId ?? 0));
                //注册新用户
                if (string.IsNullOrEmpty(demodel.Name))
                {
                    return ApiResult.ParamIsNull("请传递用户名称");
                }
                if (string.IsNullOrEmpty(demodel.Photo))
                {
                    return ApiResult.ParamIsNull("请传递用户头像");
                }
                #region 赋默认值
                demodel.AliasName ??= "";
                demodel.Moblie ??= "";
                demodel.MemberGrade ??= 0;//普通会员
                demodel.OrderNum ??= 0;
                demodel.CouponsNum ??= 0;
                demodel.CardVolumeNum ??= 0;
                demodel.Balance ??= 0;
                demodel.Integral ??= 0;
                demodel.SuperiorId ??= 0;//0表示 总店
                demodel.Blacklist ??= 0;
                demodel.ContactWay ??= "";
                demodel.Remark ??= "";
                demodel.TotalConsumption ??= 0;
                if (!demodel.UserPageType.HasValue)
                {
                    demodel.UserPageType = Common.Enum.Goods.GoodsPageTypeEnum.Mall;
                }
                else
                {
                    if (demodel.UserPageType == Common.Enum.Goods.GoodsPageTypeEnum.All)
                    {
                        demodel.UserPageType = Common.Enum.Goods.GoodsPageTypeEnum.Mall;
                    }
                }

                #endregion
                var basicsModel = userModule.GetDistributorBasicsInfo(requestParm.TenantId.ToString(), requestParm.MallBaseId);
                if ((basicsModel?.ReferralsCondition ?? DistrbutorReferralsEnum.SCDJ) == DistrbutorReferralsEnum.SCDJ || (basicsModel?.ReferralsCondition ?? DistrbutorReferralsEnum.SCDJ) == DistrbutorReferralsEnum.SC7SF)
                {
                    demodel.DownlineCondition = basicsModel?.ReferralsCondition ?? DistrbutorReferralsEnum.SCDJ;
                    demodel.IsBeDownline = 1;
                    demodel.WaitSuperiorId = 0;
                    demodel.BeDownlineDate = DateTime.Now;
                }
                else
                {
                    demodel.DownlineCondition = basicsModel?.ReferralsCondition ?? DistrbutorReferralsEnum.SCDJ;
                    demodel.IsBeDownline = 2;
                    demodel.WaitSuperiorId = demodel.SuperiorId;
                    demodel.SuperiorId = 0;//未成为下线  暂设为总店
                }

                demodel.TenantId = requestParm.TenantId;
                demodel.MallBaseId = requestParm.MallBaseId;
                demodel.CreateDate = DateTime.Now;
                demodel.UpdateDate = DateTime.Now;
                demodel.SecretKey = Guid.NewGuid().ToString();
                int UserId = userModule.AddMemberUserInfo(demodel);
                bool flag = UserId > 0;
                if (flag)
                {

                    //自动发放新人优惠券 2020-08-04 Add By:W
                    couponResult = couponModule.AutoCoupon(new Model.Extend.MarketingCenter.RB_DiscountCoupon_Extend { UserId = UserId, TenantId = demodel.TenantId, MallBaseId = demodel.MallBaseId, TriggerType = 3 });
                    educationCouponResult = educationModule.AutoEducationCoupon(new Model.Extend.Education.RB_Education_Coupon_Extend { UserId = UserId, TenantId = demodel.TenantId, MallBaseId = demodel.MallBaseId, TriggerType = 3 });
                    reserveCouponResult = reserveModule.AutoEducationCoupon(new Model.Extend.Reserve.RB_Reserve_Coupon_Extend { UserId = UserId, TenantId = demodel.TenantId, MallBaseId = demodel.MallBaseId, TriggerType = 3 });
                    if (couponResult != null && couponResult.ID > 0)
                    {
                        couponName = couponResult.Name;
                        isGiveCoupon = true;
                    }
                    //自动发放新人优惠券 2020-12-31 Add By:W
                    if (demodel.CounponPassword == 5 && !string.IsNullOrWhiteSpace(demodel.KeyWord))
                    {
                        couponResult = couponModule.AutoCoupon(new Model.Extend.MarketingCenter.RB_DiscountCoupon_Extend { UserId = UserId, TenantId = demodel.TenantId, MallBaseId = demodel.MallBaseId, TriggerType = 5, KeyWord = demodel.KeyWord });

                        if (couponResult != null && couponResult.ID > 0)
                        {
                            couponName = couponName + "," + couponResult.Name;
                            isGiveCoupon = true;
                        }
                    }
                    #region 粉象返佣  自动注册分销商 普通会员等级
                    if ((basicsModel?.IsEnableFXGrade ?? 2) == 1)
                    {
                        try
                        {
                            var FXPModel = userModule.GetFXDistributorGradeList(new RB_Distributor_FXGrade_Extend() { IsGuest = 1, MallBaseId = requestParm.MallBaseId, TenantId = requestParm.TenantId }).FirstOrDefault();
                            userModule.SetDistributorInfoForFX(FXPModel?.Id ?? 0, UserId, requestParm.TenantId, requestParm.MallBaseId);
                        }
                        catch (Exception ex)
                        {
                            LogHelper.Write(ex, "粉象模式  自动生成分销商失败，UserId:" + UserId);
                        }
                    }
                    #endregion
                    //返回基本信息
                    TokenUserInfo userInfo = new TokenUserInfo { uid = UserId.ToString(), requestFrom = ApiRequestFromEnum.MiniProgram };
                    #region JWT
                    IDateTimeProvider provider = new UtcDateTimeProvider();
                    var now = provider.GetNow().AddMinutes(-1);
                    var unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); // or use JwtValidator.UnixEpoch
                    var secondsSinceEpoch = Math.Round((now - unixEpoch).TotalSeconds);
                    var payload = new Dictionary<string, object>
                                {
                                        {"iat",secondsSinceEpoch },
                                        {"exp",secondsSinceEpoch+Config.JwtExpirTime},
                                        {"mall_userInfo",userInfo }
                                };
                    IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
                    IJsonSerializer serializer = new JsonNetSerializer();
                    IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                    IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
                    string secret = Config.JwtSecretKey;
                    string token = encoder.Encode(payload, secret);
                    #endregion
                    var mmodel = programModule.GetMiniProgramModule(new RB_MiniProgram_Extend() { MallBaseId = demodel.MallBaseId });
                    AppletUserInfo appletUserInfo = new AppletUserInfo()
                    {
                        MallBaseId = demodel.MallBaseId,
                        MallName = mmodel?.MallName ?? "",
                        Mobile = demodel.Moblie,
                        UserId = UserId,
                        TenantId = demodel.TenantId,
                        Name = demodel.Name,
                        OpenId = demodel.OpenId,
                        Photo = demodel.Photo,
                        Source = demodel.Source,
                        SecretKey = demodel.SecretKey,
                        SuperiorId = demodel.SuperiorId ?? 0,
                        Token = token,
                        SmallShopId = 0,
                        UserSmallShopId = demodel.SmallShopId,
                        IsOpenSchool = mmodel.IsOpenSchool,
                        UserPageType = mmodel.IsOpenSchool == 1 ? demodel.UserPageType : Common.Enum.Goods.GoodsPageTypeEnum.All,
                        UserTeacher = 0
                    };
                    UserReidsCache.AppletUserInfoSet(UserModuleCacheKeyConfig.Applet_Login_Info + UserId, appletUserInfo, Config.JwtExpirTime);
                    if (isGiveCoupon)
                    {
                        return ApiResult.CouponSuccess(ResultCode.Success, 1, "", couponName, appletUserInfo);

                    }
                    else
                    {
                        return ApiResult.CouponSuccess(ResultCode.Fail, 1, "", "", appletUserInfo);
                    }

                }

                return ApiResult.CouponFailed(ResultCode.Fail, 1, "");
                //  return ApiResult.Failed("注册失败，请联系管理员");
            }
            else
            {
                //查询用户信息
                var umodel = userModule.GetMemberUserEntityModule(new RB_Member_User_Extend() { TenantId = requestParm.TenantId, MallBaseId = requestParm.MallBaseId, Source = demodel.Source, OpenId = demodel.OpenId });
                if (umodel == null)
                {
                    return ApiResult.CouponFailed(ResultCode.Fail, 1, "");
                    // return ApiResult.Failed("未能查询到用户信息");
                }
                if (umodel.Blacklist == 1)
                {
                    return ApiResult.Failed("账号已被冻结，请联系运营商");
                }
                //自动发放新人优惠券 2020-12-31 Add By:W
                if (demodel.CounponPassword == 5 && !string.IsNullOrWhiteSpace(demodel.KeyWord))
                {
                    couponResult = couponModule.AutoCoupon(new Model.Extend.MarketingCenter.RB_DiscountCoupon_Extend { UserId = umodel.Id, TenantId = demodel.TenantId, MallBaseId = demodel.MallBaseId, TriggerType = 5, KeyWord = demodel.KeyWord });

                    if (couponResult != null && couponResult.ID > 0)
                    {
                        couponName = couponResult.Name;
                        isGiveCoupon = true;
                    }
                }

                TokenUserInfo userInfo = new TokenUserInfo { uid = umodel.Id.ToString(), requestFrom = ApiRequestFromEnum.MiniProgram };
                #region JWT
                IDateTimeProvider provider = new UtcDateTimeProvider();
                var now = provider.GetNow().AddMinutes(-1);
                var unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); // or use JwtValidator.UnixEpoch
                var secondsSinceEpoch = Math.Round((now - unixEpoch).TotalSeconds);
                var payload = new Dictionary<string, object>
                                {
                                        {"iat",secondsSinceEpoch },
                                        {"exp",secondsSinceEpoch + Config.JwtExpirTime},
                                        {"mall_userInfo",userInfo }
                                };
                IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
                IJsonSerializer serializer = new JsonNetSerializer();
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
                string secret = Config.JwtSecretKey;
                string token = encoder.Encode(payload, secret);
                #endregion                
                var mmodel = programModule.GetMiniProgramModule(new RB_MiniProgram_Extend() { MallBaseId = umodel.MallBaseId });
                //2020-08-12 Add By:W
                var smallShopsInfoModle = userModule.GetSmallShopsInfoList(new RB_SmallShops_Info_Extend { TenantId = umodel.TenantId, MallBaseId = umodel.MallBaseId, UserId = umodel.Id }).OrderByDescending(x => x.CreateDate).FirstOrDefault();
                var teacher = userModule.GetTeacherModel(new Model.Extend.Education.RB_Education_Teacher_Extend { TeacherStatus = 1, TenantId = umodel.TenantId, MallBaseId = umodel.MallBaseId, UserId = umodel.Id });
                AppletUserInfo appletUserInfo = new AppletUserInfo()
                {
                    MallBaseId = umodel.MallBaseId,
                    MallName = mmodel?.MallName ?? "",
                    Mobile = umodel.Moblie,
                    UserId = umodel.Id,
                    TenantId = umodel.TenantId,
                    Name = umodel.Name,
                    OpenId = umodel.OpenId,
                    Photo = umodel.Photo,
                    Source = demodel.Source,
                    SecretKey = umodel.SecretKey,
                    SuperiorId = umodel.SuperiorId ?? 0,
                    Token = token,
                    SmallShopId = (smallShopsInfoModle != null && smallShopsInfoModle.AuditStatus == DistributorAuditStatusEnum.Audited) ? smallShopsInfoModle.Id : 0,
                    UserSmallShopId = umodel.SmallShopId,
                    IsOpenSchool = mmodel.IsOpenSchool,
                    UserPageType = mmodel.IsOpenSchool == 1 ? umodel.UserPageType : Common.Enum.Goods.GoodsPageTypeEnum.All,
                    UserTeacher = (teacher != null && teacher.ID > 0) ? teacher.ID : 0
                };
                UserReidsCache.AppletUserInfoSet(UserModuleCacheKeyConfig.Applet_Login_Info + umodel.Id, appletUserInfo, Config.JwtExpirTime);
                if (isGiveCoupon)
                {
                    return ApiResult.CouponSuccess(ResultCode.Success, 1, "", couponName, appletUserInfo);


                }
                else
                {
                    return ApiResult.CouponSuccess(ResultCode.Fail, 1, "", "", appletUserInfo);
                }

                // return ApiResult.CouponSuccess(ResultCode.Fail, 1, "", "", appletUserInfo);
                //return ApiResult.Success("", appletUserInfo);
            }
        }

        /// <summary>
        /// 获取小程序token
        /// </summary>
        /// <param name="requestMsg"></param>
        /// <returns></returns>
        [HttpPost]
        public ApiResult GetMallToken(object requestMsg)
        {
            var requestParm = JsonConvert.DeserializeObject<RequestParm>(requestMsg.ToString());
            if (requestParm.TenantId <= 0)
            {
                return ApiResult.ParamIsNull("请传递商户号");
            }
            if (requestParm.MallBaseId <= 0)
            {
                return ApiResult.ParamIsNull("请传递小程序id");
            }

            var appletWeChatModel = programModule.GetMiniProgramModule(new RB_MiniProgram_Extend() { MallBaseId = requestParm.MallBaseId });
            if (appletWeChatModel == null)
            {
                return ApiResult.ParamIsNull("小程序不存在");
            }
            if (appletWeChatModel.TenantId != requestParm.TenantId)
            {
                return ApiResult.ParamIsNull("商户号错误");
            }
            string token = CacheManager.AppletWeChat.WeiXinReidsCache.Get(appletWeChatModel.MiniAppId);
            if (string.IsNullOrEmpty(token))
            {
                token = TokenHelper.GetLXYToken(token, appletWeChatModel.MiniAppId, appletWeChatModel.MiniAppSecret);
                Task.Run(() => CacheManager.AppletWeChat.WeiXinReidsCache.Set(appletWeChatModel.MiniAppId, token));
            }
            if (!string.IsNullOrEmpty(token))
            {
                return ApiResult.Success("", token);
            }
            else
            {
                return ApiResult.Failed();
            }

        }

        #endregion




        #region 小程序获取手机号码
        /// <summary>
        /// 获取手机号码
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public ApiResult GetGuestWeiXinMobile(object requestMsg)
        {
            var requestParm = JsonConvert.DeserializeObject<RequestParm>(requestMsg.ToString());
            JObject parms = JObject.Parse(requestParm.msg.ToString());
            string code = parms.GetStringValue("code");
            string encryptedData = parms.GetStringValue("encryptedData");
            string iv = parms.GetStringValue("iv");
            if (requestParm.TenantId <= 0)
            {
                return ApiResult.ParamIsNull("请传递商户号");
            }
            if (requestParm.MallBaseId <= 0)
            {
                return ApiResult.ParamIsNull("请传递小程序id");
            }

            var appletWeChatModel = programModule.GetMiniProgramModule(new RB_MiniProgram_Extend() { MallBaseId = requestParm.MallBaseId });
            if (appletWeChatModel == null)
            {
                return ApiResult.ParamIsNull("小程序不存在");
            }
            if (appletWeChatModel.TenantId != requestParm.TenantId)
            {
                return ApiResult.ParamIsNull("商户号错误");
            }
            string Appid = appletWeChatModel.MiniAppId;
            var Secret = appletWeChatModel.MiniAppSecret;
            string grant_type = "authorization_code";

            //向微信服务端 使用登录凭证 code 获取 session_key 和 openid  
            string url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + Appid + "&secret=" + Secret + "&js_code=" + code + "&grant_type=" + grant_type;
            string type = "utf-8";
            GetUsersHelper GetUsersHelper = new GetUsersHelper();
            JObject jo = null;
            string _telPhone = "";
            try
            {
                string j = GetUsersHelper.GetUrltoHtml(url, type);//获取微信服务器返回字符串 
                //将字符串转换为json格式 
                jo = (JObject)JsonConvert.DeserializeObject(j);
                Common.Plugin.result res = new Common.Plugin.result
                {
                    //微信服务器验证成功 
                    openid = jo["openid"].ToString(),
                    session_key = jo["session_key"].ToString()
                };
                if (!string.IsNullOrWhiteSpace(jo["openid"].ToString()))
                {
                    if (!String.IsNullOrEmpty(encryptedData) && !string.IsNullOrEmpty(iv))
                    {
                        //解析手机号码
                        _telPhone = Common.EncryptionHelper.AES_decrypt(encryptedData, jo["session_key"].ToString(), iv);
                    }
                }
            }
            catch (Exception ex)
            {
                Common.Plugin.LogHelper.Write(ex, string.Format("GetGuestWeiXinMobile:msg:{0},request:{1},URL:{2}", Common.Plugin.JsonHelper.Serialize(jo), requestMsg.ToString(), url));
                return ApiResult.Failed("获取失败");
            }
            return ApiResult.Success("", _telPhone);
        }
        #endregion

    }
}