using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Datory.Utils;
using GxPress.Api.Tools;
using GxPress.Auth;
using GxPress.Common.Exceptions;
using GxPress.Common.Tools;
using GxPress.Common.Validation;
using GxPress.Entity;
using GxPress.EnumConst;
using GxPress.Repository.Interface;
using GxPress.Request.App.User;
using GxPress.Request.User;
using GxPress.Result.App.FileLibrary;
using GxPress.Result.App.User;
using GxPress.Result.User;
using GxPress.Service.Interface;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace GxPress.Api.AppControllers
{
    /// <summary>
    /// 用户
    /// </summary>
    [Route("/api/app/user")]
    [ApiController]
    [Authorize]
    public class UserController : ControllerBase
    {
        private readonly JwtOptions _jwtOptions;
        private readonly ILogger<UserController> _logger;
        private readonly IUserRepository _userRepository;
        private readonly IDepartmentRepository _departmentRepository;
        private readonly ILoginContext _loginContext;
        private readonly IUserService _userService;
        private readonly IFileLibraryRepository fileLibraryRepository;
        private readonly IDistributedCache _cache;
        public UserController(IUserRepository userRepository, IOptions<JwtOptions> jwtOptions,
            ILogger<UserController> logger, IDepartmentRepository departmentRepository, ILoginContext loginContext,
            IUserService userService, IFileLibraryRepository fileLibraryRepository, IDistributedCache cache)
        {
            _userRepository = userRepository;
            _departmentRepository = departmentRepository;
            _userService = userService;
            _jwtOptions = jwtOptions.Value;
            _logger = logger;
            _loginContext = loginContext;
            this.fileLibraryRepository = fileLibraryRepository;
            _cache = cache;
        }
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("signin")]
        [AllowAnonymous]
        public async Task<UserSignInResult> SignIn(UserSignInRequest request)
        {
            var result = await _userRepository.SignInAsync(request);
            var claims = new[]
            {
                new Claim(ClaimTypes.NameIdentifier, result.UserId.ToString()),
                new Claim(ClaimTypes.Role, AccountTypeConst.User.ToString())
            };
            result.Token = TokenHelper.BuildToken(_jwtOptions, claims);
            return result;
        }
        /// <summary>
        /// 绑定opendId
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("set-opend-Id")]
        [AllowAnonymous]
        public async Task<UserSignInResult> SetOpenId(UserSignInRequest request)
        {
            var success = await _userRepository.UpdateByOpendIdAsync(request);
            if (success)
            {
                var result = await _userRepository.SignInAsync(request);
                var claims = new[]
                {
                new Claim(ClaimTypes.NameIdentifier, result.UserId.ToString()),
                new Claim(ClaimTypes.Role, AccountTypeConst.User.ToString())
            };
                result.Token = TokenHelper.BuildToken(_jwtOptions, claims);
                return result;
            }
            return new UserSignInResult();
        }
        /// <summary>
        /// 查询opendId是否存在
        /// </summary>
        /// <param name="opendId"></param>
        /// <returns></returns>
        [HttpGet("find-opend-Id/{opendId}")]
        [AllowAnonymous]
        public async Task<bool> FindOpenId(string opendId)
        {
            var user = await _userRepository.GetByOpenIdAsync(opendId);
            if (user == null)
                return false;
            return true;
        }
        /// <summary>
        /// 登录验证码发送
        /// </summary>
        /// <param name="phone"></param>
        /// <returns></returns>
        [HttpGet("sendSmsCode")]
        [AllowAnonymous]
        public async Task<bool> SendSmsCode([FromQuery] [Required] [Mobile] string phone)
        {
            var user = await _userRepository.GetByPhoneAsync(phone);
            //用户不存在
            if (user == null)
                throw new BusinessException("该用户不存在");
            //发送短信
            var key = $"login:{phone}";
            var code = await _cache.GetStringAsync(key);
            if (!string.IsNullOrEmpty(code))
                throw new BusinessException("请求太频繁！");
            code = RandomGenerator.GetNumberString(6);
            if (Common.Sms.AliySms.SendSms(phone, code))
            {
                _logger.LogInformation("{phone}验证码:{code}", phone, code);
                var codeByte = Encoding.UTF8.GetBytes(Utilities.JsonSerialize(code));
                await _cache.SetAsync($"{key}", codeByte, new DistributedCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60)
                });
                return true;
            }
            return false;
        }

        /// <summary>
        /// 更换手机号码验证码发送
        /// </summary>
        /// <param name="phone"></param>
        /// <returns></returns>
        [HttpGet("send-sms-code")]
        public async Task<bool> SendSmsCodeReplace([FromQuery] [Required] [Mobile] string phone)
        {
            var user = await _userRepository.GetByPhoneAsync(phone);
            if (user != null)
                throw new BusinessException("号码以被使用");
            //发送短信
            var key = $"login:{phone}";
            var code = await _cache.GetStringAsync(key);
            if (!string.IsNullOrEmpty(code))
                throw new BusinessException("请求太频繁！");
            code = RandomGenerator.GetNumberString(6);
            if (Common.Sms.AliySms.SendSms(phone, code))
            {
                _logger.LogInformation("{phone}验证码:{code}", phone, code);
                var codeByte = Encoding.UTF8.GetBytes(Utilities.JsonSerialize(code));
                await _cache.SetAsync($"{key}", codeByte, new DistributedCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60)
                });
                return true;
            }
            return false;
        }

        /// <summary>
        /// app查询用户详情
        /// </summary>
        /// <returns></returns>
        [HttpGet("detail")]
        public async Task<UserDetail> GetDetail()
        {
            var id = _loginContext.AccountId;
            var user = await _userRepository.GetAsync(id);
            if (user == null)
                throw new BusinessException("用户id有误");
            return await _userRepository.GetDetailAsync(id);
        }

        /// <summary>
        /// app查询他人用户详情
        /// </summary>
        /// <returns></returns>
        [HttpGet("detail/{id}")]
        public async Task<UserDetail> GetDetail(int id)
        {
            if (id <= 0)
                throw new BusinessException("用户id有误");
            return await _userService.GetUserByIdAsync(_loginContext.AccountId, id);
        }
        /// <summary>
        /// app更新用户信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPut("update")]
        public async Task<bool> Update([FromBody] User request)
        {
            var id = _loginContext.AccountId;
            var result = await _userRepository.UpdateAsync(id, request);
            if (result == false)
                throw new BusinessException("更新失败");
            return true;
        }

        /// <summary>
        /// 私信
        /// </summary>
        /// <returns></returns>
        [HttpPost("update-user-private-letter")]
        public async Task<bool> UpdateUserPrivateLetter()
        {
            UserPrivateLetterRequest request = new UserPrivateLetterRequest { Id = _loginContext.AccountId };
            var result = await _userRepository.UpdateUserPrivateLetterAsync(request);
            if (result == false)
                throw new BusinessException("更新失败");
            return true;
        }

        /// <summary>
        /// 通知
        /// </summary>
        /// <returns></returns>
        [HttpPost("update-user-notice")]
        public async Task<bool> UpdateUserNotice()
        {
            var request = new UserNoticeRequest { Id = _loginContext.AccountId };
            var result = await _userRepository.UpdateUserNoticeAsync(request);
            if (result == false)
                throw new BusinessException("更新失败");
            return true;
        }

        /// <summary>
        /// 回复
        /// </summary>
        /// <returns></returns>
        [HttpPost("update-user-reply")]
        public async Task<bool> UpdateUserReply()
        {
            var request = new UserReplyRequest { Id = _loginContext.AccountId };
            var result = await _userRepository.UpdateUserReplyAsync(request);
            if (result == false)
                throw new BusinessException("更新失败");
            return true;
        }

        /// <summary>
        /// 静音
        /// </summary>
        /// <returns></returns>
        [HttpPost("update-user-mute")]
        public async Task<bool> UpdateUserMute()
        {
            var request = new UserMuteRequest { Id = _loginContext.AccountId };
            var result = await _userRepository.UpdateUserMuteAsync(request);
            if (result == false)
                throw new BusinessException("更新失败");
            return true;
        }

        /// <summary>
        /// 震动
        /// </summary>
        /// <returns></returns>
        [HttpPost("update-user-shake")]
        public async Task<bool> UpdateUserShake()
        {
            var request = new UserShakeRequest { Id = _loginContext.AccountId };
            var result = await _userRepository.UpdateUserShakeAsync(request);
            if (result == false)
                throw new BusinessException("更新失败");
            return true;
        }

        /// <summary>
        /// 用户修改手机号码
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("update-user-phone")]
        public async Task<bool> UpdateUserPhone(UserUpdatePhoneRequest request)
        {
            request.UserId = _loginContext.AccountId;
            var result = await _userRepository.UpdateUserPhoneAsync(request);
            if (result == false)
                throw new BusinessException("更新失败");
            return true;
        }

        /// <summary>
        /// 邮箱验证码
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("send-email-verify-code")]
        public async Task<bool> SendEmailVerifyCode(UserEmailVerifyCodeRequest request)
        {
            request.UserId = _loginContext.AccountId;
            var result = await _userRepository.SendEmailVerifyCodeAsync(request);
            if (result == false)
                throw new BusinessException("更新失败");
            return true;
        }

        /// <summary>
        /// 修改邮箱
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("update-user-email")]
        public async Task<bool> UpdateUserEmail(UserUpdateEmailRequest request)
        {
            request.UserId = _loginContext.AccountId;
            var result = await _userRepository.UpdateUserEmailAsync(request);
            if (result == false)
                throw new BusinessException("更新失败");
            return true;
        }

        /// <summary>
        /// 查询联系人
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("search")]
        public async Task<IEnumerable<UserInfoResult>> SearchUserName(SearchUserNameRequest request)
        {
            return await _userRepository.SearchUserNameAsync(request);
        }

        /// <summary>
        /// 根据部门ID获取自建ID获取用户列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("find")]
        public async Task<IEnumerable<UserInfoResult>> FindUser(FindUserRequest request)
        {
            request.UserId = _loginContext.AccountId;
            return await _userService.FindUser(request);
        }

        /// <summary>
        /// 根据部门ID获取自建ID获取用户列表
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpGet("find-name")]
        public async Task<IEnumerable<UserInfoResult>> FindUserByName([FromQuery] string name)
        {
            return await _userRepository.UserByNameAsync(name);
        }
        /// <summary>
        /// 根据GUID查询用户
        /// </summary>
        /// <returns></returns>
        [HttpPost("guid")]
        public async Task<UserDetail> FindUserByGuid(FindUserByGuidRequest request)
        {
            var user = await _userRepository.GetGuidAsync(request.Guid);
            return user;
        }
        /// <summary>
        /// 获取用户工作模块未读数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("user-uread-count")]
        public async Task<UserCountResult> GetUserCountAsync()
        {
            return await _userService.GetUserCountAsync(_loginContext.AccountId);
        }

        /// <summary>
        /// 根据用户名获取电脑上传的数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("user-file-library")]
        public async Task<IEnumerable<FileLibraryResult>> GetFileLibraryByUserIdAsync()
        {
            return await fileLibraryRepository.GetFileLibraryByUserIdAsync(_loginContext.AccountId);
        }
    }
}