using Hotline.Caches;
using Hotline.Users;
using XF.Domain.Cache;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;

namespace Hotline.CacheManager;

public class UserCacheManager : IUserCacheManager, IScopeDependency
{
    private readonly ITypedCache<Work> _cacheWork;
    private readonly IWorkRepository _workRepository;

    public UserCacheManager(
        ITypedCache<Work> cacheWork,
        IWorkRepository workRepository)
    {
        _cacheWork = cacheWork;
        _workRepository = workRepository;
    }

    /// <summary>
    /// 查询用户当前工作记录
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public Work GetWorkByUser(string userId)
    {
        var work = _cacheWork.GetOrAdd(Work.GetKey(KeyMode.UserId, userId), k =>
        {
            var dbWork = _workRepository.GetCurrentWorkByUserAsync(userId)
                .GetAwaiter().GetResult();
            if (dbWork == null)
                throw new UserFriendlyException("该用户暂无工作记录");
            return dbWork;
        });
        return work;
    }

    /// <summary>
    /// 查询分机当前工作记录
    /// </summary>
    /// <param name="telNo"></param>
    /// <returns></returns>
    /// <exception cref="UserFriendlyException"></exception>
    public Work GetWorkByTel(string telNo)
    {
        var work = _cacheWork.GetOrAdd(Work.GetKey(KeyMode.TelNo, telNo), k =>
        {
            var dbWork = _workRepository.GetCurrentWorkByTelAsync(telNo)
                .GetAwaiter().GetResult();
            if (dbWork == null)
                throw new UserFriendlyException("该分机暂无工作记录");
            return dbWork;
        });
        return work;
    }

    /// <summary>
    /// 查询分机是否处于工作
    /// </summary>
    /// <param name="telNo"></param>
    /// <returns></returns>
    public async Task<bool> IsWorkingByTelAsync(string telNo, CancellationToken cancellationToken)
    {
        var work = _cacheWork.Get(Work.GetKey(KeyMode.TelNo, telNo));

        if (work is null)
        {
            var dbWork = await _workRepository.GetCurrentWorkByTelAsync(telNo, cancellationToken);
            if (dbWork != null)
            {
                _cacheWork.Add(Work.GetKey(KeyMode.TelNo, telNo), dbWork);
                return true;
            }
            return false;
        }
        return true;
    }

    /// <summary>
    /// 查询分机是否处于工作
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task<bool> IsWorkingByUserAsync(string userId, CancellationToken cancellationToken)
    {
        //return _cacheWork.TryGetOrAdd(Work.GetKey(KeyMode.UserId, userId),
        //    k => _workRepository.GetCurrentWorkByUserAsync(userId).GetAwaiter().GetResult(),
        //    out _);
        var work = _cacheWork.Get(Work.GetKey(KeyMode.UserId, userId));
        if (work is null)
        {
            var dbWork = await _workRepository.GetCurrentWorkByUserAsync(userId, cancellationToken);
            if (dbWork is null) return false;
            _cacheWork.Add(Work.GetKey(KeyMode.UserId, userId), dbWork);
        }

        return true;
    }

    /// <summary>
    /// 根据用户更新工作记录
    /// </summary>
    /// <param name="work"></param>
    /// <returns></returns>
    public void UpdateWorkByUser(Work work)
    {
        _cacheWork.Update(Work.GetKey(KeyMode.UserId, work.UserId), d => work);
        _cacheWork.Update(Work.GetKey(KeyMode.TelNo, work.TelNo), d => work);
    }
}