using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using MTWorkHR.Application.Exceptions;
using MTWorkHR.Application.Filters;
using MTWorkHR.Application.Identity;
using MTWorkHR.Application.Mapper;
using MTWorkHR.Application.Models;
using MTWorkHR.Application.Services.Interfaces;
using MTWorkHR.Core.Global;
using MTWorkHR.Infrastructure.Entities;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace MTWorkHR.Identity.Services
{
    public class AuthService : IAuthService
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly AppSettingsConfiguration _configuration;
        private readonly IUserService _userService;

        public AuthService(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, AppSettingsConfiguration configuration, IUserService userService) 
        {
            _userManager = userManager;
            _signInManager = signInManager;
            _configuration = configuration;
            _userService = userService;
        }
        public async Task<AuthResponse> Login(AuthRequest request)
        {
            var user = await _userManager.FindByEmailAsync(request.Email);           
            if (user == null)
            {
                throw new AppException(ExceptionEnum.RecordNotExist);
            }
            var result = await _signInManager.CheckPasswordSignInAsync(user, request.Password, false);
            if(!result.Succeeded)
            {
                throw new AppException($"Credentials for '{request.Email} are not valid'.");
            }
            var userResponse = await _userService.GetById(user.Id);

            JwtSecurityToken jwtToken = await GenerateToken(user);

            var response = new AuthResponse
            {
                User = userResponse,
                //Id = user.Id,
                //Email = user.Email,
                //UserName = user.UserName,
                //UserTypeId = user.UserType,
                Token = new JwtSecurityTokenHandler().WriteToken( jwtToken),
                Expiration = jwtToken.ValidTo
            };
            return response;
        }
        //public async Task<RegistrationResponse> Register(RegistrationRequest request)
        //{
        //    var user = new ApplicationUser { 
        //        Email = request.Email ,
        //        UserName = request.UserName ,
        //        FirstName = request.FirstName ,
        //        LastName = request.LastName ,
        //        EmailConfirmed  = true
        //    };
        //    var result = await _userManager.CreateAsync(user, request.Password);
        //    if (result.Succeeded)
        //    {
        //        await _userManager.AddToRoleAsync(user, request.RoleName);
        //        return new RegistrationResponse(){ UserId = user.Id };
        //    }
        //    else
        //    {
        //        StringBuilder str = new StringBuilder();
        //        foreach (var err in result.Errors)
        //        {
        //            str.AppendFormat(".{0}\n", err.Description);
        //        }
        //        throw new BadRequest($"{str}");
        //    }
        //}

      

        private async Task<JwtSecurityToken> GenerateToken(ApplicationUser user)
        {
            var userCalims = await _userManager.GetClaimsAsync(user);
            var roles = await _userManager.GetRolesAsync(user);
            var roleClaims = roles.Select(r => new Claim(ClaimTypes.Role, r)).ToList();
            var claims = new[]
            {
                new Claim(JwtRegisteredClaimNames.Name, user.UserName),
                new Claim(JwtRegisteredClaimNames.Email, user.Email),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim("companyId", user.CompanyId+""),
                new Claim("uid", user.Id)
            }.Union(userCalims)
            .Union(roleClaims);
            var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration.JwtSettings.SecretKey));
            var signingCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256);
            var jwtSecurityToken = new JwtSecurityToken(
                issuer: _configuration.JwtSettings.Issuer,
                audience: _configuration.JwtSettings.Audience,
                claims: claims,
                expires: DateTime.Now.AddMinutes(_configuration.JwtSettings.DurationInMinutes),
                signingCredentials: signingCredentials
                );
            return jwtSecurityToken;
        }

       
    }
  
}