using Hotline.CallCenter.Calls;
using Hotline.CallCenter.Tels;
using MapsterMapper;
using Microsoft.Extensions.Options;
using NewRock.Sdk;
using NewRock.Sdk.Accept.Request;
using NewRock.Sdk.Control.Request;
using NewRock.Sdk.Control.Request.Base;
using NewRock.Sdk.Manage.Request;
using NewRock.Sdk.Transfer.Conference.Request;
using NewRock.Sdk.Transfer.Connect.Request;
using NewRock.Sdk.Transfer.Queue.Request;
using NewRock.Sdk.Control.Response;
using System.Text.RegularExpressions;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using Hotline.Share.Dtos.CallCenter;
using Hotline.Share.Enums.CallCenter;
using Hotline.Caching.Interfaces;
using Hotline.CallCenter.Configs;
using Hotline.CallCenter.Devices;
using Group = NewRock.Sdk.Control.Request.Group;

namespace Hotline.NewRock
{
    public class NewRockDeviceManager : INewRockDeviceManager
    {
        private readonly INewRockClient _newRockClient;
        private readonly ICallRepository _callRepository;
        //private readonly IOptionsSnapshot<CallCenterConfiguration> _options;
        private readonly IMapper _mapper;
        private readonly ITelGroupRepository _telGroupRepository;
        private readonly IUserCacheManager _userCacheManager;
        private readonly ITelRestRepository _telRestRepository;
        private readonly ITelCacheManager _telCacheManager;

        public NewRockDeviceManager(
            INewRockClient newRockClient, 
            //IOptionsSnapshot<CallCenterConfiguration> options, 
            IMapper mapper, 
            ICallRepository callRepository, 
            ITelGroupRepository telGroupRepository,
            IUserCacheManager userCacheManager, 
            ITelRestRepository telRestRepository,
            ITelCacheManager telCacheManager)
        {
            _newRockClient = newRockClient;
            //_options = options;
            _mapper = mapper;
            _callRepository = callRepository;
            _telGroupRepository = telGroupRepository;
            _userCacheManager = userCacheManager;
            _telRestRepository = telRestRepository;
            _telCacheManager = telCacheManager;
        }

        #region 查询

        public async Task<TelDto> QueryTelAsync(NewRockConfiguration newRockConfiguration, string TelNo, CancellationToken cancellationToken)
        {
            try
            {
                var result = await _newRockClient.QueryExt(
                new QueryExtRequest() { Attribute = "Query", Ext = new Ext { Id = TelNo } },
                newRockConfiguration.ReceiveKey, newRockConfiguration.Expired, cancellationToken);

                if (result?.Ext.Outer != null)
                {
                    var telDto = new TelDto();
                    telDto.CPN = result.Ext.Outer.From;
                    telDto.CDPN = result.Ext.Outer.To;
                    telDto.TelStatusInfo = ETelStatusInfo.Out;
                    telDto.ConversationId = result.Ext.Outer.Id;
                    if (result.Ext.Outer.State == "talk")
                    {
                        telDto.TelStatus = Share.Enums.CallCenter.ETelStatus.Talk;
                        return telDto;
                    }
                    else if (result.Ext.Outer.State == "wait")
                    {
                        telDto.TelStatus = Share.Enums.CallCenter.ETelStatus.Wait;
                    }
                    return telDto;
                }
                if (result?.Ext.Visitor != null)
                {
                    var telDto = new TelDto();
                    telDto.CPN = result.Ext.Visitor.From;
                    telDto.CDPN = result.Ext.Visitor.To;
                    telDto.TelStatusInfo = ETelStatusInfo.Into;
                    telDto.ConversationId = result.Ext.Visitor.Id;
                    if (result.Ext.Visitor.State == "talk")
                    {
                        telDto.TelStatus = Share.Enums.CallCenter.ETelStatus.Talk;
                        return telDto;
                    }
                    else if (result.Ext.Visitor.State == "wait")
                    {
                        telDto.TelStatus = Share.Enums.CallCenter.ETelStatus.Wait;
                    }
                    return telDto;
                }
                if (result?.Ext.Ext != null)
                {
                    var telDto = new TelDto();
                    telDto.CPN = result.Ext.Ext.Id;
                    telDto.CDPN = result.Ext.Id;
                    telDto.TelStatusInfo = ETelStatusInfo.Ext;
                    if (result.Ext.Ext.State == "talk")
                    {
                        telDto.TelStatus = Share.Enums.CallCenter.ETelStatus.Talk;
                        return telDto;
                    }
                    else if (result.Ext.Ext.State == "wait")
                    {
                        telDto.TelStatus = Share.Enums.CallCenter.ETelStatus.Wait;
                    }
                    return telDto;
                }
                return null;
            }
            catch
            {
                return null;
            }
        }


        /// <summary>
        /// 查询分机状态
        /// </summary>
        /// <param name="TelNo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<ETelStatus> QueryTelState(NewRockConfiguration newRockConfiguration, string TelNo, CancellationToken cancellationToken)
        {
            var result = await _newRockClient.QueryExt(
                new QueryExtRequest() { Attribute = "Query", Ext = new Ext { Id = TelNo } },
                newRockConfiguration.ReceiveKey, newRockConfiguration.Expired, cancellationToken);

            switch (result.Ext.State)
            {
                case "ready":
                    return ETelStatus.Ready;
                case "active":
                    return ETelStatus.Active;
                case "progress":
                    return ETelStatus.Progress;
                case "offline":
                    return ETelStatus.Offline;
                case "offhook":
                    return ETelStatus.Offhook;
                default:
                    break;
            }
            return ETelStatus.Offline;
        }

        /// <summary>
        /// 查询所有分机
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<List<Tel>> QueryTelsAsync(NewRockConfiguration newRockConfiguration, CancellationToken cancellationToken)
        {
            var result = await _newRockClient.QueryDeviceInfo(
                new QueryDeviceInfoRequest { Attribute = "Query", DeviceInfo = string.Empty },
                newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
            var exts = result.Devices.Ext;
            return _mapper.Map<List<Tel>>(exts);
        }

        /// <summary>
        /// 查询所有分机组
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<List<TelGroup>> QueryTelGroupsAsync(NewRockConfiguration newRockConfiguration, CancellationToken cancellationToken)
        {
            var result = await _newRockClient.QueryDeviceInfo(
                new QueryDeviceInfoRequest { Attribute = "Query", DeviceInfo = string.Empty },
                newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);

            var groups = result.Devices.Group;
            return _mapper.Map<List<TelGroup>>(groups);
        }

        /// <summary>
        /// 查询语音文件
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<string> VoiceQueryListAsync(NewRockConfiguration newRockConfiguration, CancellationToken cancellationToken)
        {
            var result = await _newRockClient.VoiceQueryList(new VoiceQueryListRequest()
                {
                    Attribute = "Query",
                    VoiceFile = "",
                }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
            return result?.VoiceFile;
        }

        public async Task QueryGroupAsync(NewRockConfiguration newRockConfiguration, string groupId, CancellationToken cancellationToken)
        {
            await _newRockClient.QueryExtGroup(new QueryExtGroupRequest()
                { Attribute = "Query", Group = new QueryExtGroup() { Id = groupId } },
                newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken
            );
        }


        #endregion

        #region 配置
        /// <summary>
        /// 分机休息
        /// </summary>
        /// <param name="telNo">分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task TelRestAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
        {
            var telModel = await _newRockClient.QueryExt(new QueryExtRequest()
            {
                Attribute = "Query",
                Ext = new Ext() { Id = telNo }
            }, newRockConfiguration.ReceiveKey,
            newRockConfiguration.Expired,
            cancellationToken);

            if (telModel == null)
                throw new UserFriendlyException("未知分机");

            await _newRockClient.ConfigExt(
                new AssginConfigExtRequest() { Attribute = "Assign", Ext = new ConfigExt() { Lineid = telModel.Ext.LineId, Groups=Enumerable.Select<QueryExtGroup, string>(telModel.Ext.Group, x=>x.Id).ToList(), No_Disturb = "On" } },
                newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 分机结束休息
        /// </summary>
        /// <param name="telNo">分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task TelEndRestAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
        {
            var telModel = await _newRockClient.QueryExt(new QueryExtRequest()
            {
                Attribute = "Query",
                Ext = new Ext() { Id = telNo }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);

            if (telModel == null)
                throw new UserFriendlyException("未知分机");

            await _newRockClient.ConfigExt(
                new AssginConfigExtRequest() { Attribute = "Assign", Ext = new ConfigExt() { Lineid = telModel.Ext.LineId, Groups = Enumerable.Select<QueryExtGroup, string>(telModel.Ext.Group, x => x.Id).ToList(), No_Disturb = "Off" } },
                newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 删除语音文件
        /// </summary>
        /// <param name="voiceName"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RemoveVoiceFileAsync(NewRockConfiguration newRockConfiguration, string voiceName, CancellationToken cancellationToken)
        {
            await _newRockClient.RemoveVoiceFile(new RemoveVoiceFileRequest()
            {
                Attribute = "Remove",
                VoiceFile = voiceName
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 配置语音菜单
        /// </summary>
        /// <param name="menuId"></param>
        /// <param name="voiceFile"></param>
        /// <param name="repeat"></param>
        /// <param name="infoLength"></param>
        /// <param name="exit"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AssginConfigMenuAsync(NewRockConfiguration newRockConfiguration, string menuId, string voiceFile, string repeat, string infoLength,
            string exit,
            CancellationToken cancellationToken)
        {
            if (!int.TryParse(menuId, out int mId))
                throw new UserFriendlyException("请输入数字");

            if (mId < 1 || mId > 50)
                throw new UserFriendlyException("菜单只允许在1-50范围内");

            if (exit!="")
            {
                Regex r = new Regex(@"^[a-d]|[A-D]|[1-9]|[*]|[#]$");
                if (!r.IsMatch(exit))
                    throw new UserFriendlyException("输入指令不合法，合法值：A-D、1-9、*、#");
            }

            var resp = await _newRockClient.ConfigMenu(new AssginConfigMenuRequest()
            {
                Attribute = "Assign",
                Menu = new AssginConfigMenuMenu()
                {
                    Id = menuId,
                    VoiceFile = voiceFile,
                    InfoLength = infoLength,
                    Exit = exit,
                    Repeat = repeat,
                }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 配置分机组
        /// </summary>
        /// <param name="groupId"></param>
        /// <param name="voiceFile"></param>
        /// <param name="distribution"></param>
        /// <param name="ext"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AssginConfigGroupAsync(NewRockConfiguration newRockConfiguration, string groupId, EDistribution distribution, List<string> ext, string? voiceFile = "",CancellationToken cancellationToken=default)
        {
            if (!int.TryParse(groupId, out int mId))
                throw new UserFriendlyException("请输入数字");

            if (mId < 1 || mId > 50)
                throw new UserFriendlyException("分机组只允许在1-50范围内");

            var groupModel = new Group()
            {
                Id = groupId,
                Ext = ext,
            };
            switch (distribution)
            {
                case EDistribution.Sequential:
                    groupModel.Distribution = "sequential";
                    break;
                case EDistribution.Group:
                    groupModel.Distribution = "group";
                    break;
                case EDistribution.Circular:
                    groupModel.Distribution = "circular";
                    break;
                default:
                    break;
            }

            if (!string.IsNullOrEmpty(voiceFile))
                groupModel.Voicefile = voiceFile;

            var resp = await _newRockClient.ConfigExtGroup(new AssginConfigGroupRequest()
            {
                Attribute = "Assign",
                Group = groupModel
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }


        /// <summary>
        /// 更新分机组
        /// </summary>
        /// <param name="groupId"></param>
        /// <param name="ext"></param>
        /// <param name="cancellationToken"></param>
        /// <param name="isAdd"></param>
        /// <returns></returns>
        public async Task ModifyGroupExtAsync(NewRockConfiguration newRockConfiguration, string groupId, EDistribution distribution, string voicefile = "", string extId = "", bool isAdd = true, CancellationToken cancellationToken = default)
        {
            if (!int.TryParse(groupId, out int mId))
                throw new UserFriendlyException("请输入数字");

            if (mId < 1 || mId > 50)
                throw new UserFriendlyException("分机组只允许在1-50范围内");

            #region 清除分机组设置

            await _newRockClient.ConfigExtGroup(new AssginConfigGroupRequest() { Attribute = "Assign", Group = new Group() { Id = groupId } }, newRockConfiguration.ReceiveKey, newRockConfiguration.Expired, cancellationToken);

            #endregion

            var list = await _telGroupRepository.QueryExtAsync(d => d.No == groupId, d => d.Includes(x => x.Tels));
            //检查是否上班
            List<string> exts = new List<string>();
            foreach (var ext in list[0].Tels)
            {
                var iswork = await _userCacheManager.IsWorkingByTelAsync(ext.No, cancellationToken);
                if (iswork)
                {
                    var tel = _telCacheManager.GetTel(ext.No);
                    if (tel.TelStatus == ETelStatus.Ready)
                    {
                        exts.Add(ext.No);
                    }
                }
            }

            //查询所有正在休息的分机
            List<string> restexts = (await _telRestRepository.QueryAsync(x => x.EndTime == null)).Select(x => x.TelNo).ToList();
            if (restexts != null && restexts.Count > 0)
            {
                foreach (var item in restexts)
                {
                    exts.Remove(item);
                }
            }

            //更新
            var groupModel = new Group()
            {
                Id = groupId,
                Voicefile = voicefile
            };
            switch (distribution)
            {
                case EDistribution.Sequential:
                    groupModel.Distribution = "sequential";
                    break;
                case EDistribution.Group:
                    groupModel.Distribution = "group";
                    break;
                case EDistribution.Circular:
                    groupModel.Distribution = "circular";
                    break;
                default:
                    break;
            }

            groupModel.Ext = exts;
            await _newRockClient.ConfigExtGroup(
                new AssginConfigGroupRequest() { Attribute = "Assign", Group = groupModel, },
                newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken
                );
        }

        /// <summary>
        /// 上班/下班
        /// </summary>
        /// <param name="telNo"></param>
        /// <param name="staffNo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task UpdateStaffNoAsync(NewRockConfiguration newRockConfiguration, string telNo, string staffNo,string lineId, CancellationToken cancellationToken)
        {
            var telModel = await _newRockClient.QueryExt(new QueryExtRequest()
                {
                    Attribute = "Query",
                    Ext = new Ext() { Id = telNo }
                }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);

            if (telModel == null)
                throw new UserFriendlyException("未知分机");

            await _newRockClient.ConfigExt(
                new AssginConfigExtRequest() { Attribute = "Assign", Ext = new ConfigExt() { Id = telNo,Lineid = lineId, Staffid = staffNo } },
                newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }
        #endregion

        #region 通话控制

        /// <summary>
        /// 保持通话
        /// </summary>
        /// <param name="telNo">分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task HoldAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
        {
            await _newRockClient.HoldOrUnHold(
                new HoldSetRequest() { Attribute = "Hold", Ext = new Ext() { Id = telNo } }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 恢复通话(解除hold状态)
        /// </summary>
        /// <param name="telNo">分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task UnHoldAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
        {
            await _newRockClient.HoldOrUnHold(
                new HoldSetRequest() { Attribute = "Unhold", Ext = new Ext() { Id = telNo } }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 静音开启
        /// </summary>
        /// <param name="telNo">分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task MuteAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
        {
            await _newRockClient.MuteOrUnMute(
                new MuteSetRequest() { Attribute = "Mute", Ext = new Ext() { Id = telNo } }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 解除静音
        /// </summary>
        /// <param name="telNo">分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task UnMuteAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
        {
            await _newRockClient.MuteOrUnMute(
                new MuteSetRequest() { Attribute = "Unmute", Ext = new Ext() { Id = telNo } },
                newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 强拆分机
        /// </summary>
        /// <param name="extId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task ClearExtAsync(NewRockConfiguration newRockConfiguration, string extId, CancellationToken cancellationToken)
        {
            await _newRockClient.ClearCall(new ClearCallRequest()
            {
                Attribute = "Clear",
                Ext = new Ext()
                {
                    Id = extId
                }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 强拆来电
        /// </summary>
        /// <param name="visitorId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task ClearVisitorAsync(NewRockConfiguration newRockConfiguration, string visitorId, CancellationToken cancellationToken)
        {
            await _newRockClient.ClearCall(new ClearCallRequest()
            {
                Attribute = "Clear",
                Visitor = new ClearCallVisitor() { Id = visitorId }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 强拆去电
        /// </summary>
        /// <param name="outerId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task ClearOuterAsync(NewRockConfiguration newRockConfiguration, string outerId, CancellationToken cancellationToken)
        {
            await _newRockClient.ClearCall(new ClearCallRequest()
            {
                Attribute = "Clear",
                Outer = new ClearCallOuter() { Id = outerId }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 来电受理
        /// </summary>
        /// <param name="visitorId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AcceptVisitorAsync(NewRockConfiguration newRockConfiguration, string visitorId, CancellationToken cancellationToken)
        {
            await _newRockClient.AcceptVisitor(new AcceptVisitorRequest()
            {
                Attribute = "Accept",
                Visitor = new AcceptVisitorModel() { Id = visitorId }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }
        #endregion

        #region 连接呼叫

        /// <summary>
        /// 分机呼分机
        /// </summary>
        /// <param name="from">主叫分机号</param>
        /// <param name="to">被叫分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task ExtToExtAsync(NewRockConfiguration newRockConfiguration, string from, string to, CancellationToken cancellationToken)
        {
            await _newRockClient.ExtensionToExtension(
                new ExtensionToExtensionRequest()
                {
                    Attribute = "Connect",
                    Exts = new List<ExtToExtExt>() { new ExtToExtExt() { Id = from }, new ExtToExtExt() { Id = to } }
                }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 分机呼外部电话
        /// </summary>
        /// <param name="from">分机号</param>
        /// <param name="to">外部电话，外地电话加拨0</param>
        /// <param name="cancellationToken"></param>
        /// <param name="trunkid">指定中继线路（可为空），为空时默认由OM分配</param>
        /// <returns></returns>
        public async Task ExtToOuterAsync(NewRockConfiguration newRockConfiguration, string from, string to, CancellationToken cancellationToken, string trunkid = "")
        {
            await _newRockClient.ExtToOuter(
                    new ExtToOuterRequest()
                    {
                        Attribute = "Connect",
                        Ext = new ExtToOuterExtRequest() { Id = from },
                        Outer = new ExtToOuterOuterRequest() { To = to },
                        Trunk = new ExtToOuterTrunkRequest() { Id = trunkid }
                    },
                newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }


        /// <summary>
        /// 来电转分机
        /// </summary>
        /// <param name="visitorId">来电会话ID</param>
        /// <param name="telNo">分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task VisitorToExtAsync(NewRockConfiguration newRockConfiguration, string visitorId, string telNo, CancellationToken cancellationToken)
        {
            await _newRockClient.VisitorToExt(new VisitorToExtRequest()
            {
                Attribute = "Connect",
                Visitor = new VisitorToExtVisitor() { Id = visitorId },
                Ext = new VisitorToExtExt() { Id = telNo }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 来电转外部电话
        /// </summary>
        /// <param name="visitorId">来电会话ID</param>
        /// <param name="outerPhoneNum">外部电话，外地电话加拨0</param>
        /// <param name="cancellationToken"></param>
        /// <param name="display">来电号码，用来透传主叫号码，使去电方的来电显示号码为实际来电号码。</param>
        /// <returns></returns>
        public async Task VisitorToOuterAsync(NewRockConfiguration newRockConfiguration, string visitorId, string outerPhoneNum, CancellationToken cancellationToken,
            string display = "")
        {
            await _newRockClient.VisitorToOuter(new VisitorToOuterRequest()
            {
                Attribute = "Connect",
                Visitor = new VisitorToOuterVisitor() { Id = visitorId },
                Outer = new VisitorToOuterOuter() { To = outerPhoneNum, Display = display },

            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }


        /// <summary>
        /// 来电转语音菜单
        /// </summary>
        /// <param name="visitorId">来电会话ID</param>
        /// <param name="menuId">菜单ID</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task VisitorToMenuAsync(NewRockConfiguration newRockConfiguration, string visitorId, string menuId, CancellationToken cancellationToken)
        {
            await _newRockClient.VisitorToMenu(new VisitorToMenuRequest()
            {
                Attribute = "Connect",
                Visitor = new VisitorToMenuVisitor() { Id = visitorId },
                Menu = new VisitorToMenuMenu() { Id = menuId }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 来电转分机组
        /// </summary>
        /// <param name="visitorId"></param>
        /// <param name="groupId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task VisitorToGroupAsync(NewRockConfiguration newRockConfiguration, string visitorId, string groupId, CancellationToken cancellationToken)
        {
            await _newRockClient.VisitorToGroupQueue(new VisitorToGroupQueueRequest()
            {
                Attribute = "Queue",
                Visitor = new VisitorToGroupQueueVisitor() { Id = visitorId },
                Group = new VisitorToGroupQueueGroup() { Id = groupId }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 去电转分机
        /// </summary>
        /// <param name="outerId">去电会话ID</param>
        /// <param name="telNo">分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task OuterToExtAsync(NewRockConfiguration newRockConfiguration, string outerId, string telNo, CancellationToken cancellationToken)
        {
            await _newRockClient.OuterToExt(new OuterToExtRequest()
            {
                Attribute = "Connect",
                Outer = new OuterToExtOuter() { Id = outerId },
                Ext = new OuterToExtExt() { Id = telNo }
            },
                newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 去电转外部电话
        /// </summary>
        /// <param name="outerId">去电会话ID</param>
        /// <param name="outerPhoneNum">外部电话，外地电话加拨0</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task OuterToOuterAsync(NewRockConfiguration newRockConfiguration, string outerId, string outerPhoneNum, CancellationToken cancellationToken)
        {
            await _newRockClient.OuterToOuter(new OuterToOuterRequest()
            {
                Attribute = "Connect",
                Outer = new List<OuterToOuterOuterModel>()
                    {
                        new OuterToOuterOuterModel() { Id = outerId },
                        new OuterToOuterOuterModel() { To = outerPhoneNum }
                    },
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }


        /// <summary>
        /// 语音菜单呼叫分机
        /// </summary>
        /// <param name="menuId">语音菜单ID</param>
        /// <param name="telNo">分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task MenuToExtAsync(NewRockConfiguration newRockConfiguration, string menuId, string telNo, CancellationToken cancellationToken)
        {
            await _newRockClient.MenuToExt(new MenuToExtRequest()
            {
                Attribute = "Connect",
                Menu = new MenuToExtMenu() { Id = menuId },
                Ext = new MenuToExtExt() { Id = telNo }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }


        /// <summary>
        /// 语音菜单呼外部电话
        /// </summary>
        /// <param name="menuId">语音菜单ID</param>
        /// <param name="outerPhoneNum">外部电话，外地电话加拨0</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task MenuToOuterAsync(NewRockConfiguration newRockConfiguration, string menuId, string outerPhoneNum, CancellationToken cancellationToken)
        {
            await _newRockClient.MenuToOuter(new MenuToOuterRequest()
            {
                Attribute = "Connect",
                Menu = new MenuToOuterMenu() { Id = menuId },
                Outer = new MenuToOuterOuter() { To = outerPhoneNum }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 双向呼叫（回拨）
        /// </summary>
        /// <param name="outerOne">主叫外部电话，外地电话加拨0</param>
        /// <param name="outerTwo">被叫外部电话，外地电话加拨0</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task TwoWayOuterAsync(NewRockConfiguration newRockConfiguration, string outerOne, string outerTwo, CancellationToken cancellationToken)
        {
            await _newRockClient.TwoWayOuter(new TwoWayOuterRequest()
            {
                Attribute = "Connect",
                Outer = new List<TwoWayOuterOuter>()
                    {
                        new TwoWayOuterOuter(){ To = outerOne},
                        new TwoWayOuterOuter(){ To = outerTwo}
                    }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 语音插播（分机）
        /// </summary>
        /// <param name="voiceFileName">语音名称</param>
        /// <param name="telNo">分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task VoiceNewsFlashExtAsync(NewRockConfiguration newRockConfiguration, string voiceFileName, string telNo, CancellationToken cancellationToken)
        {
            await _newRockClient.VoiceNewsFlash(new VoiceNewsFlashRequest
            {
                Attribute = "Connect",
                VoiceFile = voiceFileName,
                Ext = new VoiceNewsFlashExt() { Id = telNo }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 语音插播（来电）
        /// </summary>
        /// <param name="voiceFileName">语音名称</param>
        /// <param name="visitorId">来电会话ID</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task VoiceNewsFlashVisitorAsync(NewRockConfiguration newRockConfiguration, string voiceFileName, string visitorId,
            CancellationToken cancellationToken)
        {
            await _newRockClient.VoiceNewsFlash(
                new VoiceNewsFlashRequest
                {
                    Attribute = "Connect",
                    VoiceFile = voiceFileName,
                    Visitor = new VoiceNewsFlashVisitor() { Id = visitorId }
                }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 语音插播（去电）
        /// </summary>
        /// <param name="voiceFileName">语音名称</param>
        /// <param name="outerId">去电会话ID</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task VoiceNewsFlashOuterAsync(NewRockConfiguration newRockConfiguration, string voiceFileName, string outerId, CancellationToken cancellationToken)
        {
            await _newRockClient.VoiceNewsFlash(
                new VoiceNewsFlashRequest
                {
                    Attribute = "Connect",
                    VoiceFile = voiceFileName,
                    Outer = new VoiceNewsFlashOuter() { Id = outerId }
                }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 会议
        /// </summary>
        /// <param name="telNo">发起方分机号</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task ConferenceMeetingAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
        {
            await _newRockClient.ConferenceMeeting(new ConferenceMeetingRequest()
            {
                Attribute = "Conference",
                Ext = new ConferenceMeetingExt() { Id = telNo }
            }, newRockConfiguration.ReceiveKey,
                newRockConfiguration.Expired,
                cancellationToken);
        }

        /// <summary>
        /// 处理IVR响应
        /// </summary>
        /// <param name="callDetail"></param>
        /// <param name="ivrAnswer"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task HandleIvrAnswerAsync(NewRockConfiguration newRockConfiguration, CallDetail callDetail, IvrAnswer ivrAnswer, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(ivrAnswer.Content))
                throw new UserFriendlyException("无效IVR应答参数");

            //获取是来电或去电
            var model = await _callRepository.GetAsync(x => x.Id == callDetail.CallId, cancellationToken);
            
        }

        #endregion

        #region 监听和插播

        /// <summary>
        /// 监听分机
        /// </summary>
        /// <param name="firstTelNo">监听方</param>
        /// <param name="secondTelNo">被监听方</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task MonitorExtAsync(NewRockConfiguration newRockConfiguration, string firstTelNo, string secondTelNo, CancellationToken cancellationToken)
        {
            await _newRockClient.MonitorExt(new MonitorExtRequest()
            {
                Attribute = "Monitor",
                Exts = new List<Ext>() { new Ext() { Id=firstTelNo },new Ext() { Id=secondTelNo } }
            }, newRockConfiguration.ReceiveKey,
             newRockConfiguration.Expired,
             cancellationToken) ;
        }

        /// <summary>
        /// 从监听到插播状态变换
        /// 1. 已知：分机 A 在监听分机 B 与其通话方的通话；
        /// 2. 执行分机 A 的从监听到插播状态变换的 API；
        /// 3. 执行成功时，分机 A 与分机 B 建立通话，分机 B 的原通话方听保持音。
        /// </summary>
        /// <param name="telNo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task MonitorExtToTalkAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
        {
            await _newRockClient.MonitorExtToTalk(new MonitorExtToTalkRequest()
            {
                Attribute = "Talk",
                Ext = new Ext() { Id = telNo }
            }, newRockConfiguration.ReceiveKey,
              newRockConfiguration.Expired,
              cancellationToken) ;
        }


        /// <summary>
        /// 从插播到监听状态变换
        /// 1. 已知：分机 A 在插播分机 B 的通话；
        /// 2. 执行分机 A 的从插播到监听状态变换的 API；
        /// 3. 执行成功时，分机 A 监听分机 B 及其原通话方的通话。
        /// </summary>
        /// <param name="telNo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task MonitorExtToListenAsync(NewRockConfiguration newRockConfiguration, string telNo, CancellationToken cancellationToken)
        {
            await _newRockClient.MonitorExtToListen(new MonitorExtToListenRequest
            {
                Attribute = "Listen",
                Ext = new Ext() { Id = telNo }
            }, newRockConfiguration.ReceiveKey,
              newRockConfiguration.Expired,
              cancellationToken);
        }

        #endregion


        #region 强插

        /// <summary>
        /// 强插
        /// 1. 已知：分机 A 当前空闲，分机 B 正在通话中；
        /// 2. 执行分机 A 强插分机 B 的 API；
        /// 3. 执行成功时，分机 A 振铃，摘机后即可形成三方通话。
        /// </summary>
        /// <param name="firstTelNo"></param>
        /// <param name="secondTelNo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task BargeinExtAsync(NewRockConfiguration newRockConfiguration, string firstTelNo,string secondTelNo,CancellationToken cancellationToken)
        {
            await _newRockClient.BargeinExt(new BargeinExtRequest()
            {
                Attribute = "Bargein",
                Exts = new List<Ext>() { new Ext() { Id = firstTelNo },new Ext() { Id=secondTelNo } }
            }, newRockConfiguration.ReceiveKey,
              newRockConfiguration.Expired,
              cancellationToken);
        }

        #endregion
    }
}
