using Hotline.Caching.Interfaces;
using Hotline.CallCenter.Calls;
using Hotline.CallCenter.Configs;
using Hotline.EventBus;
using Hotline.Realtimes;
using Hotline.Share.Dtos.CallCenter;
using Hotline.Share.Enums.CallCenter;
using Microsoft.Extensions.Options;
using NewRock.Sdk;
using NewRock.Sdk.Control.Request;
using NewRock.Sdk.Transfer.Connect.Request;
using NewRock.Sdk.Transfer.Queue.Request;

namespace Hotline.Application.Handlers.CallCenter
{
    public class NewRockBaseHandler
    {
        private readonly INewRockClient _newRockClient;
        private readonly IOptionsSnapshot<CallCenterConfiguration> _options;
        private readonly ICallRepository _callRepository;
        private readonly ICallCacheManager _callCacheManager;
        private readonly IRealtimeService _realtimeService;
        public NewRockBaseHandler(
            INewRockClient newRockClient,
            IOptionsSnapshot<CallCenterConfiguration> options,
            ICallRepository callRepository,
            ICallCacheManager callCacheManager,
            IRealtimeService realtimeService)
        {
            _newRockClient = newRockClient;
            _options = options;
            _callRepository = callRepository;
            _callCacheManager = callCacheManager;
            _realtimeService = realtimeService;
        }

        public async Task HandlerIvr(IvrAnswer? runResult, Call model, CancellationToken cancellationToken)
        {
            if (runResult != null)
            {
                var ivrAnswer = runResult;

                switch (ivrAnswer.IvrAnswerType)
                {
                    case EIvrAnswerType.Voice:
                        var tomenuId = ivrAnswer.Content;
                        switch (model?.CallType)
                        {
                            case ECallType.ExtToOuter:
                                await _newRockClient.OuterToMenu(new OuterToMenuRequest()
                                {
                                    Attribute = "Connect",
                                    Menu = new OuterToMenuMenu() { Id = tomenuId },
                                    Outer = new OuterToMenuOuter() { Id = model.ConversationId },
                                    //VoiceFile = string.IsNullOrEmpty(ivrAnswer.PreVoice) ? "" : ivrAnswer.PreVoice,
                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                break;
                            case ECallType.VisitorCallIn:
                                await _newRockClient.VisitorToMenu(new VisitorToMenuRequest()
                                {
                                    Attribute = "Connect",
                                    Menu = new VisitorToMenuMenu() { Id = tomenuId },
                                    Visitor = new VisitorToMenuVisitor() { Id = model.ConversationId },
                                    //VoiceFile = string.IsNullOrEmpty(ivrAnswer.PreVoice) ? "" : ivrAnswer.PreVoice,
                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                break;
                            default:
                                throw new ArgumentOutOfRangeException();
                        }
                        break;
                    case EIvrAnswerType.Tel:
                        var telNo = ivrAnswer.Content;
                        switch (model.CallType)
                        {
                            case ECallType.VisitorCallIn:
                                //await _newRockClient.VisitorToExt(new VisitorToExtRequest()
                                //{
                                //    Attribute = "Connect",
                                //    Ext = new VisitorToExtExt() { Id = telNo },
                                //    VoiceFile = string.IsNullOrEmpty(ivrAnswer.PreVoice) ? "" : ivrAnswer.PreVoice,
                                //    AutoAnswer = "",
                                //}, _options.Value.ReceiveKey, _options.Value.Expired, cancellationToken);
                                //来电去队列
                                await _newRockClient.VisitorToExtQueue(new VisitorToExtQueueRequest()
                                {
                                    Attribute = "Queue",
                                    Ext = new VisitorToExtQueueExt() { Id = telNo },
                                    Visitor = new VisitorToExtQueueVisitor() { Id = model.ConversationId }
                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                break;
                            case ECallType.ExtToOuter:
                                await _newRockClient.OuterToExt(new OuterToExtRequest()
                                {
                                    Attribute = "Connect",
                                    Ext = new OuterToExtExt() { Id = telNo },
                                    Outer = new OuterToExtOuter() { Id = model.ConversationId }
                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                break;
                            default:
                                throw new ArgumentOutOfRangeException();
                        }
                        break;
                    case EIvrAnswerType.TelGroup:
                        var groupId = ivrAnswer.Content;
                        model.InQueueTime = DateTime.Now;
                        await _callRepository.UpdateAsync(model);
                        await _newRockClient.VisitorToGroupQueue(new VisitorToGroupQueueRequest()
                        {
                            Attribute = "Queue",
                            Group = new VisitorToGroupQueueGroup() { Id = groupId },
                            Visitor = new VisitorToGroupQueueVisitor() { Id = model.ConversationId }
                        }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);

                        //处理队列记录
                        _callCacheManager.AddCallCache(model);
                        await _realtimeService.CallQueueAsync(_callCacheManager.GetCallQueueList(), cancellationToken);
                        break;

                    case EIvrAnswerType.Out:
                        var phoneNo = ivrAnswer.Content;
                        switch (model.CallType)
                        {
                            case ECallType.VisitorCallIn:
                                await _newRockClient.VisitorToOuter(new VisitorToOuterRequest()
                                {
                                    Attribute = "Connect",
                                    Visitor = new VisitorToOuterVisitor() { Id = model.ConversationId },
                                    Outer = new VisitorToOuterOuter()
                                    {
                                        To = phoneNo,
                                        //TODO DISPLAY属性待定
                                    }
                                },
                                    _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                break;
                            case ECallType.ExtToOuter:
                                await _newRockClient.OuterToOuter(new OuterToOuterRequest()
                                {
                                    Attribute = "Connect",
                                    Outer = new List<OuterToOuterOuterModel>(){
                                        new(){Id = model.ConversationId},
                                            new(){To = phoneNo},
                                        }
                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                break;
                            default:
                                throw new ArgumentOutOfRangeException();
                        }
                        break;
                    case EIvrAnswerType.HangUp:
                        var id = ivrAnswer.Content;
                        switch (model?.CallType)
                        {
                            case ECallType.VisitorCallIn:
                                await _newRockClient.ClearCall(new ClearCallRequest()
                                {
                                    Attribute = "Clear",
                                    Visitor = new ClearCallVisitor() { Id = model.ConversationId },
                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                break;
                            case ECallType.ExtToOuter:
                                await _newRockClient.ClearCall(new ClearCallRequest()
                                {
                                    Attribute = "Clear",
                                    Outer = new ClearCallOuter() { Id = model.ConversationId },
                                }, _options.Value.NewRock.ReceiveKey, _options.Value.NewRock.Expired, cancellationToken);
                                break;
                        }
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
        }
    }
}
