using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Knot.Contracts.Auth.Application.Abstractions;
using Knot.Contracts.Auth.Application.Auth.DTOs;
using Knot.Shared.Kernel;

namespace Knot.Modules.Auth.Application.Users.GetMe;

public sealed record GetMeQuery(Guid UserId) : IQuery<AuthResponseDto>;

internal sealed class GetMeQueryHandler : IQueryHandler<GetMeQuery, AuthResponseDto>
{
    private readonly IUserRepository _userRepository;
    private readonly IJwtTokenProvider _tokenProvider;

    public GetMeQueryHandler(IUserRepository userRepository, IJwtTokenProvider tokenProvider)
    {
        _userRepository = userRepository;
        _tokenProvider = tokenProvider;
    }

    public async Task<Result<AuthResponseDto>> Handle(GetMeQuery request, CancellationToken cancellationToken)
    {
        var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);
        if (user == null)
        {
            return Result.Failure<AuthResponseDto>(AuthErrors.UserNotFound);
        }

        // Check if access token needs to be refreshed (less than 1 hour remaining)
        string? newAccessToken = null;

        // We can't directly check the current token's expiry here, but we can 
        // always issue a new token if the user is authenticated
        // For now, let's issue a new token on every request (simplified approach)
        // A better approach would be to parse the incoming token and check expiry
        newAccessToken = _tokenProvider.Generate(user);

        var response = new AuthResponseDto
        {
            AccessToken = newAccessToken,
            RefreshToken = string.Empty,
            UserId = user.Id,
            Username = user.Username,
            DisplayName = user.DisplayName,
            Avatar = user.Avatar
        };

        return Result.Success(response);
    }
}
