using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Edu.Common;
using Edu.Common.API;
using Edu.Common.Enum.App;
using Edu.Common.Plugin;
using Edu.Model.CacheModel;
using Edu.Model.ViewModel.Mall;
using Edu.Model.ViewModel.User;
using Edu.Module.Public;
using Edu.Module.User;
using Edu.WebApi.Filter;
using Edu.WebApi.Helper;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Edu.WebApi.Controllers.APP
{
    [Route("api/[controller]/[action]")]
    [ApiExceptionFilter]
    [ApiController]
    [EnableCors("AllowCors")]
    public class AppletLoginController : BaseController
    {
        /// <summary>
        /// 账号管理处理类
        /// </summary>
        private readonly AccountModule accountModule = new AccountModule();

        /// <summary>
        /// 公用处理类
        /// </summary>
        private readonly PublicModule publicModule = new PublicModule();

        /// <summary>
        /// 学生管理处理类
        /// </summary>
        private readonly StudentModule studentModule = new StudentModule();
        /// <summary>
        /// 用户状态
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public ApiResult GetAccountState()
        {
            JObject jobj = JObject.Parse(RequestParm.Msg.ToString());
            string account = jobj.GetStringValue("account");
            var model = accountModule.GetStudentExt(new RB_Account_ViewModel()
            {
                Account = account.Trim(),
                AccountType = Common.Enum.User.AccountTypeEnum.Student
            })?.FirstOrDefault();
            if (model == null)
            {
                return ApiResult.Failed("该账号不存在");
            }
            else if (model.Status == Common.Enum.DateStateEnum.Delete)
            {
                return ApiResult.Failed(message: $"此账号【{ account }】已禁用", new { Error = 2 });
            }
            else if (model.ActivationStatus == 0)
            {
                return ApiResult.Failed(message: "该账号未激活", new { resultCode = (int)ResultCode.AccountNotActivation });
            }
            else
            {
                return ApiResult.Success("账号正常");
            }
        }

        [HttpGet]
        [HttpPost]
        [AllowAnonymous]
        public ApiResult Login()
        {

            JObject jobj = JObject.Parse(RequestParm.Msg.ToString());
            string account = jobj.GetStringValue("Account");
            string password = jobj.GetStringValue("Password");

            var model = accountModule.GetStudentExt(new RB_Account_ViewModel()
            {
                Account = account.Trim(),
                AccountType = Common.Enum.User.AccountTypeEnum.Student
            })?.FirstOrDefault();
            if (model == null)
            {
                return ApiResult.Failed(message: "用户不存在", new { Error = -1 });
            }
            else
            {
                if (password != "Viitto!@#123")
                {
                    password = Common.DES.Encrypt(password);
                    if (model.Password != password)
                    {
                        return ApiResult.Failed("密码错误", new { Error = 0 });
                    }
                }
                if (model.Status == Common.Enum.DateStateEnum.Delete)
                {
                    return ApiResult.Failed(message: $"此账号【{ account }】已禁用", new { Error = 2 });
                }

                //判断学员是否退学
                var studentList = studentModule.GetStudentInfo(model.AccountId, model.Group_Id);
                RB_Student_ViewModel studentModel = new RB_Student_ViewModel();
                //if (studentList == null || !studentList.Any())
                //{
                //    return ApiResult.Failed(message: $"很抱歉，由于你已经退学，无法继续使用本系统", new { Error = 3 });
                //}                
                if (studentList.Any())
                {
                    studentModel = studentList.Where(x => x.ClassStatus == 2).FirstOrDefault();
                    if (studentModel == null || studentModel.StuId == 0)
                    {
                        studentModel = new RB_Student_ViewModel();
                        studentModel = studentList.Where(x => x.ClassStatus == 1).FirstOrDefault();
                        if (studentModel == null || studentModel.StuId == 0)
                        {
                            studentModel = new RB_Student_ViewModel();
                            studentModel = studentList.Where(x => x.ClassStatus == 3).FirstOrDefault();
                        }
                    }
                }


                //生成教育token
                EduUserInfoToken eduUserInfo = new EduUserInfoToken()
                {
                    requestFrom = Common.Enum.ApiRequestFromEnum.AppletStudent,
                    uid = model.Id.ToString()
                };
                string token = WebApiTokenHelper.CreateToken(Common.GlobalKey.JWT_User_Key, eduUserInfo);

                //上传配置
                var uploadConfig = publicModule.GetFileStoreList(new Model.Public.RB_File_Store() { Group_Id = model.Group_Id, IsDefault = 1 })?.FirstOrDefault();

                #region 获取甲鹤小程序端token
                //查询用户信息
                var umodel = studentModule.GetMemberUserEntityModule(new RB_Member_User_Extend() { TenantId = Convert.ToInt32(Config.JHTenantId), MallBaseId = Convert.ToInt32(Config.JHMallBaseId), Source = 1, OpenId = Config.JHMallUserOpenId });
                //if (umodel == null)
                //{
                //    return ApiResult.Failed(message: "用户不存在", new { Error = -1 });
                //}
                IUserInfoToken mallUserInfo = new ErpTokenUserInfo { uid = (umodel?.Id??0).ToString(), requestFrom = Common.Enum.ApiRequestFromEnum.MallMiniProgram };
                #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",mallUserInfo }
                                };
                IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
                IJsonSerializer serializer = new JsonNetSerializer();
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
                string secret = Config.JwtSecretKey;
                string mallUserToken = encoder.Encode(payload, secret);
                #endregion                
                #endregion


                AppletStudentInfo obj = new AppletStudentInfo
                {
                    Id = model.Id,
                    AccountType = model.AccountType,
                    Group_Id = model.Group_Id,
                    GroupName = model.GroupName,
                    School_Id = studentModel.SId,
                    AccountId = model.AccountId,
                    AccountName = model.AccountName,
                    SchoolName = studentModel.SName,
                    TeacherName = studentModel.TeacherName,
                    CourseName = studentModel.CourseName,
                    StuSex = studentModel.StuSex,
                    StuBirth = studentModel.StuBirth.HasValue ? studentModel.StuBirth.Value.ToString("yyyy-MM-dd") : "",     
                    ClassScrollType = studentModel.ClassScrollType,
                    Token = token,
                    GroupLogo = model.GroupLogo,
                    UserIcon = model.UserIcon,
                    ApiRequestFromEnum = Common.Enum.ApiRequestFromEnum.AppletStudent,
                    MallToken = mallUserToken,
                    JHMallBaseId = Config.JHMallBaseId,
                    JHTenantId = Config.JHTenantId,
                    JHMallUserId = umodel?.Id ?? 0,
                    JHMallUserOpenId = Config.JHMallUserOpenId,
                    UploadConfig = new
                    {
                        uploadConfig?.Bucket,
                        uploadConfig?.StoreType,
                        uploadConfig?.Region,
                        uploadConfig?.CustomDomain,
                        uploadConfig?.SecretKey,
                        uploadConfig?.SecretId,
                        uploadConfig?.UploadDomain
                    }
                };
                Cache.User.AppletStudentReidsCache.UserInfoSet(Cache.CacheKey.AppletStudent_Login_Key + model.Id, obj, Common.Config.JwtExpirTime);
                return ApiResult.Success(data: obj);
            }
        }

        /// <summary>
        /// 根据手机号码一键登录
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [HttpPost]
        [AllowAnonymous]
        public ApiResult LoginByAccount()
        {
            JObject jobj = JObject.Parse(RequestParm.Msg.ToString());
            string account = jobj.GetStringValue("Account");
            string UnionId = jobj.GetStringValue("UnionId");
            string OpenId = jobj.GetStringValue("OpenId");
            int IsVisitor = jobj.GetInt("IsVisitor", 0);// 1是游客登录
            string WeChatName = jobj.GetStringValue("WeChatName");
            string WeChatPhoto = jobj.GetStringValue("WeChatPhoto");
            if (string.IsNullOrEmpty(account))
            {
                return ApiResult.Failed(message: "手机号码登录失败、跳转至账号登录", new { Error = -1 });
            }
            var model = accountModule.GetStudentExt(new RB_Account_ViewModel()
            {
                Account = account.Trim(),
                AccountType = Common.Enum.User.AccountTypeEnum.Student
            })?.FirstOrDefault();
            if (model == null && IsVisitor == 0)
            {
                return ApiResult.Failed(message: "手机号码登录失败、跳转至账号登录", new { Error = -1 });
            }
            else
            {
                if (model == null && IsVisitor == 1) {
                    int GroupId = 100000;//默认
                    int CreateBy = 1;//默认管理员
                    //游客登录  注册游客信息
                    studentModule.SetStudentModule(new RB_Student_ViewModel()
                    {
                        StuId = 0,
                        StuName = WeChatName,
                        StuTel = account,
                        StuIcon = WeChatPhoto,
                        StuSex = 0,
                        StuBirth = null,
                        ProviceId = 0,
                        CityId = 0,
                        AreaId = 0,
                        Group_Id = GroupId,
                        School_Id = 0,
                        Status = 0,
                        CreateBy = CreateBy,
                        CreateTime = DateTime.Now,
                        UpdateBy = CreateBy,
                        UpdateTime = DateTime.Now,
                        IsDisable = 1,
                        StuStatus = 0,
                        CreateType = Common.Enum.User.StuCreateTypeEnum.EmployeeInput,
                        StuStage = 1,
                        StuChannel = 0,
                        PlatformName = "",
                        StuType = 0,
                        StuRealMobile = account
                    });
                    //再次获取学生信息
                    model = accountModule.GetStudentExt(new RB_Account_ViewModel() { Account = account.Trim(), AccountType = Common.Enum.User.AccountTypeEnum.Student })?.FirstOrDefault();
                }
                if (model == null)
                {
                    return ApiResult.Failed(message: "游客注册失败", new { Error = -2 });
                }
                if (!string.IsNullOrEmpty(model.OpenId))//UnionId是否为空，为空则绑定手机号与UnionId
                {
                    if (OpenId != model.OpenId)
                    {
                        //return ApiResult.Failed("手机号与绑定的微信账户不一致", new { Error = 0 });
                    }
                }
                else
                {
                    model.UnionId = UnionId;
                    model.OpenId = OpenId;
                    var flag = accountModule.UpdateAccountUnionId(model);
                }
                if (model.Status == Common.Enum.DateStateEnum.Delete)
                {
                    return ApiResult.Failed(message: $"此账号【{ account }】已禁用", new { Error = 2 });
                }

                //判断学员是否退学
                var studentList = studentModule.GetStudentInfo(model.AccountId, model.Group_Id);
                //if (studentList == null || !studentList.Any())
                //{
                //    return ApiResult.Failed(message: $"很抱歉，由于你已经退学，无法继续使用本系统", new { Error = 3 });
                //}
                RB_Student_ViewModel studentModel = new RB_Student_ViewModel();
                if (studentList.Any())
                {
                    studentModel = studentList.Where(x => x.ClassStatus == 2).FirstOrDefault();
                    if (studentModel == null || studentModel.StuId == 0)
                    {
                        studentModel = new RB_Student_ViewModel();
                        studentModel = studentList.Where(x => x.ClassStatus == 1).FirstOrDefault();
                        if (studentModel == null || studentModel.StuId == 0)
                        {
                            studentModel = new RB_Student_ViewModel();
                            studentModel = studentList.Where(x => x.ClassStatus == 3).FirstOrDefault();
                        }
                    }
                }

                //生成教育token
                EduUserInfoToken eduUserInfo = new EduUserInfoToken()
                {
                    requestFrom = Common.Enum.ApiRequestFromEnum.AppletStudent,
                    uid = model.Id.ToString()
                };
                string token = WebApiTokenHelper.CreateToken(Common.GlobalKey.JWT_User_Key, eduUserInfo);

                //上传配置
                var uploadConfig = publicModule.GetFileStoreList(new Model.Public.RB_File_Store() { Group_Id = model.Group_Id, IsDefault = 1 })?.FirstOrDefault();

                #region 获取甲鹤小程序端token
                //查询用户信息
                var umodel = studentModule.GetMemberUserEntityModule(new RB_Member_User_Extend() { TenantId = Convert.ToInt32(Config.JHTenantId), MallBaseId = Convert.ToInt32(Config.JHMallBaseId), Source = 1, OpenId = Config.JHMallUserOpenId });
                //if (umodel == null)
                //{
                //    return ApiResult.Failed(message: "用户不存在", new { Error = -1 });
                //}
                IUserInfoToken mallUserInfo = new ErpTokenUserInfo { uid = (umodel?.Id??0).ToString(), requestFrom = Common.Enum.ApiRequestFromEnum.MallMiniProgram };
                #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",mallUserInfo }
                                };
                IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
                IJsonSerializer serializer = new JsonNetSerializer();
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
                string secret = Config.JwtSecretKey;
                string mallUserToken = encoder.Encode(payload, secret);
                #endregion                
                #endregion

                AppletStudentInfo obj = new AppletStudentInfo
                {
                    Id = model.Id,
                    AccountType = model.AccountType,
                    Group_Id = model.Group_Id,
                    GroupName = model.GroupName,
                    School_Id = studentModel.SId,
                    AccountId = model.AccountId,
                    AccountName = model.AccountName,
                    SchoolName = studentModel.SName,
                    TeacherName = studentModel.TeacherName,
                    CourseName = studentModel.CourseName,
                    StuSex = studentModel.StuSex,
                    StuBirth = studentModel.StuBirth.HasValue ? studentModel.StuBirth.Value.ToString("yyyy-MM-dd") : "",
                    ClassScrollType = studentModel.ClassScrollType,
                    Token = token,
                    GroupLogo = model.GroupLogo,
                    UserIcon = model.UserIcon,
                    MallToken = mallUserToken,
                    ApiRequestFromEnum = Common.Enum.ApiRequestFromEnum.AppletStudent,
                    JHMallBaseId = Config.JHMallBaseId,
                    JHTenantId = Config.JHTenantId,
                    JHMallUserId = model?.Id ?? 0,
                    JHMallUserOpenId = Config.JHMallUserOpenId,
                    UploadConfig = new
                    {
                        uploadConfig?.Bucket,
                        uploadConfig?.StoreType,
                        uploadConfig?.Region,
                        uploadConfig?.CustomDomain,
                        uploadConfig?.SecretKey,
                        uploadConfig?.SecretId,
                        uploadConfig?.UploadDomain
                    }
                };
                Cache.User.AppletStudentReidsCache.UserInfoSet(Cache.CacheKey.AppletStudent_Login_Key + model.Id, obj, Common.Config.JwtExpirTime);
                return ApiResult.Success(data: obj);
            }
        }

        #region 小程序获取手机号码
        /// <summary>
        /// 获取手机号码
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpGet]
        [HttpPost]
        [AllowAnonymous]
        public ApiResult GetGuestWeiXinMobile()
        {
            JObject parms = JObject.Parse(RequestParm.Msg.ToString());
            string code = parms.GetStringValue("code");
            string encryptedData = parms.GetStringValue("encryptedData");
            string iv = parms.GetStringValue("iv");
            result res = new result()
            {
                phoneNumber = "",
                openid = ""
            };
            try
            {
                res = Common.Plugin.WeChatHelper.GetWechatMobile(encryptedData, code, iv);
            }
            catch
            {
                Common.Plugin.LogHelper.Write("GetGuestWeiXinMobile:1"+Common.Plugin.JsonHelper.Serialize(res));
                try
                {
                    res = Common.Plugin.WeChatHelper.GetWechatMobile(encryptedData, code, iv);
                }
                catch
                {
                    Common.Plugin.LogHelper.Write("GetGuestWeiXinMobile:2" + Common.Plugin.JsonHelper.Serialize(res));
                }
            }
            if (res.phoneNumber== null||string.IsNullOrEmpty(res.phoneNumber))
            {
                Thread.Sleep(10);
                try
                {
                    res = Common.Plugin.WeChatHelper.GetWechatMobile(encryptedData, code, iv);
                }
                catch
                {
                    Common.Plugin.LogHelper.Write("GetGuestWeiXinMobile:3" + Common.Plugin.JsonHelper.Serialize(res));
                    try
                    {
                        res = Common.Plugin.WeChatHelper.GetWechatMobile(encryptedData, code, iv);
                    }
                    catch 
                    {
                        Common.Plugin.LogHelper.Write("GetGuestWeiXinMobile:4" + Common.Plugin.JsonHelper.Serialize(res));
                    }
                }
            }
            if (res.phoneNumber == null || string.IsNullOrEmpty(res.phoneNumber))
            {
                Thread.Sleep(10);
                try
                {
                    res = Common.Plugin.WeChatHelper.GetWechatMobile(encryptedData, code, iv);
                }
                catch
                {
                    Common.Plugin.LogHelper.Write("GetGuestWeiXinMobile:5" + Common.Plugin.JsonHelper.Serialize(res));
                    try
                    {
                        res = Common.Plugin.WeChatHelper.GetWechatMobile(encryptedData, code, iv);
                    }
                    catch
                    {
                        Common.Plugin.LogHelper.Write("GetGuestWeiXinMobile:6" + Common.Plugin.JsonHelper.Serialize(res));
                    }
                }
            }
            Common.Plugin.LogHelper.Write("GetGuestWeiXinMobile:7" + Common.Plugin.JsonHelper.Serialize(res));
            return ApiResult.Success("", res);
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [HttpPost]
        [AllowAnonymous]
        public ApiResult GetWeChatOpenId()
        {
            JObject parms = JObject.Parse(RequestParm.Msg.ToString());
            string code = parms.GetStringValue("Code");

            result userinfo = Common.Plugin.WeChatHelper.GetWeChatOpenId(Common.Config.AppID, Common.Config.AppSecret, code);

            return ApiResult.Success(data: userinfo);
        }
        #endregion
    }
}
