using DataSharing.Province.SendTask.SubmitCaseInfo;
using DataSharing.RawData;
using DataSharing.SendTask;
using DataSharing.Share.Dtos.Province;
using DataSharing.Share.Enums;
using MapsterMapper;
using Microsoft.Extensions.Logging;
using Quartz;
using System.Text.Json;
using XF.Domain.Repository;

namespace DataSharing.Province.SendTask
{
    /// <summary>
    /// 服务工单受理 
    /// </summary>
    public class TaskSubmitCaseInfoJob : IJob, IDisposable
    {
        private readonly IMapper _mapper;
        private readonly ILogger<TaskSubmitCaseInfoJob> _logger;
        private readonly IRepository<DsSendTaskSubmitCaseInfo> _sendTaskSubmitCaseInfoRepository;
        private readonly IRepository<DsWaitSendTaskSubmitCaseInfo> _waitSendTaskSubmitCaseInfoRepository;
        private readonly IChannelConfigurationManager _channelConfigurationManager;
        private readonly HuiJuClient _huiJuClient;
        private readonly IRepository<DsSendTaskDetailInfo> _sendTaskDetailInfoRepository;
        private readonly IRepository<DsOrderSend> _orderSendRepository;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mapper"></param>
        /// <param name="logger"></param>
        /// <param name="sendTaskSubmitCaseInfoRepository"></param>
        /// <param name="waitSendTaskSubmitCaseInfoRepository"></param>
        /// <param name="channelConfigurationManager"></param>
        /// <param name="huiJuClient"></param>
        /// <param name="sendTaskDetailInfoRepository"></param>
        /// <param name="orderSendRepository"></param>
        public TaskSubmitCaseInfoJob(IMapper mapper,
            ILogger<TaskSubmitCaseInfoJob> logger,
            IRepository<DsSendTaskSubmitCaseInfo> sendTaskSubmitCaseInfoRepository,
            IRepository<DsWaitSendTaskSubmitCaseInfo> waitSendTaskSubmitCaseInfoRepository,
            IChannelConfigurationManager channelConfigurationManager,
            HuiJuClient huiJuClient,
            IRepository<DsSendTaskDetailInfo> sendTaskDetailInfoRepository,
            IRepository<DsOrderSend> orderSendRepository)
        {
            _mapper = mapper;
            _logger = logger;
            _sendTaskSubmitCaseInfoRepository = sendTaskSubmitCaseInfoRepository;
            _waitSendTaskSubmitCaseInfoRepository = waitSendTaskSubmitCaseInfoRepository;
            _channelConfigurationManager = channelConfigurationManager;
            _huiJuClient = huiJuClient;
            _sendTaskDetailInfoRepository = sendTaskDetailInfoRepository;
            _orderSendRepository = orderSendRepository;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Execute(IJobExecutionContext context)
        {
            var configProvince = _channelConfigurationManager.GetConfigurationProvince();
            //加载数据
            var tasks = await _waitSendTaskSubmitCaseInfoRepository.Queryable()
           .Where(d => d.State == EWaitSendTaskState.WaitPush && d.SendTimes <= 6)
           .OrderBy(d => d.CreationTime)
           .Take(50)
           .ToListAsync(context.CancellationToken);

            _logger.LogInformation("业务汇聚-服务工单受理读取数据条数--------------------------------------" + tasks.Count);

            if (tasks.Count != 0)
            {
                #region 处理请求参数
                var request = new ProvinceListRequest<Share.Dtos.Province.HuiJu.SubmitCaseInfo>(configProvince.ClientId, configProvince.ClientSecret);
                List<Share.Dtos.Province.HuiJu.SubmitCaseInfo> listOrder = [];
                #endregion

                List<DsWaitSendTaskSubmitCaseInfo> taskData = [];

                //处理推送数据
                foreach (var sendTask in tasks)
                {
                    //状态更改为推送中
                    sendTask.State = EWaitSendTaskState.Pushing;
                    //使用乐观锁，控制数据
                    if (await _waitSendTaskSubmitCaseInfoRepository.Updateable(sendTask).ExecuteCommandWithOptLockAsync() > 0)
                    {
                        var existsOrder = listOrder.FirstOrDefault(p => p.CaseSerial == sendTask.ProvinceNo);
                        if (existsOrder is null)
                            //组装这一条数据
                            listOrder.Add(sendTask.RequestData);
                        else
                            sendTask.State = EWaitSendTaskState.StopPush;

                        taskData.Add(sendTask);
                    }
                }

                _logger.LogInformation("业务汇聚-服务工单受理锁定条数--------------------------------------" + taskData.Count);

                if (listOrder != null && listOrder.Count > 0)
                {
                    request.SetData(listOrder);
                    var jsonData = request.ToString();
                    _logger.LogInformation("业务汇聚-服务工单受理请求参数--------------------------------------" + jsonData);
                    ProvinceResponse result = new();
                    string error = "";
                    //执行推送任务
                    try
                    {
                        _logger.LogInformation("准备推送--------------------------------------");
                        result = await _huiJuClient.RequestAsync<ProvinceResponse>(configProvince.HuiJu + PtahDefaults.SubmitCaseInfo, "Post", jsonData, context.CancellationToken);
                    }
                    catch (Exception ex)
                    {
                        error = ex.Message;
                    }
                    _logger.LogInformation("业务汇聚-服务工单受理返回参数--------------------------------------" + System.Text.RegularExpressions.Regex.Unescape(JsonSerializer.Serialize(result)));
                    if (result != null)
                    {
                        //处理数据
                        foreach (var item in taskData)
                        {
                            //如果是下一轮推送，直接将状态修改成待推送，否则正常处理
                            if (item.State == EWaitSendTaskState.StopPush)
                            {
                                item.State = EWaitSendTaskState.WaitPush;
                                //修改待推送表
                                await _waitSendTaskSubmitCaseInfoRepository.UpdateAsync(item, context.CancellationToken);
                            }
                            else
                            {
                                //查询是否有错误
                                //有错误处理
                                //没有错误删除待推送表，更新主表
                                bool isError = false;
                                if (result == null || result.Custom == null || result.ReturnInfo == null)
                                {
                                    //请求报错，那么则所有的推送失败
                                    isError = true;
                                }
                                else
                                {
                                    if (result.Custom.ErrorObjs.Exists(p => p.CaseSerial == item.ProvinceNo && p.ErrorMsg != "本次推送内容中该条数据重复，跳过"))
                                        isError = true;
                                }

                                #region 处理待推送表数据
                                //处理待推送数据
                                if (isError)
                                {
                                    //修改
                                    item.LastTime = DateTime.Now;
                                    item.SendTimes = item.SendTimes + 1;

                                    if (item.FirstTime is null)
                                        item.FirstTime = DateTime.Now;

                                    if (item.SendTimes >= 7)
                                        item.State = EWaitSendTaskState.PushFail;
                                    else
                                        item.State = EWaitSendTaskState.WaitPush;

                                    //修改待推送表
                                    await _waitSendTaskSubmitCaseInfoRepository.UpdateAsync(item, context.CancellationToken);
                                }
                                else
                                {
                                    //删除
                                    await _waitSendTaskSubmitCaseInfoRepository.RemoveAsync(item, cancellationToken: context.CancellationToken);
                                }
                                #endregion

                                #region 处理数据推送主表数据
                                //查询主表
                                var sendData = await _sendTaskSubmitCaseInfoRepository.GetAsync(p => p.Id == item.Id, context.CancellationToken);
                                if (sendData != null)
                                {
                                    sendData.LastTime = DateTime.Now;
                                    sendData.SendTimes = sendData.SendTimes + 1;

                                    if (sendData.FirstTime is null)
                                        sendData.FirstTime = DateTime.Now;

                                    sendData.IsSuccess = isError == false ? ESendTaskState.PushSuccess : ESendTaskState.PushFail;
                                    await _sendTaskSubmitCaseInfoRepository.UpdateAsync(sendData, cancellationToken: context.CancellationToken);
                                }
                                #endregion

                                #region 新增推送明细
                                //新增明细
                                DsSendTaskDetailInfo dsSendTaskDetailInfo = new()
                                {
                                    TaskId = item.Id,
                                    IsSuccess = !isError,
                                    Result = System.Text.RegularExpressions.Regex.Unescape(JsonSerializer.Serialize(result)),
                                    ResultErrorData = error,
                                    ProcessingServices = _channelConfigurationManager.GetConfigurationProcessingServices()
                                };
                                await _sendTaskDetailInfoRepository.AddAsync(dsSendTaskDetailInfo, context.CancellationToken);
                                #endregion

                                #region 上传成功后，处理工单的上传时间，用于统计
                                if (!isError)
                                {
                                    var order = await _orderSendRepository.GetAsync(p => p.ProvinceNo == item.ProvinceNo, context.CancellationToken);
                                    if (order != null)
                                    {
                                        if (order.FirstSendProvinceTime is null)
                                            order.FirstSendProvinceTime = DateTime.Now;

                                        order.LastSendProvinceTime = DateTime.Now;
                                        await _orderSendRepository.UpdateAsync(order, context.CancellationToken);
                                    }
                                }
                                #endregion
                            }
                        }
                    }
                }
            }
        }

        public void Dispose()
        {

        }
    }
}
