using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Collections.Concurrent;
using Microsoft.AspNetCore.Mvc.Filters;
using WebApplication1.Models;

namespace WebApplication1.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AuthController : ControllerBase
    {
        private readonly IConfiguration _configuration;
        private static ConcurrentDictionary<string, User> _users = new ConcurrentDictionary<string, User>();
        private static ConcurrentDictionary<string, DateTime> _tokenBlacklist = new ConcurrentDictionary<string, DateTime>();

        public AuthController(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        [HttpPost("register")]
        public ActionResult<User> Register(UserDto request)
        {
            var user = new User
            {
                Username = request.Username,
                PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.Password)
            };

            if (!_users.TryAdd(user.Username, user))
            {
                return Conflict("User already exists.");
            }

            return Ok(user);
        }

        [HttpPost("login")]
        public ActionResult<string> Login(UserDto request)
        {
            if (_users.TryGetValue(request.Username, out var user))
            {
                if (!BCrypt.Net.BCrypt.Verify(request.Password, user.PasswordHash))
                {
                    return BadRequest("Incorrect password.");
                }

                string token = CreateToken(user);
                return Ok(token);
            }
            else
            {
                return BadRequest("User not found.");
            }
        }

        [HttpPost("logout")]
        public IActionResult Logout(string token)
        {
            if (InvalidateToken(token))
            {
                return Ok("Logged out successfully.");
            }

            return BadRequest("Invalid token.");
        }

        private bool InvalidateToken(string token)
        {
            var handler = new JwtSecurityTokenHandler();
            var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
            if (jwtToken == null)
            {
                return false;
            }

            DateTime expiration = jwtToken.ValidTo;
            return _tokenBlacklist.TryAdd(token, expiration);
        }

        private string CreateToken(User user)
        {
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, user.Username)
            };

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["AppSettings:Token"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
                claims: claims,
                expires: DateTime.Now.AddDays(1),
                signingCredentials: creds);

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

    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
    public class JwtBlacklistFilter : Attribute, IAsyncActionFilter
    {
        private readonly ConcurrentDictionary<string, DateTime> _tokenBlacklist;

        public JwtBlacklistFilter(ConcurrentDictionary<string, DateTime> tokenBlacklist)
        {
            _tokenBlacklist = tokenBlacklist;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            if (context.HttpContext.Request.Headers.TryGetValue("Authorization", out var token))
            {
                token = token.ToString().Replace("Bearer ", "");

                if (_tokenBlacklist.TryGetValue(token, out var expiration))
                {
                    if (expiration > DateTime.UtcNow)
                    {
                        context.Result = new UnauthorizedResult();
                        return;
                    }
                    else
                    {
                        _tokenBlacklist.TryRemove(token, out _);
                    }
                }
            }

            await next();
        }
    }
}


میخواهم کد ام را به دیتابیس وصل کنم