using System.Security.Authentication;
using Hotline.CallCenter;
using Hotline.CallCenter.Configs;
using Hotline.Share.Notifications.NewRockCallCenter;
using MapsterMapper;
using MediatR;
using Microsoft.Extensions.Logging;
using NewRock.Sdk;
using NewRock.Sdk.Events;
using NewRock.Sdk.Extensions;
using NewRock.Sdk.Security;
using XF.Domain.Dependency;

namespace Hotline.NewRock.Handlers
{
    public class DeviceEventHandler : IDeviceEventHandler, IScopeDependency
    {
        private readonly IMediator _mediator;
        private readonly IMapper _mapper;
        private readonly ILogger<DeviceEventHandler> _logger;
        private static readonly string _cdrMarkup = "<Cdr id=";

        public DeviceEventHandler(
            IMediator mediator,
            IMapper mapper,
            ILogger<DeviceEventHandler> logger)
        {
            _mediator = mediator;
            _mapper = mapper;
            _logger = logger;
        }

        public async Task HandleAsync(Stream eventStream, NewRockConfiguration newRockConfiguration,
            CancellationToken cancellationToken)
        {
            var sr = new StreamReader(eventStream);
            var content = await sr.ReadToEndAsync();
            _logger.LogInformation("收到设备事件：\r\n{content}", content);

            if (content.Contains(_cdrMarkup))
            {
                // cdr事件
                //通话记录报告
                var eventBase = content.DeserializeWithAuthorize<NewRockCdrEvent>();
                if (eventBase.value == null) return;
                if (newRockConfiguration.Authorize && (eventBase.authorize == null ||
                                                       !eventBase.authorize.IsAuthorized(newRockConfiguration.SendKey)))
                    throw new AuthenticationException("无有效身份认证信息");

                var cdrRcv = content.DeserializeWithAuthorize<CdrEvent>();
                await _mediator.Publish(_mapper.Map<CdrNotification>(cdrRcv.value!), cancellationToken);
            }
            else
            {
                var eventBase = content.DeserializeWithAuthorize<NewRockEvent>();
                if (eventBase.value == null) return;
                if (newRockConfiguration.Authorize && (eventBase.authorize == null ||
                                                       !eventBase.authorize.IsAuthorized(newRockConfiguration.SendKey)))
                    throw new AuthenticationException("无有效身份认证信息");

                switch (eventBase.value.Attribute)
                {
                    //分机上线事件发布
                    case Event.ONLINE:
                        var onLineRcv = content.DeserializeWithAuthorize<OnlineEvent>();
                        await _mediator.Publish(_mapper.Map<OnlineNotification>(onLineRcv.value!), cancellationToken);
                        break;
                    //分机下线事件
                    case Event.OFFLINE:
                        var offLineRcv = content.DeserializeWithAuthorize<OfflineEvent>();
                        await _mediator.Publish(_mapper.Map<OfflineNotification>(offLineRcv.value!), cancellationToken);
                        break;
                    //分机示闲事件
                    case Event.IDLE:
                        var idleRcv = content.DeserializeWithAuthorize<IdleEvent>();
                        await _mediator.Publish(_mapper.Map<IdleNotification>(idleRcv.value!), cancellationToken);
                        break;
                    //分机示忙事件
                    case Event.BUSY:
                        var busyRcv = content.DeserializeWithAuthorize<BusyEvent>();
                        await _mediator.Publish(_mapper.Map<BusyNotification>(busyRcv.value!), cancellationToken);
                        break;
                    //振铃事件
                    case Event.RING:
                        var ringRcv = content.DeserializeWithAuthorize<RingEvent>();
                        //判断是哪种振铃事件
                        //分机呼分机
                        if (ringRcv.value?.Ext.Count > 1)
                        {
                            //await _mediator.Publish(_mapper.Map<RingExtToExtNotification>(ringRcv.value!),cancellationToken);
                        }
                        //来电转分机
                        else if (ringRcv.value?.Ext.Count == 1 && ringRcv.value.Visitor != null)
                        {
                            await _mediator.Publish(_mapper.Map<RingVisitorToExtNotification>(ringRcv.value!),
                                cancellationToken);
                        }
                        //分机外呼
                        else if (ringRcv.value?.Ext.Count == 1 && ringRcv.value.Outer != null && ringRcv.value.Outer.Id != "")
                        {
                            await _mediator.Publish(_mapper.Map<RingExtToOuterNotification>(ringRcv.value!), cancellationToken);
                        }
                        //menu呼叫分机
                        else if (ringRcv.value?.Ext.Count == 1 && ringRcv.value.Menu != null)
                        {
                            await _mediator.Publish(_mapper.Map<RingMenuToExtNotification>(ringRcv.value!),
                                cancellationToken);
                        }
                        break;
                    //回铃事件
                    case Event.ALERT:
                        var alertRcv = content.DeserializeWithAuthorize<AlertEvent>();
                        //判断是 哪种回铃事件
                        //来电转分机，分机回铃
                        if (alertRcv.value?.Ext.Count == 1 && alertRcv.value.Visitor != null)
                        {
                            await _mediator.Publish(_mapper.Map<AlertVisitorToExtNotification>(alertRcv.value!),
                                cancellationToken);
                        }
                        //分机呼外部电话，外部电话回铃
                        else if (alertRcv.value?.Ext.Count == 1 && alertRcv.value.Outer != null)
                        {
                            await _mediator.Publish(_mapper.Map<AlertExtToOuterNotification>(alertRcv.value!),
                                cancellationToken);
                        }
                        //分机呼分机，被叫分机回铃
                        else if (alertRcv.value?.Ext.Count > 1)
                        {
                            await _mediator.Publish(_mapper.Map<AlertExtToExtNotification>(alertRcv.value!),
                                cancellationToken);
                        }
                        //Menu外呼，外部电话回铃
                        else if ((alertRcv.value?.Ext == null || alertRcv.value?.Ext.Count == 0) &&
                                 alertRcv.value?.Outer != null)
                        {
                            await _mediator.Publish(_mapper.Map<AlertMenuToOuterNotification>(alertRcv.value!),
                                cancellationToken);
                        }
                        break;
                    //呼叫应答事件
                    case Event.ANSWER:
                        var answerRcv = content.DeserializeWithAuthorize<AnswerEvent>();
                        //分机呼分机，被叫分机应答
                        if (answerRcv.value?.Ext.Count > 1)
                        {
                            await _mediator.Publish(_mapper.Map<AnswerExtToExtNotification>(answerRcv.value!),
                                cancellationToken);
                        }
                        //来电转分机，分机应答
                        else if (answerRcv.value?.Ext.Count == 1 && answerRcv.value.Visitor != null)
                        {
                            await _mediator.Publish(_mapper.Map<AnswerViisitorToExtNotification>(answerRcv.value!),
                                cancellationToken);
                        }
                        //去电转分机，分机应答
                        else if (answerRcv.value?.Ext.Count == 1 && answerRcv.value?.Outer != null)
                        {
                            await _mediator.Publish(_mapper.Map<AnswerExtToOuterNotification>(answerRcv.value!),
                                cancellationToken);
                        }
                        break;
                    //呼叫被应答事件
                    case Event.ANSWERED:
                        var answeredRcv = content.DeserializeWithAuthorize<AnsweredEvent>();
                        //分机呼分机，主叫分机检查到被叫分机应答
                        if (answeredRcv.value?.Ext.Count > 1)
                        {
                            await _mediator.Publish(_mapper.Map<AnsweredExtToExtNotification>(answeredRcv.value!),
                                cancellationToken);
                        }
                        //分机呼外部电话，分机检查到外部电话应答
                        else if (answeredRcv.value?.Ext.Count == 1 && answeredRcv.value?.Outer != null)
                        {
                            await _mediator.Publish(_mapper.Map<AnsweredExtToOuterNotification>(answeredRcv.value!),
                                cancellationToken);
                        }
                        //来电呼叫分机
                        else if (answeredRcv.value?.Visitor != null && answeredRcv.value?.Ext.Count == 1)
                        {
                            await _mediator.Publish(_mapper.Map<AnsweredVisitorToExtNotification>(answeredRcv.value!),
                                cancellationToken);
                        }
                        //分机呼外部电话，转接其他分机，其他分机应答
                        else if (answeredRcv.value?.Outer != null)
                        {
                            await _mediator.Publish(
                                _mapper.Map<AnsweredExtToOuterToExtNotification>(answeredRcv.value!),
                                cancellationToken);
                        }
                        break;
                    //通话结束事件
                    case Event.BYE:
                        var byeRcv = content.DeserializeWithAuthorize<ByeEvent>();
                        //来电和分机的通话结束，来电挂断
                        if (byeRcv.value?.Ext.Count == 1 && byeRcv.value?.Visitor != null)
                        {
                            await _mediator.Publish(_mapper.Map<ByeVisitorAndExtNotification>(byeRcv.value!),
                                cancellationToken);
                        }
                        //来电和分机的通话，分机挂断
                        else if (byeRcv.value?.Visitor != null)
                        {
                            await _mediator.Publish(_mapper.Map<ByeVisitorOffNotification>(byeRcv.value!),
                                cancellationToken);
                        }
                        //来电转去电的通话结束，来电挂断
                        else if (byeRcv.value?.Outer != null && byeRcv.value?.Visitor != null)
                        {
                            await _mediator.Publish(_mapper.Map<ByeVisitorAndOuterNotification>(byeRcv.value!),
                                cancellationToken);
                        }
                        //分机和分机结束通话,挂断
                        else if (byeRcv.value?.Ext.Count == 2)
                        {
                            await _mediator.Publish(_mapper.Map<ByeExtAndExtNotification>(byeRcv.value!), cancellationToken);
                        }
                        //其他条件
                        else if (byeRcv.value?.Outer != null)
                        {
                            //分机和去电的通话结束，分机挂断 类型一
                            if (byeRcv.value?.Ext.Count == 1)
                            {
                                await _mediator.Publish(_mapper.Map<ByeExtAndOuterOneNotification>(byeRcv.value!),
                                    cancellationToken);
                            }
                            //双向外呼的通话结束，两个去电分别各有一个 BYE 事件
                            else if (byeRcv.value?.Outer.From != "")
                            {
                                await _mediator.Publish(_mapper.Map<ByeOuterAndOuterNotification>(byeRcv.value!),
                                    cancellationToken);
                            }
                            //分机和去电的通话结束，分机挂断 类型二
                            else
                            {
                                await _mediator.Publish(_mapper.Map<ByeExtAndOuterTwoNotification>(byeRcv.value!),
                                    cancellationToken);
                            }
                        }
                        break;
                    //呼叫转移事件
                    case Event.DIVERT:
                        var divertRcv = content.DeserializeWithAuthorize<DivertEvent>();
                        //来电呼叫分机时，因分机设置了呼叫转移等原因，导致该呼叫被转移
                        if (divertRcv.value?.Visitor != null)
                        {
                            await _mediator.Publish(_mapper.Map<DivertVisitorToExtNotification>(divertRcv.value!),
                                cancellationToken);
                        }
                        //分机呼叫其他分机时，因被叫分机设置了呼叫转移等原因，导致该呼叫被转移
                        else if (divertRcv.value?.Ext != null)
                        {
                            await _mediator.Publish(_mapper.Map<DivertExtToExtNotification>(divertRcv.value!),
                                cancellationToken);
                        }
                        break;
                    //呼叫临时事件
                    case Event.TRANSIENT:
                        var transientRcv = content.DeserializeWithAuthorize<TransientEvent>();
                        if (transientRcv.value?.Outer != null)
                        {
                            await _mediator.Publish(_mapper.Map<TransientOuterNotification>(transientRcv.value!),
                                cancellationToken);
                        }
                        else if (transientRcv.value?.Visitor != null)
                        {
                            await _mediator.Publish(_mapper.Map<TransientVisitorNotification>(transientRcv.value!),
                                cancellationToken);
                        }
                        //TODO 处理来电临时事件
                        break;
                    //呼叫失败事件
                    case Event.FAILED:
                        var failedRcv = content.DeserializeWithAuthorize<FailedEvent>();
                        await _mediator.Publish(_mapper.Map<FailedNotification>(failedRcv.value!), cancellationToken);
                        break;
                    //来电呼叫请求事件
                    case Event.INVITE:
                        var inviteRcv = content.DeserializeWithAuthorize<InviteEvent>();
                        await _mediator.Publish(_mapper.Map<InviteNotification>(inviteRcv.value!), cancellationToken);
                        break;
                    //来电呼入事件
                    case Event.INCOMING:
                        var incomingRcv = content.DeserializeWithAuthorize<IncomingEvent>();
                        await _mediator.Publish(_mapper.Map<IncomingNotification>(incomingRcv.value!),
                            cancellationToken);
                        break;
                    //按键信息事件
                    case Event.DTMF:
                        var dtmfRcv = content.DeserializeWithAuthorize<DtmfEvent>();
                        await _mediator.Publish(_mapper.Map<DtmfNotification>(dtmfRcv.value!), cancellationToken);
                        break;
                    //语音文件播放完毕事件
                    case Event.EndOfAnn:
                        var endOfAnnRcv = content.DeserializeWithAuthorize<EndOfAnnEvent>();
                        //来电转menu
                        if (endOfAnnRcv.value?.Visitor != null && endOfAnnRcv.value?.Menu != null)
                        {
                            await _mediator.Publish(_mapper.Map<EndOfAnnVisitorToMenuNotification>(endOfAnnRcv.value!),
                                cancellationToken);
                        }
                        //去电转menu
                        else if (endOfAnnRcv.value?.Outer != null && endOfAnnRcv.value?.Menu != null)
                        {
                            await _mediator.Publish(_mapper.Map<EndOfAnnOuterToMenuNotification>(endOfAnnRcv.value!),
                                cancellationToken);
                        }
                        //分机转menu
                        else if (endOfAnnRcv.value?.Ext != null && endOfAnnRcv.value?.Menu != null)
                        {
                            await _mediator.Publish(_mapper.Map<EndOfAnnExtToMenuNotification>(endOfAnnRcv.value!),
                                cancellationToken);
                        }
                        break;
                    //分机组队列事件
                    case Event.QUEUE:
                        var queueRcv = content.DeserializeWithAuthorize<QueueEvent>();
                        //分机呼入分机组
                        if (queueRcv.value?.Ext != null && queueRcv.value?.Waiting != null)
                        {
                            //组内分机全忙，分机和来电相继呼入分机组
                            if (queueRcv.value?.Waiting.Reason == "")
                            {
                                await _mediator.Publish(_mapper.Map<QueueExtToGroupBusyNotification>(queueRcv.value!),
                                    cancellationToken);
                            }
                            //若所有分机离线，分机和来电呼叫分机组
                            else if (queueRcv.value?.Waiting.Reason == "offline")
                            {
                                await _mediator.Publish(
                                    _mapper.Map<QueueExtToGroupOfflineNotification>(queueRcv.value!),
                                    cancellationToken);
                            }
                            //若排队满了，分机和来电呼叫分机组
                            else if (queueRcv.value?.Waiting.Reason == "full")
                            {
                                await _mediator.Publish(_mapper.Map<QueueExtToGroupFullNotification>(queueRcv.value!),
                                    cancellationToken);
                            }
                        }
                        //组内分机全忙，分机和来电相继呼入分机组
                        //来电呼入分机组
                        else if (queueRcv.value?.Visitor != null && queueRcv.value?.Waiting != null)
                        {
                            //组内分机全忙，分机和来电相继呼入分机组
                            if (queueRcv.value?.Waiting.Reason == "")
                            {
                                await _mediator.Publish(
                                    _mapper.Map<QueueVisitorToGroupBusyNotification>(queueRcv.value!),
                                    cancellationToken);
                            }
                            else if (queueRcv.value?.Waiting.Reason == "offline")
                            {
                                await _mediator.Publish(
                                    _mapper.Map<QueueVisitorToGroupOfflineNotification>(queueRcv.value!),
                                    cancellationToken);
                            }
                            else if (queueRcv.value?.Waiting.Reason == "full")
                            {
                                await _mediator.Publish(
                                    _mapper.Map<QueueVisitorToGroupFullNotification>(queueRcv.value!),
                                    cancellationToken);
                            }
                        }
                        break;
                    //系统重启事件
                    case Event.BOOTUP:
                        var bootupRcv = content.DeserializeWithAuthorize<BootupEvent>();
                        await _mediator.Publish(_mapper.Map<BootupNotification>(bootupRcv.value!), cancellationToken);
                        break;
                    default:
                        break;
                }
            }
        }
    }
}
