using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Tiku.Application.Auth;
using Tiku.Domain.Identity;
using Tiku.Domain.Tenancy;

namespace Tiku.Infrastructure.Auth;

public sealed partial class AuthService
{
    public async Task<AuthenticationResult> LoginWithPasswordAsync(
        PasswordLoginRequest request,
        CancellationToken cancellationToken = default)
    {
        var identifier = request.Phone.Trim();
        var normalizedEmail = userManager.NormalizeEmail(identifier);
        var normalizedUserName = userManager.NormalizeName(identifier);
        var user = await dbContext.Users
            .SingleOrDefaultAsync(entity =>
                    entity.Phone == identifier ||
                    entity.NormalizedEmail == normalizedEmail ||
                    entity.NormalizedUserName == normalizedUserName,
                cancellationToken);
        var passwordResult = user is null || user.Status != UserStatus.Active
            ? SignInResult.Failed
            : await signInManager.CheckPasswordSignInAsync(user, request.Password, true);

        if (!passwordResult.Succeeded)
        {
            var loginResult = passwordResult.IsLockedOut
                ? AuthLoginResult.Blocked
                : AuthLoginResult.Failed;
            var failureCode = passwordResult.IsLockedOut
                ? "account_locked"
                : "invalid_credentials";
            await AddLoginEventAsync(
                request.TenantId,
                user?.Id,
                PasswordProvider,
                identifier,
                loginResult,
                failureCode,
                request.IpAddress,
                request.UserAgent,
                cancellationToken);
            throw new InvalidCredentialsException();
        }

        return await CompleteSuccessfulLoginAsync(
            request.Realm,
            request.TenantId,
            user!,
            PasswordProvider,
            identifier,
            request.IpAddress,
            request.UserAgent,
            cancellationToken);
    }
}