using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using Performance.DtoModels;
using Performance.DtoModels.AppSettings;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Performance.Api.Controllers
{
    [Route("api/[controller]")]
    public class AccountController : Controller
    {
        private UserService _userService;
        private RoleService _roleService;
        private IMemoryCache _memoryCache;
        private Application _options;
        private ClaimService _claim;
        private HospitalService _hospitalService;
        public AccountController(UserService userService,
            HospitalService hospitalService,
            RoleService roleService,
            IMemoryCache memoryCache,
            IOptions<Application> options,
            ClaimService claim)
        {
            _userService = userService;
            _roleService = roleService;
            _memoryCache = memoryCache;
            _hospitalService = hospitalService;
            _options = options.Value;
            _claim = claim;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns> 
        [HttpPost]
        [Route("login")]
        [AllowAnonymous]
        public ApiResponse<JwtToken> Login([FromBody]LoginRequest request)
        {
            var user = _userService.Login(request);
            if (user == null)
                return new ApiResponse<JwtToken>(ResponseType.Fail, "用户不存在");

            var claims = new Claim[]
            {
                new Claim(JwtClaimTypes.Id, user.UserID.ToString()),
                new Claim(JwtClaimTypes.Login, user.Login),
                new Claim(JwtClaimTypes.RealName,  user.RealName),
                new Claim(JwtClaimTypes.Mail, user.Mail),
                new Claim(JwtClaimTypes.AppName, request.AppName ?? ""),
                new Claim(JwtClaimTypes.Device, request.Device ?? ""),
                new Claim(JwtClaimTypes.Department, user.Department ?? ""),
            };

            var jwtToken = JwtTokenHelper.GenerateToken(claims, _options.ExpirationMinutes);
            return new ApiResponse<JwtToken>(ResponseType.OK, jwtToken);
        }

        /// <summary>
        /// 刷新登录JWT TOKEN
        /// </summary>
        /// <returns></returns> 
        [HttpPost]
        [Route("refresh")]
        public ApiResponse<JwtToken> Refresh()
        {
            var userClaim = _claim.GetUserClaim();
            var claims = new Claim[]
            {
                new Claim(JwtClaimTypes.Id, userClaim.FirstOrDefault(t => t.Type == JwtClaimTypes.Id).Value),
                new Claim(JwtClaimTypes.Login, userClaim.FirstOrDefault(t => t.Type == JwtClaimTypes.Login).Value),
                new Claim(JwtClaimTypes.RealName,  userClaim.FirstOrDefault(t => t.Type == JwtClaimTypes.RealName).Value),
                new Claim(JwtClaimTypes.Mail, userClaim.FirstOrDefault(t => t.Type == JwtClaimTypes.Mail).Value),
                new Claim(JwtClaimTypes.AppName, userClaim.FirstOrDefault(t => t.Type == JwtClaimTypes.AppName).Value),
                new Claim(JwtClaimTypes.Device, userClaim.FirstOrDefault(t => t.Type == JwtClaimTypes.Device).Value),
                new Claim(JwtClaimTypes.Department, userClaim.FirstOrDefault(t => t.Type == JwtClaimTypes.Department).Value),
            };

            var jwtToken = JwtTokenHelper.GenerateToken(claims, _options.ExpirationMinutes);
            // 设置当前请求Jwt失效
            var jwt = _claim.GetJwtToken();
            //claimService.SetJwtBlacklist(jwt);

            return new ApiResponse<JwtToken>(ResponseType.OK, jwtToken);
        }
        /// <summary>
        /// 查询个人信息
        /// </summary>
        /// <returns></returns>
        [Route("selfinfo")]
        [HttpPost]
        public ApiResponse SelfInfo()
        {
            var userid = _claim.GetUserId();
            var user = _userService.GetUser(userid);
            user.Role = _roleService.GetUserRole(user.UserID);
            user.Hospital = _hospitalService.GetUserHopital(user.UserID);

            int[] roleArray = new int[] { _options.NurseRole, _options.DirectorRole };
            user.IsAgainAdmin = user.Role != null ? roleArray.Contains(user.Role.First().Type ?? 0) : false;
            return new ApiResponse(ResponseType.OK, user);
        }

        /// <summary>
        /// 修改个人信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("updateself")]
        [HttpPost]
        public ApiResponse<UserResponse> UpdateSelf([CustomizeValidator(RuleSet = "Self"), FromBody]UserRequest request)
        {
            request.ID = _claim.GetUserId();
            var user = _userService.UpdateSelf(request);
            return new ApiResponse<UserResponse>(ResponseType.OK, user);
        }

        /// <summary>
        /// 用户列表
        /// </summary>
        /// <returns></returns>
        [Route("list")]
        [HttpPost]
        public ApiResponse<List<UserResponse>> List()
        {
            var userList = _userService.GetUserList(_claim.GetUserId());
            return new ApiResponse<List<UserResponse>>(ResponseType.OK, "ok", userList);
        }

        /// <summary>
        /// 新增用户
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("insert")]
        [HttpPost]
        public ApiResponse<UserResponse> Insert([CustomizeValidator(RuleSet = "Insert"), FromBody]UserRequest request)
        {
            var userId = _claim.GetUserId();
            var user = _userService.Insert(request, userId);
            user.Role = request.Role;
            return new ApiResponse<UserResponse>(ResponseType.OK, user);
        }

        /// <summary>
        /// 新增用户
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("delete")]
        [HttpPost]
        public ApiResponse Delete([CustomizeValidator(RuleSet = "Delete"), FromBody]UserRequest request)
        {
            return _userService.Delete(request.ID);
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("update")]
        [HttpPost]
        public ApiResponse<UserResponse> Update([CustomizeValidator(RuleSet = "Update"), FromBody]UserRequest request)
        {
            var userId = _claim.GetUserId();

            int[] roleArray = new int[] { _options.NurseRole, _options.DirectorRole };
            var roles = _roleService.GetUserRole(userId);
            var isAgainAdmin = roles != null ? roleArray.Contains(roles.First().Type ?? 0) : false;

            var user = _userService.Update(request, isAgainAdmin);
            user.Role = request.Role;
            return new ApiResponse<UserResponse>(ResponseType.OK, user);
        }

        /// <summary>
        /// 修改用户密码
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("password")]
        [HttpPost]
        public ApiResponse<UserResponse> Password([FromBody]PasswordRequest request)
        {
            var userid = _claim.GetUserId();
            var user = _userService.UpdatePwd(request, userid);
            return new ApiResponse<UserResponse>(ResponseType.OK, user);
        }

        /// <summary>
        /// 角色列表
        /// </summary>
        /// <returns></returns>
        [Route("rolelist")]
        [HttpPost]
        public ApiResponse<List<sys_role>> RoleList()
        {
            var userid = _claim.GetUserId();
            var roleList = _userService.RoleList(userid);
            return new ApiResponse<List<sys_role>>(ResponseType.OK, "ok", roleList);
        }

        /// <summary>
        /// 科室列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("department")]
        [HttpPost]
        public ApiResponse<List<TitleValue>> Department([FromBody]SetDepartmentRequest request)
        {
            var department = _userService.Department(request.HospitalID);
            return new ApiResponse<List<TitleValue>>(ResponseType.OK, "ok", department);
        }
    }
}
