using Hotline.CallCenter.Calls;
using Hotline.Share.Dtos.TrCallCenter;
using Hotline.Share.Enums.CallCenter;
using Mapster;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Hotline.CallCenter.Tels;
using XingTang.Sdk;
using Hotline.Share.Dtos.CallCenter;
using Hotline.Share.Dtos.Order;

namespace Hotline.Application.Mappers
{
    public class CallMapperConfigs : IRegister
    {
        public void Register(TypeAdapterConfig config)
        {
            config.ForType<ReceiveCallRecordDto, TrCallRecord>()
                .Map(d => d.User, x => x.user)
                .Map(d => d.RecordingFileName, x => x.recording_file_name)
                .Map(d => d.CallDirection, x => x.call_direction == "in" ? ECallDirection.In : ECallDirection.Out)
                .Map(d => d.EndBy,
                    x => x.hangup_side == "caller"
                        ? EEndBy.From
                        : (x.hangup_side == "callee" ? EEndBy.To : EEndBy.None))
                .Map(d => d.AgentTransferNumber, x => x.agent_transfer_number)
                .Map(d => d.CallAccept, x => x.call_accept)
                .Map(d => d.CPN, x => x.caller_id_number)
                .Map(d => d.CPNName, x => x.caller_id_name)
                .Map(d => d.CDPN, x => x.destination_number)
                .Map(d => d.RecordingFileUrl, x => x.recording_file_url)
                .Map(d => d.Gateway, x => x.gateway)
                .Map(d => d.OtherStr, x => x.other_str)
                .Map(d => d.OtherAccept, x => x.other_accept)
                .Map(d => d.Status, x => x.status)
                .Map(d => d.OlaQueue, x => x.ola_queue)
                .Map(d => d.BatchAccept, x => x.batch_accept)
                .Map(d => d.IvrDtmf, x => x.ivr_dtmf)
                .Map(d => d.DtmfType, x => x.dtmf_type)
                .AfterMapping((s, d) => { d.CreatedTime = DateTime.Parse(s.created_time); })
                .AfterMapping((s, d) => { d.AnsweredTime = FormatDateTime(s.answered_time); })
                .AfterMapping((s, d) => { d.OverTime = DateTime.Parse(s.over_time); })
                .AfterMapping((s, d) => { d.BeginIvrTime = FormatDateTime(s.beginIvrTime); })
                .AfterMapping((s, d) => { d.EndIvrTime = FormatDateTime(s.endIvrTime); })
                .AfterMapping((s, d) => { d.BeginQueueTime = FormatDateTime(s.beginQueueTime); })
                .AfterMapping((s, d) => { d.EndQueueTime = FormatDateTime(s.endQueueTime); })
                .AfterMapping((s, d) => { d.BeginRingTime = FormatDateTime(s.beginRingTime); })
                .AfterMapping((s, d) => { d.EndRingTimg = FormatDateTime(s.endRingTime); })
                .AfterMapping((s, d) =>
                {
                    if (string.IsNullOrEmpty(s.recording_file_url)) return;
                    var uri = new Uri(s.recording_file_url);
                    d.RecordingBaseAddress = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
                    d.RecordingAbsolutePath = uri.AbsolutePath;
                })
                ;


            config.ForType<ReceiveCallEvaluateDto, TrCallEvaluate>()
                .Map(d => d.Dtmf, x => x.dtmf)
                .Map(d => d.CallAccept, x => x.call_accept)
                .Map(d => d.Type, x => x.type);

            config.ForType<XingtangCall, CallNative>()
                .Map(d => d.CallNo, s => s.CallGuid)
                .Map(d => d.Direction, s => s.CallType)
                .Map(d => d.FromNo, s => s.Caller)
                .Map(d => d.ToNo, s => s.Called)
                .Map(d => d.TelNo, s => s.Ext)
                .Map(d => d.BeginIvrTime, s => s.CallStartTime)
                .Map(d => d.EndIvrTime, s => s.EnqueueTime)
                .Map(d => d.BeginQueueTime, s => s.EnqueueTime)
                .Map(d => d.EndQueueTime, s => s.DequeueTime)
                .Map(d => d.BeginRingTime, s => s.ReceiveStartTime)
                .Map(d => d.EndRingTime, s => s.ReceiveEndTime.HasValue ? s.ReceiveEndTime : s.CallEndTime)
                .Map(d => d.AnsweredTime, s => s.ReceiveEndTime)
                .Map(d => d.EndTime, s => s.CallEndTime)
                .Map(d => d.GroupId, s => s.SkillId.ToString())
                .Map(d => d.StaffNo, s => s.UserCode)
                .Map(d => d.Duration, s => s.Duration)
                .Map(d => d.RingDuration, s => s.RingTime)
                .Map(d => d.WaitDuration, s => s.WaitTime)
                .Map(d => d.AudioFile, s => s.AudioFile)
                .Map(d => d.AgentTransferNumber, s => s.TransCalled)
                .AfterMapping((s, d) =>
                {
                    if (s.CallState == 0 || s.CallState == 4 || s.CallState == 5 || s.CallState == 8)
                        d.CallState = ECallState.On;
                    if (s.CallState == 1)
                        d.CallState = ECallState.NotAcceptedHang;
                    if (s.CallState == 2 || s.CallState == 3 || s.CallState == 7)
                        d.CallState = ECallState.Missed;
                    if (s.CallState == 6)
                        d.CallState = ECallState.IVRNoAccept;
                })
                .AfterMapping((s, d) =>
                {
                    d.EndBy = d.Direction == ECallDirection.In
                        ? EEndBy.From
                        : EEndBy.To;
                })
                .AfterMapping((s, d) =>
                {
                    if (s.BlackList == 1)
                        d.CallIdentity = ECallIdentity.Black;
                    if (s.WhiteList == 1)
                        d.CallIdentity = ECallIdentity.White;
                })
                ;

            config.ForType<XingtangSatisfaction, CallSatisfaction>()
                .Map(d => d.CallNo, s => s.CallNo)
                .Map(d => d.Result, s => s.Result)
                ;

            config.ForType<XingtangSeatOperation, TelOperation>()
                .Map(d => d.StaffNo, s => s.UserCode)
                .Map(d => d.TelNo, s => s.Ext)
                .Map(d => d.OperateState, s => s.ExecutionState)
                //.Map(d => d.OperateStateText, s => s.GetExecutionStateText())
                .Map(d => d.OperateTime, s => s.ExecutionTime)
                .AfterMapping((s, d) => d.OperateStateText = s.GetExecutionStateText())
                ;

            config.ForType<CallNative, TrCallDto>()
                .Map(d => d.CPN, s => s.FromNo)
                .Map(d => d.OnState, s => s.AnsweredTime.HasValue ? EOnState.On : EOnState.NoOn)
                .Map(d => d.CallDirection, s => s.Direction)
                .Map(d => d.AnsweredTime, s => s.AnsweredTime)
                .Map(d => d.OverTime, s => s.EndTime)
                .Map(d => d.BeginIvrTime, s => s.BeginIvrTime)
                .Map(d => d.BeginQueueTime, s => s.BeginQueueTime)
                .Map(d => d.BeginRingTime, s => s.BeginRingTime)
                .Map(d => d.Duration, s => s.Duration)
                .Map(d => d.TelNo, s => s.TelNo)
                .Map(d => d.RecordingFileUrl, s => s.AudioFile)
                .Map(d => d.OtherAccept, s => s.Id)
                ;

            config.ForType<TrCallRecord, TrCallDtoNew>()
                .Map(d => d.Cpn, s => s.CPN)
                .Map(d => d.Cdpn, s => s.CDPN)
                ;

            config.ForType<TrCallRecord, CallNative>()
                .Map(d => d.CallNo, s => s.OtherAccept)
                .Map(d => d.FromNo, s => s.CPN)
                .Map(d => d.ToNo, s => s.CDPN)
                .Map(d => d.EndRingTime, s => s.EndRingTimg)
                .Map(d => d.AudioFile, s => s.RecordingAbsolutePath)
                .Map(d => d.BeginIvrTime, s => s.CreatedTime);

            config.ForType<VisitDto, OrderRelevanceCallIdDto>()
                .Map(d => d.Id, s => s.Id)
                .Map(d => d.CallId, s => s.CallId);
            config.ForType<AddOrderDto, OrderRelevanceCallIdDto>()
                .Map(d => d.CallId, s => s.CallId);
        }

        private DateTime? FormatDateTime(string? time)
        {
            if (string.IsNullOrEmpty(time)) return null;

            try
            {
                return DateTime.Parse(time);
            }
            catch
            {
                return null;
            }
        }
    }
}