using Tiku.Application.Auth;
using Tiku.Domain.Tenancy;

namespace Tiku.Infrastructure.Auth;

internal sealed class SelfHostedIdentityProvider(
    IPasswordLoginService passwordLoginService,
    ISmsLoginService smsLoginService,
    IWechatLoginService wechatLoginService) : IIdentityProvider
{
    public async Task<IdentityProviderResult> AuthenticateAsync(
        IdentityProviderRequest request,
        CancellationToken cancellationToken = default)
    {
        var provider = request.Provider.Trim().ToLowerInvariant().Replace("-", "_", StringComparison.Ordinal);
        var authenticated = provider switch
        {
            "password" => await passwordLoginService.LoginWithPasswordAsync(
                new PasswordLoginRequest(
                    AuthRealm.Tenant,
                    request.TenantId,
                    request.Identifier,
                    request.Secret,
                    request.IpAddress,
                    request.UserAgent),
                cancellationToken),
            "sms" => await smsLoginService.LoginWithSmsAsync(
                new SmsLoginRequest(
                    AuthRealm.Tenant,
                    request.TenantId,
                    request.Identifier,
                    request.Secret,
                    request.IpAddress,
                    request.UserAgent),
                cancellationToken),
            "wechat_web" => await wechatLoginService.LoginWithWechatWebAsync(
                new WechatLoginRequest(
                    AuthRealm.Tenant,
                    request.TenantId,
                    request.Secret,
                    request.IpAddress,
                    request.UserAgent),
                cancellationToken),
            "wechat_miniapp" => await wechatLoginService.LoginWithWechatMiniAppAsync(
                new WechatLoginRequest(
                    AuthRealm.Tenant,
                    request.TenantId,
                    request.Secret,
                    request.IpAddress,
                    request.UserAgent),
                cancellationToken),
            _ => throw new AuthProviderNotConfiguredException(provider)
        };

        var user = authenticated.User ?? throw new InvalidAuthChallengeException("interactive_authentication_required");

        return new IdentityProviderResult(
            provider,
            user.UserId.ToString("N"),
            user.Phone,
            user.Email,
            user.Name);
    }
}
