namespace OBSBoardsWWW
{
    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Http;
    using Newtonsoft.Json;
    using System.IdentityModel.Tokens.Jwt;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    
    public class JwtTokenMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IHttpClientFactory _httpClientFactory;

        public JwtTokenMiddleware(RequestDelegate next, IHttpClientFactory httpClientFactory)
        {
            _next = next;
            _httpClientFactory = httpClientFactory;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            var token = context.Session.GetString("AccessToken");
            var expirationString = context.Session.GetString("TokenExpiration");

            if (!string.IsNullOrEmpty(token) && DateTime.TryParse(expirationString, out DateTime expiration))
            {
                // Sprawdź, czy token wygaśnie w ciągu następnych 1 minut
                if (expiration < DateTime.UtcNow.AddMinutes(1))
                {
                    // Wywołaj funkcję odświeżania tokena
                    token = await RefreshToken(context);
                }

                // Dodaj token do nagłówka Authorization
                context.Request.Headers["Authorization"] = $"Bearer {token}";
            }

            await _next(context);
        }

        private async Task<string> RefreshToken(HttpContext context)
        {
            var accessToken = context.Session.GetString("AccessToken");
            var refreshToken = context.Session.GetString("RefreshToken");

            if (!string.IsNullOrEmpty(refreshToken))
            {
                var client = _httpClientFactory.CreateClient();
                var content = new StringContent(JsonConvert.SerializeObject(new { Token = accessToken, RefreshToken = refreshToken }), Encoding.UTF8, "application/json");
                var response = await client.PostAsync("https://localhost:44372/api/Authenticate/RefreshToken", content);

                if (response.IsSuccessStatusCode)
                {
                    var responseContent = await response.Content.ReadAsStringAsync();
                    var newTokenData = JsonConvert.DeserializeObject<TokenModel>(responseContent);

                    // Przechowaj nowy token i datę wygaśnięcia w sesji
                    context.Session.SetString("AccessToken", newTokenData.Token);

                    var jwtToken = new JwtSecurityTokenHandler().ReadToken(newTokenData.Token) as JwtSecurityToken;
                    var newExpiration = jwtToken.ValidTo;
                    context.Session.SetString("TokenExpiration", newExpiration.ToString());

                    return newTokenData.Token;
                }
            }

            // Jeśli odświeżenie tokena się nie powiodło, wyloguj użytkownika
            await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            context.Session.Remove("AccessToken");
            context.Session.Remove("RefreshToken");
            context.Session.Remove("TokenExpiration");

            context.Response.Redirect("/Auth/Login");
            return null;
        }
        public class TokenModel
        {
            public string Token { get; set; }
            public string RefreshToken { get; set; }
        }
    }
}
