using DotNetCore.CAP;
using Hotline.FlowEngine.Notifications;
using Hotline.FlowEngine.WorkflowModules;
using Hotline.Orders;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Enums.Order;
using MapsterMapper;
using MediatR;
using Hotline.Share.Dtos;
using XF.Domain.Repository;
using XF.Domain.Authentications;

namespace Hotline.Application.Orders.OrderScreenHandler;
public class OrderScreenEndWorkflowHandler : INotificationHandler<EndWorkflowNotify>
{
	private readonly IOrderRepository _orderRepository;
	private readonly ICapPublisher _capPublisher;
	private readonly IMapper _mapper;
	private readonly IRepository<OrderVisitDetail> _orderVisitedDetailRepository;
	private readonly IRepository<OrderScreen> _orderScreenRepository;
	private readonly IRepository<OrderVisit> _orderVisitRepository;
	private readonly ISessionContext _sessionContext;
	private readonly IRepository<OrderScreenDetail> _orderScreenDetailRepository;

	public OrderScreenEndWorkflowHandler(
		IOrderRepository orderRepository,
		ICapPublisher capPublisher,
		IMapper mapper,
		IRepository<OrderVisitDetail> orderVisitedDetailRepository,
		IRepository<OrderScreen> orderScreenRepository,
		IRepository<OrderVisit> orderVisitRepository,
		ISessionContext sessionContext,
		IRepository<OrderScreenDetail> orderScreenDetailRepository)
	{
		_orderRepository = orderRepository;
		_capPublisher = capPublisher;
		_mapper = mapper;
		_orderScreenRepository = orderScreenRepository;
		_orderVisitedDetailRepository = orderVisitedDetailRepository;
		_orderVisitRepository = orderVisitRepository;
		_sessionContext = sessionContext;
		_orderScreenDetailRepository = orderScreenDetailRepository;
	}

	/// <summary>Handles a notification</summary>
	/// <param name="notification">The notification</param>
	/// <param name="cancellationToken">Cancellation token</param>
	public async Task Handle(EndWorkflowNotify notification, CancellationToken cancellationToken)
	{
		if (notification.Workflow.ModuleCode == WorkflowModuleConsts.OrderScreen) 
		{
			var workflow = notification.Workflow;
			//审批是否通过
			var isReviewPass = workflow.IsReviewPass();

			var screen = await _orderScreenRepository.GetAsync(workflow.ExternalId, cancellationToken);
			if (screen != null)
			{
				screen.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
				if (isReviewPass)
				{
					screen.Status = EScreenStatus.End;
					screen.ReplyContent = workflow.ActualOpinion;
					await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
					var visitDetail =
						await _orderVisitedDetailRepository.GetAsync(screen.VisitDetailId, cancellationToken);
					if (visitDetail != null)
					{
						var screenSatisfy = new Kv() { Key = "-1", Value = "视为满意" };
						visitDetail.OrgProcessingResults = screenSatisfy;
						//visitDetail.OrgHandledAttitude = screenSatisfy;
						await _orderVisitedDetailRepository.UpdateAsync(visitDetail, cancellationToken);
						// 修改主表当前评价结果
						await _orderVisitRepository.Updateable().SetColumns(v => new OrderVisit() { NowEvaluate = screenSatisfy }).Where(v => v.Id == visitDetail.VisitId).ExecuteCommandAsync(cancellationToken);
						//获取回访信息
						var visit = await _orderVisitRepository.Queryable().Includes(x => x.Order)
							.Includes(x => x.OrderVisitDetails)
							.Where(x => x.Id == screen.VisitId).FirstAsync(cancellationToken);
						if (visit != null)
						{
							//获取回访明细
							var visitDe = visit.OrderVisitDetails.First(x => x.Id == screen.VisitDetailId);
							//推省上
							await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderScreenApplyed,
								  new PublishVisitDto()
								  {
									  Order = _mapper.Map<OrderDto>(visit.Order),
									  No = visit.No,
									  VisitType = visit.VisitType,
									  VisitName = visit.CreatorName,
									  VisitTime = visit.VisitTime,
									  VisitRemark = string.IsNullOrEmpty(visitDe.VisitContent) ? screenSatisfy.Value : visitDe.VisitContent,
									  AreaCode = visit.Order.AreaCode!,
									  SubjectResultSatifyCode = visitDe.OrgProcessingResults?.Key,
									  FirstSatisfactionCode = visit.Order.FirstVisitResultCode!,
									  ClientGuid = ""
								  });

							//推门户
							await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisitedWeb, new PublishVisitAllDto()
							{
								Id = visit.Id,
								Order = _mapper.Map<OrderDto>(visit.Order),
								OrderVisitDetails = _mapper.Map<List<VisitDetailDto>>(visit.OrderVisitDetails),
								VisitName = visit.CreatorName,
								VisitTime = visit.VisitTime,
								VisitType = visit.VisitType,
								VisitState = visit.VisitState,
								PublishTime = visit.PublishTime,
							}, cancellationToken: cancellationToken);
						}
					}
				}
				else
				{
					await _orderRepository.OrderScreenRevisionVisit(screen.VisitId, true, cancellationToken);
					screen.Status = EScreenStatus.Refuse;
					screen.ReplyContent = workflow.ActualOpinion;
				}
				screen.NewestAuditTime = DateTime.Now;
				await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
				OrderScreenDetail detail = new OrderScreenDetail
				{
					ScreenId = screen.Id
				};
				detail.Audit(_sessionContext.UserId, _sessionContext.UserName, _sessionContext.OrgId, _sessionContext.OrgName, 1);
				await _orderScreenDetailRepository.AddAsync(detail, cancellationToken);
			}
		}
	}
}