using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Identity;
using Cloud.Models;
using Cloud.Requests;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using Microsoft.EntityFrameworkCore; 
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;

namespace Cloud.Controllers;

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    private PasswordHasher<User> _passwordHasher;
    private IConfiguration _config;
    private ApplicationContext _context;

    public AuthController(IConfiguration config, ApplicationContext context)
    {
        _passwordHasher = new PasswordHasher<User>();
        _config = config;
        _context = context;
    }

    [HttpPost("register")]
    public async Task<IActionResult> Register([FromBody] RegisterRequest request)
    {
        var existUser = await _context.Users.SingleOrDefaultAsync(u => u.Email == request.Email);

        if (existUser != null) {
            return BadRequest("Пользователь с такой эл. почтой уже существует");
        }

        var user = new User
        {
            Name = request.Name,
            Email = request.Email,
            Password = _passwordHasher.HashPassword(null, request.Password)
        };

        _context.Users.Add(user);
        await _context.SaveChangesAsync();

        return Ok("Пользователь успешно зарегистрирован");
    }

    [HttpPost("login")]
    public async Task<IActionResult> Login([FromBody] LoginRequest request)
    {
        var user = await _context.Users.SingleOrDefaultAsync(u => u.Email == request.Email);

        if (user == null) {
            return Unauthorized("Пользователя с такой эл. почтой не существует");
        }

        var verificationResult = _passwordHasher.VerifyHashedPassword(null, user.Password, request.Password);
        
        if (verificationResult == PasswordVerificationResult.Failed) {
            return Unauthorized("Неверный пароль");
        }

        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        var claims = new[]
        {
            new Claim(ClaimTypes.Name, user.Email),
        };

        var Sectoken = new JwtSecurityToken(_config["Jwt:Issuer"],
            _config["Jwt:Issuer"],
            claims: claims,
            expires: DateTime.Now.AddMinutes(120),
            signingCredentials: credentials);

        var token =  new JwtSecurityTokenHandler().WriteToken(Sectoken);

        return Ok(token);
    }

    [Authorize]
    [HttpGet("user")]
    public async Task<IActionResult> GetAuthUser()
    {
        var userEmail = User.Identity.Name;

        var user = await _context.Users.SingleOrDefaultAsync(u => u.Email == userEmail);

        if (user == null) {
            return NotFound("Пользователь не найден");
        }

        return Ok(new 
        {
            user.Id,
            user.Name,
            user.Email
        });
    }
}