﻿// Copyright (c) 2016 BlueConcord. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace BlueConcord.IdentityServer.EntityFrameworkCore.Services
{
    public class ResourceOwnerPasswordValidator<TUser> : IResourceOwnerPasswordValidator where TUser : class
    {
        private readonly ILogger<ResourceOwnerPasswordValidator<TUser>> _logger;
        private readonly UserManager<TUser> _userManager;

        public ResourceOwnerPasswordValidator(ILogger<ResourceOwnerPasswordValidator<TUser>> logger,
                                              UserManager<TUser> userManager)
        {
            _logger = logger;
            _userManager = userManager;
        }

        public async Task<CustomGrantValidationResult> ValidateAsync(string userName, string password, ValidatedTokenRequest request)
        {
            if (string.IsNullOrEmpty(userName))
            {
                _logger.LogError("ValidateAsync::Missing userName");
                throw new ArgumentNullException(nameof(userName));
            }

            if (string.IsNullOrEmpty(password))
            {
                _logger.LogError("ValidateAsync::Missing password");
                throw new ArgumentNullException(nameof(password));
            }

            var user = await _userManager.FindByNameAsync(userName);
            if (user != null && await _userManager.CheckPasswordAsync(user, password))
            {
                var userId = await _userManager.GetUserIdAsync(user);

                _logger.LogDebug($"ValidateAsync {userName ?? "N/A"}. UserId: {userId ?? "N/A"}");

                return new CustomGrantValidationResult(userId, "password");
            }

            _logger.LogDebug($"ValidateAsync {userName ?? "N/A"} Failure.");
            return new CustomGrantValidationResult("Invalid username or password");
        }
    }
}
