using GraphQL;
using LY.App.Common.Cypher;
using LY.App.Common.Redis;
using LY.App.Extensions.DI;
using LY.App.Model;
using Mapster;
using Microsoft.IdentityModel.Tokens;
using SqlSugar;
using StackExchange.Redis;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace LY.App.Service
{
    [ServiceInjection(InjectionType.Transient)]
    public class UserService
    {
        private readonly SqlSugarClient _db;
        private readonly IConfiguration _config;
        private readonly RedisService _redisService;
        public UserService(SqlSugarClient db, IConfiguration config, RedisService redisService)
        {
            _db = db;
            _config = config;
            _redisService = redisService;
        }
        #region 增删改查
        /// 
        /// 
        /// 
        /// 
        /// 
        public async Task Add(AddUser input)
        {
            var exists = await _db.Queryable().AnyAsync(s => s.Name == input.Name && s.Disable == false);
            if (!exists)
            {
                var entity = input.Adapt();
                // var entity = _mapper.Map(input);
                entity.CreateTime = DateTime.Now;
                entity.UpdatePwdTime = DateTime.Now;
                entity.Password = MD5CypherUtil.Hash("ly_" + input.Password);
                var Id = await _db.Insertable(entity).ExecuteReturnSnowflakeIdAsync();
                return new ApiResult() { code = 0, data = Id.ToString() };
            }
            else
            {
                return new ApiResult() { code = 1, msg = "已存在该用户名" };
            }
        }
        /// 
        /// 删除用户,标记删除,不是物理删除
        /// 
        /// 
        /// 
        public async Task SoftDelete(IEnumerable ids)
        {
            if (ids.Any())
            {
                foreach (var item in ids)
                {
                    var entity = await _db.Queryable().FirstAsync(s => s.Id == item);
                    if (entity?.Name != "admin")
                    {
                        entity.Disable = entity.Disable == true ? false : true;
                        await _db.Updateable(entity).ExecuteCommandAsync();
                    }
                    else
                        return "admin 不可删除!";
                }
                return "";
            }
            return "ids不能为空";
        }
        /// 
        /// 获取用户信息
        /// 
        /// 
        /// 
        public async Task GetUserById(long userId)
        {
            var entity = await _db.Queryable().FirstAsync(s => s.Id == userId);
            if (entity != null)
            {
                entity.Password = "";
                return new ApiResult() { code = 0, data = entity };
            }
            return null;
        }
        /// 
        /// 监测登录次数
        /// 
        /// 
        /// 
        private async Task CheckLoginNum(string username)
        {
            int num = 0;
            // var node = SettingHelper.Instance.GetNode("Vertify", "LoginFailed");
            var node = _config["Vertify"];
            var key = RedisKeyList.LogNum(username);
            var val = await _redisService.GetAsync(key);
            if (num >= int.Parse(node))
            {
                return true;
            }
            return false;
        }
        /// 
        /// 登录
        /// 
        /// 
        /// 
        public async Task Login(LoginModel input)
        {
            if (await CheckLoginNum(input.username))
            {
                return new ApiResult()
                {
                    code = 1,
                    msg = "连续登录失败5次,锁定30分钟"
                };
            }
            var password = MD5CypherUtil.Hash("ly_" + input.password);
            var entity = await _db.Queryable()
                 .Where(s => s.Disable == false &&
                 s.Name == input.username && s.Password == password).FirstAsync();
            if (entity == null)
            {
                await SetLoginNum(input.username);
                return new ApiResult()
                {
                    code = 1,
                    msg = "请检查用户名跟密码!"
                };
            }
            entity.LoginTime = DateTime.Now;
            await _db.Updateable(entity).ExecuteCommandAsync();
            await RemoveLoginNum(input.username);
            string token = CreateToken(entity);
            //加入redis
            await _redisService.SetAsync(RedisKeyList.TokenUser(input.username),
                token, TimeSpan.FromSeconds(60 * 60 * 24 * 7));
            return new ApiResult()
            {
                code = 1,
                data = new
                {
                    token,
                    expires = DateTime.UtcNow.AddSeconds(60*60*24*7),
                    isAdmin = entity.IsAdmin,
                    userid = entity.Id.ToString()
                }
            };
        }
        private async Task RemoveLoginNum(string username)
        {
            var key = $"login_num_{username}";
            await _redisService.DeleteAsync(key);
        }
        private async Task SetLoginNum(string username)
        {
            var key = RedisKeyList.LogNum(username);
            var num = await _redisService.GetAsync(key);
            await _redisService.SetAsync(key, num + 1, TimeSpan.FromMinutes(30));
        }
        private string CreateToken(UserEntity user)
        {
            // 创建JWT的密钥
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Token:SecretKey"]));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
            // 创建Claims
            var claims = new[]
            {
            new Claim(JwtRegisteredClaimNames.Sub,user.Name),
            new Claim(JwtRegisteredClaimNames.Sid, user.Id.ToString())
            // 还可以添加其他需要的Claims
        };
            // 创建Token
            var token = new JwtSecurityToken(
                issuer: _config["Token:Issuer"],
                audience: _config["Token:Audience"],
                claims: claims,
                expires: DateTime.UtcNow.AddSeconds(60 * 60 * 24 * 7), // 设置Token过期时间
                signingCredentials: credentials
            );
            // 生成Token字符串
            var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
            return tokenString;
        }
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public async Task