using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Authorization;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.Extensions.Configuration;
using System.Linq;
using System;
using System.Text;
using System.Security.Claims;
using System.Collections.Generic;

using AutoMapper;

using skydiveLogs_api.Business.Interface;
using skydiveLogs_api.DataContract;
using skydiveLogs_api.Model;


namespace skydiveLogs_api.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : Base
    {
        public UserController(IUserService userService,
                              IMapper mapper,
                              IConfiguration configuration)
        {
            _userService = userService;
            _mapper = mapper;
            _jwtConf = configuration.GetSection("JWT")
                                    .GetChildren()
                                    .ToDictionary(d => d.Key, d => d.Value);
        }

        // GET: api/User/AlwayLogin
        [HttpGet("AlwayLogin")]
        [EnableCors]
        public IActionResult AlwayLogin()
        {
            return Ok();
        }


        // POST: api/User/Authenticate
        [AllowAnonymous]
        [HttpPost("Authenticate")]
        [EnableCors]
        public IActionResult Authenticate([FromBody] UserReq value)
        {
            IActionResult result;
            var foundUser = _userService.GetByLogin(value.Login, value.Password);

            if (foundUser == null)
            {
                result = BadRequest(new { message = "Username or password is incorrect" });
            }
            else
            {
                foundUser.Password = null;
                var resp = _mapper.Map<UserResp>(foundUser);
                resp.Token = CreateToken(resp);

                result = Ok(resp);
            }

            return result;
        }

        // POST: api/User
        [AllowAnonymous]
        [HttpPost]
        [EnableCors]
        public IActionResult Post([FromBody] UserReq userToAdd)
        {
            IActionResult result;
            var newUser = _mapper.Map<User>(userToAdd);
            var userAdded = _userService.AddNewUser(newUser);

            if (!userAdded)
            {
                result = BadRequest(new { message = "Error during the creation of the user." });
            }
            else
            {
                newUser.Password = null;
                var resp = _mapper.Map<UserResp>(newUser);
                resp.Token = CreateToken(resp);

                result = Ok(resp);
            }

            return result;
        }

        private string CreateToken(UserResp foundUser)
        {
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtConf["Key"]));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(issuer: _jwtConf["Issuer"],
                                             audience: _jwtConf["Issuer"],
                                             expires: DateTime.Now.AddDays(1),
                                             signingCredentials: credentials,
                                             claims: new Claim[]
                                             {
                                                new Claim(ClaimTypes.Name, foundUser.Login),
                                                new Claim(ClaimTypes.UserData, foundUser.Id.ToString())
                                             });

            return new JwtSecurityTokenHandler().WriteToken(token);
        }

        private readonly IUserService _userService;
        private readonly IMapper _mapper;
        private readonly Dictionary<string, string> _jwtConf;
    }
}
