using Hotline.Application.FlowEngine;
using Hotline.Caching.Interfaces;
using Hotline.Configurations;
using Hotline.FlowEngine.WorkflowModules;
using Hotline.FlowEngine.Workflows;
using Hotline.Orders;
using Hotline.Push.Notifies;
using Hotline.SeedData;
using Hotline.Settings;
using Hotline.Share.Dtos.FlowEngine;
using Hotline.Share.Dtos.FlowEngine.Workflow;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Enums.FlowEngine;
using Hotline.Share.Enums.Order;
using Hotline.Share.Enums.Push;
using Hotline.Users;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using XF.Domain.Authentications;
using XF.Domain.Exceptions;
using XF.Domain.Repository;

namespace Hotline.Api.Controllers
{
    public class OrderRevocationController : BaseController
    {
        private readonly IMapper _mapper;
        private readonly IRepository<OrderRevocation> _orderRevocationRepository;
        private readonly IRepository<Order> _orderRepository;
        private readonly ISessionContext _sessionContext;
        private readonly IWorkflowApplication _workflowApplication;
        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
        private readonly IRepository<SystemOrganize> _systemOrganizeRepository;
        private readonly IRepository<User> _userRepository;
        private readonly IMediator _mediator;
        private readonly IWorkflowDomainService _workflowDomainService;
        private readonly IOptionsSnapshot<AppConfiguration> _appOptions;


        public OrderRevocationController(IMapper mapper,
            IRepository<OrderRevocation> orderRevocationRepository,
            IRepository<Order> orderRepository,
            ISessionContext sessionContext,
            IWorkflowApplication workflowApplication,
            ISystemSettingCacheManager systemSettingCacheManager,
            IRepository<SystemOrganize> systemOrganizeRepository,
            IRepository<User> userRepository,
            IMediator mediator,
            IWorkflowDomainService workflowDomainService,
            IOptionsSnapshot<AppConfiguration> appOptions)
        {
            _mapper = mapper;
            _orderRevocationRepository = orderRevocationRepository;
            _orderRepository = orderRepository;
            _sessionContext = sessionContext;
            _workflowApplication = workflowApplication;
            _systemSettingCacheManager = systemSettingCacheManager;
            _systemOrganizeRepository = systemOrganizeRepository;
            _userRepository = userRepository;
            _mediator = mediator;
            _workflowDomainService = workflowDomainService;
            _appOptions = appOptions;
        }

        /// <summary>
        /// 撤销件处理
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("add_order_revocation")]
        public async Task<OrderRevocationResponseDto> AddOrderRevocation([FromBody] OrderRevocationDto dto)
        {
            if (!dto.Ids.Any())
                throw UserFriendlyException.SameMessage("请选择需要撤销的记录！");

            if (string.IsNullOrEmpty(dto.RevocationReason))
                throw UserFriendlyException.SameMessage("撤销说明不能为空！");
            int successNum = 0;
            int errorNum = 0;
            var orders = await _orderRepository.Queryable().Where(p => dto.Ids.Contains(p.Id)).ToListAsync();
            if (orders != null && orders.Any())
            {
                foreach (var order in orders)
                {
                    if (order != null)
                    {
                        //工单状态为会签中、退回审批中、特提审批中、已归档，则不能撤销
                        if (order.Status == EOrderStatus.Countersigning
                            || order.Status == EOrderStatus.SendBackAudit
                            || order.Status == EOrderStatus.SpecialAudit
                            || order.Status >= EOrderStatus.Filed)
                        {
                            errorNum++;
                        }
                        else
                        {
                            //添加撤销件
                            OrderRevocation orderRevocation = new()
                            {
                                OrderId = order.Id,
                                No = order.No,
                                RevocationReason = dto.RevocationReason,
                                IsSendSms = dto.IsSendSms,
                            };
                            var id = await _orderRevocationRepository.AddAsync(orderRevocation, HttpContext.RequestAborted);
                            if (!string.IsNullOrEmpty(id))
                            {
                                #region 处理短信业务

                                //如果需要发短信、处理短信业务
                                if (dto.IsSendSms && !string.IsNullOrEmpty(order.WorkflowId))
                                {
                                    //查询当前工单的实际办理节点，如果在热线中心不处理，如果在部门需要更新期满时间
                                    var workflow = await _workflowDomainService.GetWorkflowAsync(order.WorkflowId, withSteps: true, withTraces: true,
                                        cancellationToken: HttpContext.RequestAborted);
                                    var nowWorkflow = workflow.Steps.Where(p =>
                                        p.Id == order.ActualHandleStepId && p.BusinessType >= EBusinessType.Department &&
                                        p.BusinessType <= EBusinessType.DepartmentLeader).FirstOrDefault();
                                    //在部门才需要发送短信
                                    if (nowWorkflow != null && order.CenterToOrgTime.HasValue)
                                    {
                                        //处理短信业务
                                        var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
                                        //查询部门所有账号
                                        var userlist = await _userRepository.Queryable().Where(x =>
                                            x.OrgId == order.CurrentHandleOrgId && !string.IsNullOrEmpty(x.PhoneNo) &&
                                            x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id))).ToListAsync();
                                        //发送短信
                                        foreach (var user in userlist)
                                        {
                                            var messageDto = new Share.Dtos.Push.MessageDto
                                            {
                                                PushBusiness = EPushBusiness.OrderRevocationSms,
                                                PushPlatform = EPushPlatform.Sms,
                                                Name = user.Name,
                                                TemplateCode = "1016",
                                                Params = new List<string>() { order.No },
                                                TelNumber = user.PhoneNo,
                                            };
                                            await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted);
                                        }
                                    }
                                }

                                #endregion

                                #region 处理流程业务

                                //处理流程业务
                                //如果开启了流程直接归档，如果没开启流程，开启流程到归档
                                if (string.IsNullOrEmpty(order.WorkflowId))
                                {
                                    var startDto = new StartWorkflowDto
                                    {
                                        DefinitionModuleCode = WorkflowModuleConsts.OrderHandle,
                                        Title = order.Title,
                                        Opinion = dto.RevocationReason,
                                    };
                                    // await _workflowApplication.StartToEndAsync(startDto, order.Id, order.ExpiredTime, HttpContext.RequestAborted);
                                    await _workflowDomainService.StartToEndAsync(startDto, order.Id, order.ExpiredTime, HttpContext.RequestAborted);
                                }
                                else
                                {
                                    if (_appOptions.Value.IsLuZhou)
                                    {
                                        await _workflowDomainService.RecallToStartStepAsync(order.WorkflowId, dto.RevocationReason, order.ExpiredTime, order.Status >= EOrderStatus.Filed, EHandleMode.Revocation, cancellationToken: HttpContext.RequestAborted);
                                    }
                                    await _workflowDomainService.JumpToEndAsync(_sessionContext, order.WorkflowId, dto.RevocationReason, null, order.ExpiredTime, cancellationToken: HttpContext.RequestAborted);
                                }

                                #endregion

                                #region 处理工单的一级部门和实际办理部门

                                //处理工单的一级部门和实际办理部门
                                var org = await _systemOrganizeRepository.GetAsync(p => p.Id == OrgSeedData.CenterId, HttpContext.RequestAborted);
                                order.ActualHandleOrgAreaCode = org?.AreaCode;
                                order.ActualHandleOrgAreaName = org?.AreaName;
                                order.ActualHandleOrgCode = OrgSeedData.CenterId;
                                order.ActualHandleOrgName = OrgSeedData.CenterName;
                                order.OrgLevelOneCode = OrgSeedData.CenterId;
                                order.OrgLevelOneName = OrgSeedData.CenterName;
                                order.ActualHandlerName = _sessionContext.UserName;
                                order.ActualHandleTime = DateTime.Now;
                                order.ActualHandlerId = _sessionContext.UserId;

                                await _orderRepository.Updateable(order).UpdateColumns(it => new
                                {
                                    it.ActualHandleOrgName,
                                    it.ActualHandleOrgCode,
                                    it.OrgLevelOneCode,
                                    it.OrgLevelOneName,
                                    it.ActualHandleOrgAreaCode,
                                    it.ActualHandleOrgAreaName,
                                    it.ActualHandlerName,
                                    it.ActualHandleTime,
                                    it.ActualHandlerId
                                }).ExecuteCommandAsync();

                                #endregion

                                successNum++;
                            }
                            else
                                errorNum++;
                        }
                    }
                    else
                    {
                        errorNum++;
                    }
                }
            }
            OrderRevocationResponseDto responseDto = new OrderRevocationResponseDto()
            {
                ErrorNum = errorNum,
                SuccessNum = successNum,
            };
            return responseDto;
        }
    }
}