using DocumentFormat.OpenXml.Office.CustomUI;
using DotNetCore.CAP;
using Hotline.CallCenter.Calls;
using Hotline.Repository.SqlSugar;
using Hotline.Share.Mq;
using Hotline.Share.Tools;
using MapsterMapper;
using Microsoft.Extensions.Logging;
using Quartz;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XF.Domain.Repository;
using XingTang.Sdk;

namespace Hotline.Application.Jobs
{
    /// <summary>
    /// 兴唐评价结果
    /// </summary>
    public class XingTangCallSatisfactionSyncJob : IJob, IDisposable
    {
        private readonly IRepository<CallNative> _callNativeRepository;
        private readonly ISqlSugarClient _db;
        private readonly IRepository<CallSatisfaction> _callSatisfactionRepository;
        private readonly IMapper _mapper;
        private readonly ILogger<XingTangCallSatisfactionSyncJob> _logger;

        public XingTangCallSatisfactionSyncJob(IRepository<CallNative> callRepository, ISugarUnitOfWork<XingTangDbContext> uow,
            IRepository<CallSatisfaction> callSatisfactionRepository, IMapper mapper, ILogger<XingTangCallSatisfactionSyncJob> logger)
        {
            _callNativeRepository = callRepository;
            _db = uow.Db;
            _callSatisfactionRepository = callSatisfactionRepository;
            _mapper = mapper;
            _logger = logger;
        }

        public void Dispose()
        {
        }

        public async Task Execute(IJobExecutionContext context)
        {
            var callSatisfactions = await _db.Queryable<XingtangSatisfaction>()
                .Where(d => (d.IsSync == null || !d.IsSync) && (d.Tries == null || d.Tries <= 50))
                .OrderBy(d => d.Id)
                .Take(10)
                .ToListAsync(context.CancellationToken);

            if (callSatisfactions.IsNullOrEmpty()) return;
            var occupyCallSatisfactions = new List<XingtangSatisfaction>();
            foreach (var callSatisfaction in callSatisfactions)
            {
                callSatisfaction.IsSync = true;
                callSatisfaction.Tries += 1;

                var rows = await _db.Updateable(callSatisfaction)
                    .ExecuteCommandWithOptLockAsync();
                if (rows > 0)
                    occupyCallSatisfactions.Add(callSatisfaction);
            }

            if (occupyCallSatisfactions.IsNullOrEmpty()) return;
            try
            {
                var callStatisfactions = _mapper.Map<List<CallSatisfaction>>(occupyCallSatisfactions);
                var callNos = callSatisfactions.Select(m => m.CallNo).ToList();
                var callNative = await _callNativeRepository.Queryable().Where(x => callNos.Contains(x.CallNo) && string.IsNullOrEmpty(x.AudioFile) == false).Select(x => new { x.Id, x.CallNo }).ToListAsync();
                var failSyncList = new List<XingtangSatisfaction>();
                var newCallNative = new List<CallSatisfaction>();
                foreach (var item in callStatisfactions)
                {
                    var call = callNative.FirstOrDefault(m => m.CallNo == item.CallNo);
                    if (call == null)
                    {
                        var goSync = (occupyCallSatisfactions.FirstOrDefault(m => m.CallNo == item.CallNo)?.Tries ?? 0) == 50;
                        if (goSync)
                        {
                            newCallNative.Add(item);
                        }
                        else
                        {
                            var fail = callSatisfactions.First(m => m.CallNo == item.CallNo);
                            fail.IsSync = false;
                            failSyncList.Add(fail);
                        }
                    }
                    else
                    {
                        newCallNative.Add(item);
                        item.Id = call.Id;
                        await _callNativeRepository.Updateable()
                            .SetColumns(m => m.ReplyTxt, item.Result)
                            .Where(m => m.CallNo == call.CallNo)
                            .ExecuteCommandAsync();
                    }
                }

                await _db.Updateable(failSyncList).UpdateColumns(m => new { m.IsSync }).ExecuteCommandAsync();
                await _callSatisfactionRepository.AddRangeAsync(newCallNative, context.CancellationToken);
            }
            catch (Exception e)
            {
                _logger.LogError($"获取通话记录评价：{e.Message} \n {e.StackTrace}");
                foreach (var callSatisfaction in occupyCallSatisfactions)
                {
                    callSatisfaction.IsSync = false;
                }

                await _db.Updateable(occupyCallSatisfactions)
                    .UpdateColumns(d => new { d.IsSync })
                    .ExecuteCommandAsync(context.CancellationToken);
            }
        }
    }
}