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();

        #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"),
            };
            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();

            //验证是否新用户
            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;
                #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 });


                    #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
                    };
                    UserReidsCache.AppletUserInfoSet(UserModuleCacheKeyConfig.Applet_Login_Info + UserId, appletUserInfo, Config.JwtExpirTime);
                    if (couponResult != null && couponResult.ID > 0)
                    {
                        return ApiResult.CouponSuccess(ResultCode.Success,1, "", couponResult.Name, 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("账号已被冻结，请联系运营商");
                }
                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();

                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
                };
                UserReidsCache.AppletUserInfoSet(UserModuleCacheKeyConfig.Applet_Login_Info + umodel.Id, appletUserInfo, Config.JwtExpirTime);
                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
    }
}