using DotNetCore.CAP;
using Hotline.Share.Dtos.CallCenter;
using Hotline.Share.Mq;
using MapsterMapper;
using XF.Domain.Cache;
using XF.Domain.Dependency;

namespace Hotline.CallCenter.BlackLists;

public class BlacklistDomainService : IBlacklistDomainService, IScopeDependency
{
    private readonly ITypedCache<Blacklist> _blackCache;
    private readonly IBlacklistRepository _blacklistRepository;
    private readonly IMapper _mapper;
    private readonly ICapPublisher _capPublisher;

    public BlacklistDomainService(
        ITypedCache<Blacklist> blackCache,
        IBlacklistRepository blacklistRepository,
        IMapper mapper,
        ICapPublisher capPublisher)
    {
        _blackCache = blackCache;
        _blacklistRepository = blacklistRepository;
        _mapper = mapper;
        _capPublisher = capPublisher;
    }

    /// <summary>
    /// 将电话加入黑名单
    /// </summary>
    public async Task AddAsync(AddBlacklistDto dto, CancellationToken cancellationToken = default)
    {
        var cache = await _blackCache.GetOrSetAsync(
            Blacklist.GetKey(dto.Phone),
            k => _blacklistRepository.Queryable().FirstAsync(d => d.PhoneNo == dto.Phone).GetAwaiter().GetResult(),
            TimeSpan.FromSeconds(dto.Duration),
            cancellationToken);
        if (cache != null) return;

        var blacklist = _mapper.Map<Blacklist>(dto);
        await _blacklistRepository.AddAsync(blacklist, cancellationToken);
        await _blackCache.SetAsync(Blacklist.GetKey(blacklist.PhoneNo), blacklist, TimeSpan.FromSeconds(blacklist.Duration), cancellationToken);
        await _capPublisher.PublishDelayAsync(TimeSpan.FromSeconds(blacklist.Duration),
            EventNames.CallCenterBlackListExpired, blacklist.PhoneNo, cancellationToken: cancellationToken);
    }

    /// <summary>
    /// 删除黑名单信息
    /// </summary>
    public async Task RemoveAsync(string phoneNo, CancellationToken cancellationToken = default)
    {
        await _blackCache.RemoveAsync(Blacklist.GetKey(phoneNo), cancellationToken);
        var items = await _blacklistRepository.Queryable().Where(d => d.PhoneNo == phoneNo).ToListAsync();
        if (items.Any())
        {
            foreach (var blacklist in items)
            {
                await _blacklistRepository.RemoveAsync(blacklist, true, cancellationToken);
            }
        }
    }

    /// <summary>
    /// 是否在黑名单中
    /// </summary>
    /// <param name="phoneNo"></param>
    /// <returns></returns>
    public bool IsInBlacklist(string phoneNo)
    {
        var blacklist = _blackCache.Get(Blacklist.GetKey(phoneNo));
        return blacklist != null;
    }
}