using Hotline.Ai.Quality;
using Hotline.Application.CallCenter;
using Hotline.Caching.Interfaces;
using Hotline.CallCenter.Calls;
using Hotline.CallCenter.Configs;
using Hotline.EventBus;
using Hotline.FlowEngine.Notifications;
using Hotline.Orders;
using Hotline.Quality;
using Hotline.Settings;
using Hotline.Share.Dtos.Quality;
using Hotline.Share.Enums.Quality;
using MapsterMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using StackExchange.Redis;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
using Hotline.Quality.Notifications;
using XF.Domain.Authentications;
using XF.Domain.Constants;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using XF.Domain.Repository;
using Hotline.Share.Enums.CallCenter;
using Hotline.Configurations;

namespace Hotline.Application.Quality
{
    public class QualityApplication : IQualityApplication, IScopeDependency
    {
        private readonly ISessionContext _sessionContext;
        private readonly IMapper _mapper;
        private readonly IRepository<QualityDetail> _qualiteyDetail;
        private readonly IQualityRepository _qualityRepository;
        private readonly IOrderRepository _orderRepository;
        private readonly IRepository<QualityTemplate> _qualityTemplate;
        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
        private readonly ILogger<Hotline.Quality.Quality> _logger;
        private readonly ICallApplication _callApplication;
        private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
        private readonly Publisher _publisher;
        private readonly IRepository<TrCallRecord> _trCallRecordRepository;

		public QualityApplication(
            ISessionContext sessionContext,
            IMapper mapper,
            IRepository<QualityDetail> qualiteyDetail,
            IQualityRepository qualityRepository,
            IRepository<QualityTemplate> qualityTemplate,
            IOrderRepository orderRepository,
            ISystemSettingCacheManager systemSettingCacheManager,
            ICallApplication callApplication,
            IOptionsSnapshot<AppConfiguration> appOptions,
            ILogger<Hotline.Quality.Quality> logger,
            Publisher publisher,
            IRepository<TrCallRecord> trCallRecordRepository)
        {
            _sessionContext = sessionContext;
            _mapper = mapper;
            _qualiteyDetail = qualiteyDetail;
            _qualityRepository = qualityRepository;
            _qualityTemplate = qualityTemplate;
            _orderRepository = orderRepository;
            _systemSettingCacheManager = systemSettingCacheManager;
            _callApplication = callApplication;
            _appOptions = appOptions;
            _logger = logger;
            _publisher = publisher;
            _trCallRecordRepository = trCallRecordRepository;
		}

        /// <summary>
        /// 新增质检
        /// </summary>
        /// <param name="Source"></param>
        /// <param name="OrderId"></param>
        /// <param name="VisitId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddQualityAsync(EQualitySource Source, string OrderId, string VisitId, CancellationToken cancellationToken)
        {
            QualityAddDto quality = new QualityAddDto
            {
                Source = Source,
                OrderId = OrderId,
                VisitId = VisitId
            };
            var count = await _qualityRepository.CountAsync(x => x.OrderId == OrderId && x.Source == Source, cancellationToken);
            if (count <= 0)
                await AddQualityAsync(quality, cancellationToken);
            else
            {
                if (Source == EQualitySource.Visit) await _qualityRepository.Updateable().SetColumns(x => x.VisitId == VisitId).Where(x => x.OrderId == OrderId && x.Source == Source).ExecuteCommandAsync();
            }
        }

        /// <summary>
        /// 新增质检
        /// </summary>
        /// <param name="Source"></param>
        /// <param name="OrderId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddQualityAsync(EQualitySource Source, string OrderId, CancellationToken cancellationToken)
        {
            QualityAddDto quality = new QualityAddDto
            {
                Source = Source,
                OrderId = OrderId
            };
            var count = await _qualityRepository.CountAsync(x => x.OrderId == OrderId && x.Source == Source, cancellationToken);
            if (count <= 0)
                await AddQualityAsync(quality, cancellationToken);
        }

        /// <summary>
        /// 新增质检实现
        /// </summary>
        /// <param name="model"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddQualityAsync(QualityAddDto model, CancellationToken cancellationToken)
        {
            var quality = _mapper.Map<Hotline.Quality.Quality>(model);
            quality.InitId();

            if (model.QualityDetails.Any())
            {
                foreach (var item in model.QualityDetails)
                {
                    item.QualityId = quality.Id;
                }
                List<QualityDetail> details = _mapper.Map<List<QualityDetail>>(model.QualityDetails);
                await _qualiteyDetail.AddRangeAsync(details, cancellationToken);
            }
            var order = await _orderRepository.GetAsync(model.OrderId);
			//受理智能质检
			if (model.Source == EQualitySource.Accepted)
            {
                var teAny = await _qualityTemplate.Queryable()
                    .LeftJoin<QualityTemplateDetail>((x, d) => x.Id == d.TemplateId)
                    .LeftJoin<QualityItem>((x, d, i) => d.ItemId == i.Id)
                    .Where((x, d, i) => i.IsIntelligent == 1).AnyAsync();
                if (teAny)
                {
                    if (order != null && !string.IsNullOrEmpty(order.CallId))
                    {
                        quality.AiQuality = true;
                        quality.Mode = "智能质检";
                    }
                }
            }
            await _qualityRepository.AddAsync(quality, cancellationToken);
            ///调用智能质检 捷通
			if (quality.AiQuality is true)
            {
                try
                {
                    var audioFile = string.Empty;
                    var fromNo = string.Empty;
                    DateTime? callStartTime = null;
                    if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.TianRun)
                    {
                        var call = await _callApplication.GetTianrunCallAsync(order.CallId, cancellationToken);
                        audioFile = call.RecordingAbsolutePath;
                        fromNo = call.CPN;
                        callStartTime = call.CreatedTime;
                    }
                    else if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XingTang)
                    {
                        var call = await _callApplication.GetCallAsync(order.CallId, cancellationToken);
                        audioFile = call.AudioFile;
                        fromNo = call.FromNo;
                        callStartTime = call.BeginIvrTime;
                    }

                    var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
                    var handler = new AiQualityHandler() 
                    {
                        Id = quality.Id,
                        AudioFile =audioFile,
                        FromNo = fromNo,
                        CallStartTime = callStartTime,
                        ViteRecordPrefix = setting?.SettingValue[0],
                        Source = quality.Source.ToString(),
					};
                   await  _publisher.PublishAsync(new AiOrderQualityNotify(handler),PublishStrategy.ParallelNoWait,cancellationToken);
                }
                catch (Exception e)
                {
                    _logger.LogError($"写入智能质检异常！, \r\n{e.Message}");
                }
            }

            _logger.LogInformation($"质检对象：{System.Text.Json.JsonSerializer.Serialize(quality,
                new JsonSerializerOptions { Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.CjkUnifiedIdeographs) })}");
        }

        /// <summary>
        /// 修改质检信息
        /// </summary>
        /// <param name="model"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task UpdateQualityAsync(UpdateQualityDto model, CancellationToken cancellationToken)
        {
            //验证工单是否可以申请
            var quality = await _qualityRepository.GetAsync(model.Id, cancellationToken);
            if (quality is null)
                throw UserFriendlyException.SameMessage("无效质检");
            _mapper.Map(model, quality);
            quality.State = EQualityState.End;
            quality.UserName = _sessionContext.UserName;
            quality.QualityTime = DateTime.Now;
            await _qualityRepository.UpdateAsync(quality, cancellationToken);
            List<QualityDetail> deleteDetails = await _qualiteyDetail.Queryable().Where(x => x.QualityId == model.Id).ToListAsync(cancellationToken);
            await _qualiteyDetail.RemoveRangeAsync(deleteDetails, cancellationToken);
            if (model.QualityDetails.Any())
            {
                foreach (var item in model.QualityDetails)
                {
                    item.QualityId = model.Id;
                }
                List<QualityDetail> details = _mapper.Map<List<QualityDetail>>(model.QualityDetails);
                await _qualiteyDetail.AddRangeAsync(details, cancellationToken);
            }
        }

        /// <summary>
        /// 智能质检数据返回
        /// </summary>
        /// <returns></returns>
        public async Task AiResultAsync(List<AiQualityResultDto> model, CancellationToken cancellationToken) 
        {
            foreach(var item in model)
            {
                if (item.extended_field.field11 == "AiAnswered")
                {
                    await AiAnsweredDisposeAsync(item, cancellationToken);
				}
                if (item.extended_field.field11 == "Accepted")
                {
	                await AiQualityDisposeAsync(item, cancellationToken);
				}
			}
        }
        /// <summary>
        /// 智能质检数据处理
        /// </summary>
        /// <returns></returns>
		public async Task AiQualityDisposeAsync(AiQualityResultDto model, CancellationToken cancellationToken)
        {
			var quality = await _qualityRepository.GetAsync(model.record_id,cancellationToken);
			if (quality is { State: EQualityState.Apply } && model.score_items != null && model.score_items.Any())
			{
				List<QualityDetail> details = new List<QualityDetail>();
				foreach (var item2 in model.score_items)
				{
					if (item2.score > 0)
					{
						var detailsSentence = new List<QualityDetail>();
						QualityDetail detail = new QualityDetail
						{
							QualityId = quality.Id,
							Second = 0,
							EndSecond = 0,
							Name = item2.name,
							Content = item2.description,
							Intelligent = true,
							Grade = item2.score,
							Check = true,
						};
						if (item2?.qualityModels?.Count > 0)
						{
							foreach (var models in item2.qualityModels)
							{
								if (models?.sentenceResults?.Count > 0)
								{
									for (int i = 0; i < models.sentenceResults.Count; i++)
									{
										var newDetail = new QualityDetail();
										_mapper.Map(detail, newDetail);
										var sentenceList = model.trans_data.sentence_list.First(x => x.index == models.sentenceResults[i].index);
										newDetail.Second = sentenceList.start;
										newDetail.EndSecond = sentenceList.end == null ? 0 : sentenceList.end;
										newDetail.Content = sentenceList.text;
										detailsSentence.Add(newDetail);
									}
								}
							}
						}
						if (item2?.audioAttributes?.Count > 0)
						{
							foreach (var audio in item2.audioAttributes)
							{
								if (audio?.sentenceResults?.Count > 0)
								{
									for (int i = 0; i < audio.sentenceResults.Count; i++)
									{
										var newDetail = new QualityDetail();
										_mapper.Map(detail, newDetail);
										var sentenceList = model.trans_data.sentence_list.First(x => x.index == audio.sentenceResults[i].index);
										newDetail.Second = sentenceList.start;
										newDetail.EndSecond = sentenceList.end == null ? 0 : sentenceList.end;
										newDetail.Content = sentenceList.text;
										detailsSentence.Add(newDetail);
									}
								}

							}
						}
						if (detailsSentence.Count == 0)
						{
							details.Add(detail);
						}
						else
						{
							details.AddRange(detailsSentence);
						}
					}
				}
				await _qualiteyDetail.AddRangeAsync(details,cancellationToken);
			}
		}
        /// <summary>
        /// 智能应答数据处理  暂时只支持天润  
        /// </summary>
        /// <returns></returns>
        public async Task AiAnsweredDisposeAsync(AiQualityResultDto model, CancellationToken cancellationToken)
        {
			var call = await _callApplication.GetTianrunCallTransliterationAsync(model.record_id, cancellationToken);
            if (call != null)
            {
                var transliterationContent = string.Empty;
				foreach (var item in model.trans_data.sentence_list)
	            {
                    var text = "user".Equals(item.role) ? item.text + "\n" : string.Empty;
                    transliterationContent += text;
				}
                transliterationContent = transliterationContent.Length > 7500 ? transliterationContent.Substring(0, 7500) : transliterationContent;
				var state = !string.IsNullOrEmpty(transliterationContent)? ECallTransliterationState.Succeed : ECallTransliterationState.Fail;
				await _trCallRecordRepository.Updateable().SetColumns(o => new TrCallRecord { TransliterationState = state, TransliterationContent = transliterationContent })
					.Where(o => o.Id == call.Id).ExecuteCommandAsync(cancellationToken);
			}
		}


	}
}
