namespace TaxBaik.Application.Services;

using TaxBaik.Domain.Entities;
using TaxBaik.Domain.Interfaces;

public class PortalUserService(IPortalUserRepository repository)
{
    public async Task<PortalUser?> GetByEmailAsync(string email, CancellationToken ct = default) =>
        await repository.GetByEmailAsync(email.Trim(), ct);

    public async Task<PortalUser?> GetByProviderAsync(string provider, string providerId, CancellationToken ct = default) =>
        await repository.GetByProviderAsync(provider.Trim(), providerId.Trim(), ct);

    public async Task<int> RegisterLocalAsync(string name, string email, string phone, string? passwordHash, int? clientId = null, CancellationToken ct = default) =>
        await RegisterAsync(name, email, phone, "local", null, passwordHash, clientId, ct);

    public async Task<int> RegisterOAuthAsync(string name, string email, string? phone, string provider, string providerId, int? clientId = null, CancellationToken ct = default) =>
        await RegisterAsync(name, email, phone, provider, providerId, null, clientId, ct);

    public async Task LinkOAuthAsync(PortalUser user, string provider, string providerId, string? displayName = null, string? email = null, CancellationToken ct = default)
    {
        user.Name = string.IsNullOrWhiteSpace(displayName) ? user.Name : displayName.Trim();
        user.Email = string.IsNullOrWhiteSpace(email) ? user.Email : email.Trim();
        if (string.IsNullOrWhiteSpace(user.PasswordHash))
        {
            user.Provider = provider.Trim();
            user.ProviderId = providerId.Trim();
        }
        await repository.UpdateAsync(user, ct);
    }

    public async Task AttachClientAsync(PortalUser user, int clientId, CancellationToken ct = default)
    {
        user.ClientId = clientId;
        await repository.UpdateAsync(user, ct);
    }

    private async Task<int> RegisterAsync(string name, string email, string? phone, string provider, string? providerId, string? passwordHash, int? clientId, CancellationToken ct)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new ValidationException("이름을 입력하세요.");
        if (string.IsNullOrWhiteSpace(email))
            throw new ValidationException("이메일을 입력하세요.");

        var user = new PortalUser
        {
            ClientId = clientId,
            Name = name.Trim(),
            Email = email.Trim(),
            Phone = string.IsNullOrWhiteSpace(phone) ? null : phone.Trim(),
            Provider = provider,
            ProviderId = providerId,
            PasswordHash = passwordHash,
            CreatedAt = DateTime.UtcNow
        };

        return await repository.CreateAsync(user, ct);
    }
}
