using FluentValidation;
using MediatR;
using Microsoft.AspNetCore.Identity;
using SolutionErp.Application.Common.Exceptions;
using SolutionErp.Application.Common.Interfaces;
using SolutionErp.Domain.Identity;

namespace SolutionErp.Application.Auth.Commands.ChangePassword;

// Self-service đổi mật khẩu — user đang đăng nhập TỰ đổi, BẮT BUỘC nhập mật khẩu hiện tại
// để xác thực. Khác ResetPasswordCommand (admin đặt pass hộ theo userId, KHÔNG cần pass cũ).
public record ChangePasswordCommand(string CurrentPassword, string NewPassword) : IRequest;

public class ChangePasswordCommandValidator : AbstractValidator<ChangePasswordCommand>
{
    public ChangePasswordCommandValidator()
    {
        RuleFor(x => x.CurrentPassword)
            .NotEmpty().WithMessage("Vui lòng nhập mật khẩu hiện tại.");
        RuleFor(x => x.NewPassword)
            .NotEmpty().WithMessage("Vui lòng nhập mật khẩu mới.")
            .MinimumLength(12).WithMessage("Mật khẩu mới phải có ít nhất 12 ký tự.");
        RuleFor(x => x.NewPassword)
            .NotEqual(x => x.CurrentPassword).WithMessage("Mật khẩu mới phải khác mật khẩu hiện tại.")
            .When(x => !string.IsNullOrEmpty(x.NewPassword) && !string.IsNullOrEmpty(x.CurrentPassword));
    }
}

public class ChangePasswordCommandHandler(
    UserManager<User> userManager,
    ICurrentUser currentUser) : IRequestHandler<ChangePasswordCommand>
{
    public async Task Handle(ChangePasswordCommand request, CancellationToken ct)
    {
        if (!currentUser.IsAuthenticated || currentUser.UserId is null)
            throw new UnauthorizedException();

        var user = await userManager.FindByIdAsync(currentUser.UserId.Value.ToString())
            ?? throw new UnauthorizedException();

        // Identity tự verify CurrentPassword — sai mật khẩu cũ => result.Errors có code "PasswordMismatch".
        // Luật mật khẩu mới (độ dài, ...) cũng do Identity + validator ở trên kiểm.
        var result = await userManager.ChangePasswordAsync(user, request.CurrentPassword, request.NewPassword);
        if (!result.Succeeded)
        {
            var failures = result.Errors.Select(e => new FluentValidation.Results.ValidationFailure(
                e.Code == "PasswordMismatch" ? nameof(request.CurrentPassword) : nameof(request.NewPassword),
                e.Code == "PasswordMismatch" ? "Mật khẩu hiện tại không đúng." : e.Description));
            throw new SolutionErp.Application.Common.Exceptions.ValidationException(failures);
        }

        // Vô hiệu refresh token (mirror ResetPasswordCommand) → các phiên hiện có sẽ phải
        // đăng nhập lại bằng mật khẩu mới khi access token hết hạn.
        user.RefreshToken = null;
        user.RefreshTokenExpiresAt = null;
        await userManager.UpdateAsync(user);
    }
}
