using DotNetCore.CAP;
using Hotline.Application.CallCenter;
using Hotline.Configurations;
using Hotline.FlowEngine.Workflows;
using Hotline.Orders;
using Hotline.Share.Dtos.FlowEngine.Workflow;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Dtos.TrCallCenter;
using Hotline.Share.Enums.FlowEngine;
using Hotline.Share.Enums.Order;
using MapsterMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.VisualBasic;
using SqlSugar;
using System.Text;
using NPOI.SS.Formula.Functions;
using XF.Domain.Repository;
using Hotline.FlowEngine.WorkflowModules;
using MediatR;

namespace Hotline.Api.Controllers
{
    public class PushProvinceController : BaseController
    {
        private readonly ILogger<PushProvinceController> _logger;
        private readonly IOrderRepository _orderRepository;
        private readonly IMapper _mapper;
        private readonly ICapPublisher _capPublisher;
        private readonly IRepository<WorkflowTrace> _workflowTraceRepository;
        private readonly ICallApplication _callApplication;
        private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
        private readonly IOrderScreenRepository _orderScreenRepository;
        private readonly IRepository<WorkflowStep> _workflowStepRepository;

        public PushProvinceController(ILogger<PushProvinceController> logger,
             IOrderRepository orderRepository,
             IMapper mapper,
             ICapPublisher capPublisher,
             IRepository<WorkflowTrace> workflowTraceRepository,
             ICallApplication callApplication,
             IOrderScreenRepository orderScreenRepository,
             IOptionsSnapshot<AppConfiguration> appOptions,
             IRepository<WorkflowStep> workflowStepRepository)
        {
            _logger = logger;
            _orderRepository = orderRepository;
            _mapper = mapper;
            _capPublisher = capPublisher;
            _workflowTraceRepository = workflowTraceRepository;
            _callApplication = callApplication;
            _appOptions = appOptions;
            _orderScreenRepository = orderScreenRepository;
            _workflowStepRepository = workflowStepRepository;

        }

        /// <summary>
        /// 推送最新工单信息
        /// </summary>
        /// <param name="Provinces"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("pushneworder")]
        public async Task PushNewOrder(string Provinces)
        {
            Provinces = Provinces.Trim();
            string[] provinceNos = Provinces.Split(',');
            for (int i = 0; i < provinceNos.Length; i++)
            {
                provinceNos[i] = provinceNos[i].Trim();
            }

            var list = await _orderRepository.Queryable().Where(x => provinceNos.Contains(x.ProvinceNo)).ToListAsync();
            if (list != null && list.Any())
            {
                foreach (var item in list)
                {
                    var orderDto = _mapper.Map<OrderDto>(item);
                    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto,
                        cancellationToken: HttpContext.RequestAborted);
                }

            }
        }

        /// <summary>
        /// 推送回访到省上
        /// </summary>
        /// <param name="Provinces"></param>
        /// <returns></returns>
        [HttpPost("publishvisittoprovincebyno")]
        [AllowAnonymous]
        public async Task PublishVisitToProvinceByNo(string Provinces)
        {
            Provinces = Provinces.Trim();
            string[] provinceNos = Provinces.Split(',');
            for (int i = 0; i < provinceNos.Length; i++)
            {
                provinceNos[i] = provinceNos[i].Trim();
            }
            var list = await _orderRepository.Queryable()
                 .Includes(x => x.OrderVisits.Where(q => q.VisitState == EVisitState.Visited).ToList(), d => d.OrderVisitDetails)
                 .Where(x => provinceNos.Contains(x.ProvinceNo) && x.Status == EOrderStatus.Visited).ToListAsync();

            if (list != null && list.Any())
            {
                foreach (var item in list)
                {
                    try
                    {
                        var visit = item.OrderVisits.FirstOrDefault();
                        if (visit != null)
                        {
                            var visitRemark = visit.OrderVisitDetails.Where(q => q.VisitTarget == EVisitTarget.Org).FirstOrDefault()?.VisitContent;
                            //推省上
                            await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisited,
                            new PublishVisitDto()
                            {
                                Order = _mapper.Map<OrderDto>(item),
                                No = visit.No,
                                VisitType = visit.VisitType,
                                VisitName = visit.CreatorName,
                                VisitTime = visit.VisitTime,
                                VisitRemark = string.IsNullOrEmpty(visitRemark) == true ? "满意" : visitRemark,
                                AreaCode = item.AreaCode!,
                                SubjectResultSatifyCode = visit.NowEvaluate.Key,
                                FirstSatisfactionCode = item.FirstVisitResultCode,
                                ClientGuid = ""
                            }, cancellationToken: HttpContext.RequestAborted);
                        }
                    }
                    catch { }
                }
            }
        }

        /// <summary>
        /// 推送工单归档数据
        /// </summary>
        /// <param name="Provinces"></param>
        /// <returns></returns>
        [HttpPost("pushfiledtoprovince")]
        [AllowAnonymous]
        public async Task PushFiledToProvince(string Provinces)
        {
            Provinces = Provinces.Trim();
            string[] provinceNos = Provinces.Split(',');
            for (int i = 0; i < provinceNos.Length; i++)
            {
                provinceNos[i] = provinceNos[i].Trim();
            }

            var unpublishOrders = await _orderRepository.Queryable()
                .Where(d => provinceNos.Contains(d.ProvinceNo) && !string.IsNullOrEmpty(d.ProvinceNo) && d.Status >= EOrderStatus.Filed)
                .ToListAsync(HttpContext.RequestAborted);

            if (unpublishOrders != null && unpublishOrders.Any())
            {
                foreach (var order in unpublishOrders)
                {
                    var trace = await _workflowTraceRepository.Queryable()
                        .FirstAsync(d => d.WorkflowId == order.WorkflowId && d.StepType == EStepType.End,
                            HttpContext.RequestAborted);
                    var orderFlowDto = new OrderFlowDto
                    {
                        Order = _mapper.Map<OrderDto>(order),
                        WorkflowTrace = _mapper.Map<WorkflowTraceDto>(trace)
                    };
                    if (order.SourceChannelCode == AppDefaults.SourceChannel.DianHua &&
                        !string.IsNullOrEmpty(order.CallId))
                    {
                        if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.TianRun)
                        {
                            var callRecord = await _callApplication.GetTianrunCallAsync(order.CallId, HttpContext.RequestAborted);
                            if (callRecord != null)
                            {
                                orderFlowDto.TrCallRecordDto = _mapper.Map<TrCallDto>(callRecord);
                            }
                        }
                        else if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XingTang)
                        {
                            var call = await _callApplication.GetCallAsync(order.CallId, HttpContext.RequestAborted);
                            if (call is not null)
                                orderFlowDto.TrCallRecordDto = _mapper.Map<TrCallDto>(call);
                        }
                    }

                    //这里需要判断是否是警情退回
                    orderFlowDto.IsNonPoliceReturn = false;
                    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFiled, orderFlowDto, cancellationToken: HttpContext.RequestAborted);
                }
            }
        }

        /// <summary>
        /// 根据省编号重新执行工单和通话记录关联并推送省上
        /// </summary>
        /// <returns></returns>
        [HttpPost("OrderRelateCallHandler")]
        [AllowAnonymous]
        public async Task<dynamic> OrderRelateCallHandlerAsync([FromBody] string provinces)
        {
            provinces = provinces.Trim();
            var provinceNos = provinces.Split(',');
            for (int i = 0; i < provinceNos.Length; i++)
            {
                provinceNos[i] = provinceNos[i].Trim();
            }

            var orders = await _orderRepository.Queryable()
                .Where(d => provinceNos.Contains(d.ProvinceNo))
                .Select(d => new { d.Id, d.ProvinceNo })
                .ToListAsync(HttpContext.RequestAborted);

            dynamic sb = new System.Dynamic.ExpandoObject();
            var sbs = new List<dynamic>();
            foreach (var order in orders)
            {
                sb.OrderId = order.Id;
                sb.ProvinceNo = order.ProvinceNo;
                try
                {
                    sb.Message = await _callApplication.OrderRelateCallHandlerAsync(order.Id, HttpContext.RequestAborted);
                }
                catch (ArgumentException e)
                {
                    sb.Message = e.Message;
                }
                finally
                {
                    sbs.Add(sb);
                }
            }
            return sbs;
        }

        /// <summary>
        /// 甄别申请重推
        /// </summary>
        /// <param name="Provinces"></param>
        /// <returns></returns>
        [HttpPost("order_screen_push_province")]
        [AllowAnonymous]
        public async Task OrderScreenPushProvince([FromBody] string Provinces)
        {
            Provinces = Provinces.Trim();
            string[] provinceNos = Provinces.Split(',');
            for (int i = 0; i < provinceNos.Length; i++)
            {
                provinceNos[i] = provinceNos[i].Trim();
            }

            var unpublishScreens = await _orderScreenRepository.Queryable().Includes(x => x.Order)
                .Where(x => provinceNos.Contains(x.Order.ProvinceNo) && !string.IsNullOrEmpty(x.Order.ProvinceNo) && x.Order.Status >= EOrderStatus.Filed)
                .ToListAsync(HttpContext.RequestAborted);
            if (unpublishScreens != null && unpublishScreens.Any())
            {
                foreach (var screen in unpublishScreens)
                {
                    var traces = await _workflowTraceRepository.Queryable()
                        .Where(d => d.WorkflowId == screen.WorkflowId && d.ModuleCode == WorkflowModuleConsts.OrderScreen).ToListAsync(HttpContext.RequestAborted);
                    var currentStep = traces
                        .FirstOrDefault(x => x.Status == EWorkflowStepStatus.WaitForAccept ||
                                             x.Status == EWorkflowStepStatus.WaitForHandle);
                    var prevStep = traces.FirstOrDefault(x => x.Id == currentStep.PrevStepId);

                    var screenDto = _mapper.Map<OrderScreenListDto>(screen);
                    var screenOrderDto = _mapper.Map<OrderDto>(screen.Order);
                    //省件甄别--以省审批前一个节点整理的甄别意见为准推送省上 宜宾
                    if (_appOptions.Value.IsYiBin && prevStep is not null && !string.IsNullOrEmpty(prevStep.Opinion))
                    {
                        screenDto.Content = prevStep.Opinion;
                        screenDto.Files = new List<Share.Dtos.File.FileDto>();
                    }
                    //推省上
                    _capPublisher.Publish(Hotline.Share.Mq.EventNames.HotlineOrderScreenApply, new PublishScreenDto()
                    {
                        Order = screenOrderDto,
                        Screen = screenDto,
                        ClientGuid = ""
                    });
                }
            }
        }

        /// <summary>
        /// 推送工单归档数据
        /// </summary>
        /// <param name="No"></param>
        /// <param name="fileTime"></param>
        /// <returns></returns>
        [HttpGet("pushfiledtoprovincenew")]
        [AllowAnonymous]
        public async Task PushFiledToProvinceNew(string No, DateTime fileTime)
        {
            var order = await _orderRepository.GetAsync(p => p.No == No, HttpContext.RequestAborted);
            if (order != null)
            {
                order.FiledTime = fileTime;
                order.ActualHandleStepCreateTime = fileTime.AddMinutes(-30);
                order.ActualHandleStepAcceptTime = fileTime.AddMinutes(-10);

                var notification = await _workflowStepRepository.Queryable().Includes(x => x.Workflow, w => w.Steps).Where(x => x.ExternalId == order.Id
                && x.BusinessType == EBusinessType.File && x.StepType == EStepType.End).FirstAsync(HttpContext.RequestAborted);
                if (notification != null)
                {
                    var orderFlowDto = new OrderFlowDto
                    {
                        Order = _mapper.Map<OrderDto>(order),
                    };
                    var workflowTrace = _mapper.Map<WorkflowTraceDto>(notification);
                    workflowTrace.HandleTime = fileTime;

                    orderFlowDto.WorkflowTrace = workflowTrace;
                    //这里需要判断是否是警情退回
                    orderFlowDto.IsNonPoliceReturn = false;
                    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFiled, orderFlowDto, cancellationToken: HttpContext.RequestAborted);
                }
            }
        }

    }
}
