using Hotline.Caching.Interfaces;
using Hotline.CallCenter.Calls;
using Hotline.CallCenter.Tels;
using Hotline.Settings;
using Hotline.Share.Dtos.CallCenter;
using Hotline.Share.Dtos.TrCallCenter;
using Hotline.Share.Enums.CallCenter;
using Hotline.Users;
using Microsoft.AspNetCore.Http;
using Tr.Sdk;
using XF.Domain.Authentications;
using XF.Domain.Cache;
using XF.Domain.Constants;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using XF.Domain.Repository;

namespace Hotline.Application.CallCenter.Calls
{
    public class TrApplication : ITrApplication//, IScopeDependency
    {
        private readonly ITrClient _trClient;
        private readonly ISessionContext _sessionContext;
        private readonly IWorkRepository _workRepository;
        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
        private readonly IUserCacheManager _userCacheManager;
        private readonly ITelRestRepository _telRestRepository;
        private readonly ITypedCache<Work> _cacheWork;
        private readonly IRepository<TelCallModel> _telCallModelRepository;
        private readonly IRepository<TelActionRecord> _telActionRecordRepository;

        public TrApplication(ITrClient trClient, ISessionContext sessionContext,IWorkRepository workRepository,ISystemSettingCacheManager systemSettingCacheManager,IUserCacheManager userCacheManager, ITelRestRepository telRestRepository, ITypedCache<Work> cacheWork,IRepository<TelCallModel> telCallModelRepository,IRepository<TelActionRecord> telActionRecordRepository)
        {
            _trClient = trClient;
            _sessionContext = sessionContext;
            _workRepository = workRepository;
            _systemSettingCacheManager = systemSettingCacheManager;
            _userCacheManager = userCacheManager;
            _telRestRepository = telRestRepository;
            _cacheWork = cacheWork;
            _telCallModelRepository = telCallModelRepository;
            _telActionRecordRepository = telActionRecordRepository;
        }

        /// <summary>
        /// 签入
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="telNo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TrOnDutyResponseDto> OnSign(string userId,string telNo,ETelModel telModelState,CancellationToken cancellationToken)
        {
            var work = _userCacheManager.GetWorkByUserNoExp(userId);
            if (work is not null)
            {
                
                if (work.TelNo != telNo)
                {
                    throw UserFriendlyException.SameMessage("当前用户已签入其他分机");
                }
            }

            var telWork = _userCacheManager.GetWorkByTelNoExp(telNo);
            if (telWork is not null)
            {
                throw UserFriendlyException.SameMessage("当前分机已被占用");
            }

            var telModel = await _trClient.QueryTelsAsync(new Tr.Sdk.Tels.QueryTelRequest() { TelNo = telNo }, cancellationToken);
            if (telModel !=null && telModel.Count>0)
            {
                work = new Work(_sessionContext.UserId, _sessionContext.UserName, telModel[0].Id, telNo, telModel[0].Password, telModel[0].Description, telModel[0].QueueId,_sessionContext.StaffNo, telModelState);
                await _workRepository.AddAsync(work, cancellationToken);
                //记录签入日志
                var actionRecord = new TelActionRecord(work.UserId, work.UserName, work.TelNo, work.QueueId, EActionType.SignIn);
                //记录外呼模式日志
                var CallOutModelActionRecord = new TelActionRecord(work.UserId, work.UserName, work.TelNo, work.QueueId, EActionType.TelCallOut);

                await _telActionRecordRepository.AddAsync(actionRecord, cancellationToken);
                await _telActionRecordRepository.AddAsync(CallOutModelActionRecord, cancellationToken);

                bool IsTelNeedVerify = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.IsTelNeedVerify).SettingValue[0]);
                string callOutQueueId = _systemSettingCacheManager.GetSetting(SettingConstants.CallOutQueueId).SettingValue[0];
                if (IsTelNeedVerify)
                {
                    return new TrOnDutyResponseDto() { QueueCallOut = callOutQueueId,TelModel = telModelState, TelNo = telNo, TelPwd = "", Description = telModel[0].Description, QueueId = telModel[0].QueueId,StartTime = work.StartTime};
                }
                else
                {
                    return new TrOnDutyResponseDto() { QueueCallOut = callOutQueueId, TelModel = telModelState, TelNo = telNo, TelPwd = telModel[0].Password, Description = telModel[0].Description, QueueId = telModel[0].QueueId,StartTime = work.StartTime };
                }
            }
            throw UserFriendlyException.SameMessage("签入异常，未查询到对应分机信息");
        }

        /// <summary>
        /// 查询当前用户的分机状态
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<TrOnDutyResponseDto> TelState(string userId, CancellationToken cancellationToken)
        {
            var work = _userCacheManager.GetWorkByUserNoExp(userId);
            if (work is not null)
            {
                
                bool isRest = await _telRestRepository.AnyAsync(x => x.TelNo == work.TelNo && x.UserId == userId && !x.EndTime.HasValue,cancellationToken);

                bool isCallHold = await _telActionRecordRepository.AnyAsync(x => x.TelNo == work.TelNo && x.UserId == userId && x.ActionType == EActionType.CallHold && !x.EndTime.HasValue, cancellationToken);

                bool isCallEndArrange = await _telActionRecordRepository.AnyAsync(x => x.TelNo == work.TelNo && x.UserId == userId && x.ActionType == EActionType.CallEndArrange && !x.EndTime.HasValue, cancellationToken);

                bool isTelMute = await _telActionRecordRepository.AnyAsync(x => x.TelNo == work.TelNo && x.UserId == userId && x.ActionType == EActionType.TelMute && !x.EndTime.HasValue, cancellationToken);

                bool IsTelNeedVerify = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.IsTelNeedVerify).SettingValue[0]);
                string callOutQueueId = _systemSettingCacheManager.GetSetting(SettingConstants.CallOutQueueId).SettingValue[0];
                if (IsTelNeedVerify)
                {
                    return new TrOnDutyResponseDto() { QueueCallOut= callOutQueueId, TelNo = work.TelNo, TelPwd = "", Description = work.Description, QueueId = work.QueueId, StartTime = work.StartTime, IsRest = isRest, TelModel = work.TelModel, IsCallHold = isCallHold, IsCallEndArrange = isCallEndArrange, IsTelMute = isTelMute };
                }
                else
                {
                    return new TrOnDutyResponseDto() { QueueCallOut = callOutQueueId, TelNo = work.TelNo, TelPwd = work.TelPwd, Description = work.Description, QueueId = work.QueueId, StartTime = work.StartTime, IsRest = isRest, TelModel = work.TelModel, IsCallHold = isCallHold, IsCallEndArrange = isCallEndArrange,IsTelMute = isTelMute };
                }
               
            }
            return null;
        }

        /// <summary>
        /// 切换状态
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task ChangeTelModel(string userId,bool isCallOut, CancellationToken cancellationToken)
        {
            var work = _userCacheManager.GetWorkByUserNoExp(userId);
            if (work!=null)
            {
                if (isCallOut)
                {
                    //切换外呼模式
                    if (work.TelModel== ETelModel.CallOutModel)
                    {
                        throw UserFriendlyException.SameMessage("已是外呼模式，无需切换");
                    }
                    work.TelModel = ETelModel.CallOutModel;
                    await _workRepository.UpdateAsync(work, cancellationToken);
                    var telCallModel = new TelCallModel(work.TelId,work.TelNo,userId,work.UserName);
                    await _telCallModelRepository.AddAsync(telCallModel,cancellationToken);
                }
                else
                {
                    //切换普通模式
                    if (work.TelModel == ETelModel.OrdinaryModel)
                    {
                        throw UserFriendlyException.SameMessage("已是普通模式，无需切换");
                    }
                    work.TelModel = ETelModel.OrdinaryModel;
                    await _workRepository.UpdateAsync(work, cancellationToken);
                    var telCallModel = await _telCallModelRepository.GetAsync(x => x.TelNo == work.TelNo && !x.EndTime.HasValue, cancellationToken);
                    if (telCallModel!=null)
                    {
                        telCallModel.EndCallOut();
                        await _telCallModelRepository.UpdateAsync(telCallModel, cancellationToken);
                    }
                }
                _cacheWork.Remove(work.GetKey(KeyMode.UserId));
                _cacheWork.Remove(work.GetKey(KeyMode.TelNo));
            }
            else
            {
                throw UserFriendlyException.SameMessage("当前用户没有签入，不能切换状态");
            }
        }
    }
}
