using MemberCenter.Application.Abstractions;
using MemberCenter.Application.Models.Admin;
using MemberCenter.Domain.Entities;
using MemberCenter.Infrastructure.Identity;
using MemberCenter.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;

namespace MemberCenter.Infrastructure.Services;

public sealed class EmailBlacklistService : IEmailBlacklistService
{
    private readonly MemberCenterDbContext _dbContext;

    public EmailBlacklistService(MemberCenterDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public Task<bool> IsBlacklistedAsync(string email)
    {
        var normalized = Normalize(email);
        return _dbContext.EmailBlacklist.AnyAsync(x => x.Email == normalized);
    }

    public async Task AddOrUpdateAsync(string email, string reason, string blacklistedBy, DateTimeOffset occurredAt)
    {
        var normalized = Normalize(email);
        var existing = await _dbContext.EmailBlacklist.FirstOrDefaultAsync(x => x.Email == normalized);
        if (existing is null)
        {
            _dbContext.EmailBlacklist.Add(new EmailBlacklist
            {
                Id = Guid.NewGuid(),
                Email = normalized,
                Reason = reason,
                BlacklistedAt = occurredAt,
                BlacklistedBy = blacklistedBy
            });
        }
        else
        {
            existing.Reason = reason;
            existing.BlacklistedAt = occurredAt;
            existing.BlacklistedBy = blacklistedBy;
        }

        var user = await _dbContext.Set<ApplicationUser>()
            .FirstOrDefaultAsync(u => u.Email != null && u.Email.ToLower() == normalized);
        if (user is not null)
        {
            user.IsBlacklisted = true;
            user.BlacklistedAt = occurredAt;
            user.BlacklistedBy = blacklistedBy;
        }

        await _dbContext.SaveChangesAsync();
    }

    public async Task<IReadOnlyList<EmailBlacklistDto>> ListAsync(int take = 200)
    {
        var items = await _dbContext.EmailBlacklist
            .OrderByDescending(x => x.BlacklistedAt)
            .Take(take)
            .ToListAsync();

        return items.Select(x => new EmailBlacklistDto(
            x.Email,
            x.Reason,
            x.BlacklistedBy,
            x.BlacklistedAt)).ToList();
    }

    private static string Normalize(string email)
    {
        return email.Trim().ToLowerInvariant();
    }
}
