using Hotline.Caching.Interfaces;
using Hotline.Configurations;
using Hotline.File;
using Hotline.FlowEngine.Notifications;
using Hotline.FlowEngine.Workflows;
using Hotline.Orders;
using Hotline.Share.Attributes;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.File;
using Hotline.Share.Dtos.FlowEngine;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Dtos.Snapshot;
using Hotline.Share.Enums.FlowEngine;
using Hotline.Share.Enums.Order;
using Hotline.Share.Enums.Snapshot;
using Hotline.Share.Tools;
using Hotline.Snapshot;
using Hotline.Tools;
using Mapster;
using Microsoft.Extensions.Options;
using Novacode.NETCorePort;
using NPOI.POIFS.Properties;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Hotline.Share.Dtos.FlowEngine.Workflow;
using XF.Domain.Authentications;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using XF.Utility.EnumExtensions;
using Hotline.Snapshot.IRepository;
using Hotline.Application.Snapshot.Contracts;
using Microsoft.AspNetCore.Http;
using Hotline.Configurations;
using Microsoft.Extensions.Options;
using Hotline.FlowEngine.WorkflowModules;
using System.Reflection.Metadata.Ecma335;
using Microsoft.Extensions.Logging;

namespace Hotline.Application.Snapshot;
public class SnapshotOrderApplication : IOrderSnapshotApplication, IScopeDependency
{
    private readonly IOrderSnapshotRepository _orderSnapshotRepository;
    private readonly IOrderRepository _orderRepository;
    private readonly ISnapshotOrderPublishRepository _snapshotOrderPublishRepository;
    private readonly ISessionContext _sessionContext;
    private readonly ISystemSettingCacheManager _systemSettingCacheManager;
    private readonly IIndustryCaseRepository _industryCaseRepository;
    private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
    private readonly IIndustryRepository _industryRepository;
    private readonly IFileRepository _fileRepository;
    private readonly ISnapshotLabelLogRepository _snapshotLabelLogRepository;
    private readonly IRedPackAuditRepository _redPackAuditRepository;
    private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
    private readonly ILogger<SnapshotOrderApplication> _logger;

    public SnapshotOrderApplication(IOrderSnapshotRepository orderSnapshotRepository, IOrderRepository orderRepository, ISnapshotOrderPublishRepository snapshotOrderPublishRepository, ISessionContext sessionContext, ISystemSettingCacheManager systemSettingCacheManager, IIndustryCaseRepository industryCaseRepository, ISystemDicDataCacheManager systemDicDataCacheManager, IIndustryRepository industryRepository, IFileRepository fileRepository, ISnapshotLabelLogRepository snapshotLabelLogRepository, IRedPackAuditRepository redPackAuditRepository, IOptionsSnapshot<AppConfiguration> appOptions, ILogger<SnapshotOrderApplication> logger)
    {
        _orderSnapshotRepository = orderSnapshotRepository;
        _orderRepository = orderRepository;
        _snapshotOrderPublishRepository = snapshotOrderPublishRepository;
        _sessionContext = sessionContext;
        _systemSettingCacheManager = systemSettingCacheManager;
        _industryCaseRepository = industryCaseRepository;
        _systemDicDataCacheManager = systemDicDataCacheManager;
        _industryRepository = industryRepository;
        _fileRepository = fileRepository;
        _snapshotLabelLogRepository = snapshotLabelLogRepository;
        _redPackAuditRepository = redPackAuditRepository;
        _appOptions = appOptions;
        _logger = logger;
    }

    /// <summary>
    /// 添加公开工单
    /// </summary>
    /// <param name="addSnapshotOrderPublishInDto"></param>
    /// <param name="none"></param>
    /// <returns></returns>
    public async Task<string> AddOrderPublishAsync(AddSnapshotOrderPublishInDto dto, CancellationToken cancellation)
    {
        dto.ValidateObject();
        var oldPublish = await _snapshotOrderPublishRepository.Queryable().Where(m => m.OrderId == dto.OrderId).FirstAsync(cancellation);
        if (oldPublish != null)
            await _snapshotOrderPublishRepository.RemoveAsync(oldPublish, cancellationToken: cancellation);
        var snapshotOrder = await _orderSnapshotRepository.GetAsync(dto.OrderId)
            ?? throw UserFriendlyException.SameMessage("工单不存在");
        var order = await _orderRepository.Queryable()
            .Where(m => m.Id == dto.OrderId)
            .Select(m => new { m.Id, m.No })
            .FirstAsync(cancellation)
            ?? throw UserFriendlyException.SameMessage("工单不存在");
        var entity = dto.Adapt<SnapshotOrderPublish>();
        entity.Id = order.Id;
        entity.IndustryId = snapshotOrder.IndustryId;
        entity.IndustryName = snapshotOrder.IndustryName;
        entity.No = order.No;
        entity.Status = EOrderSnapshotPublishStatus.Pending;
        return await _snapshotOrderPublishRepository.AddAsync(entity, cancellation);
    }

    /// <summary>
    /// 获取网格员回复集合
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    public ISugarQueryable<GuiderReplyItemsOutDto> GetGuiderReplyItems(GuiderReplyItemsInDto dto)
    {
        var query = _orderSnapshotRepository.Queryable()
            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
            .Where((snapshot, order) => snapshot.ReplyResultType != null)
            .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order) => order.No.Contains(dto.No))
            .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.Title))
            .WhereIF(dto.GuiderName.NotNullOrEmpty(), (snapshot, order) => snapshot.MemberName.Contains(dto.GuiderName))
            .WhereIF(dto.GuiderPhoneNumber.NotNullOrEmpty(), (snapshot, order) => snapshot.MemberMobile.Contains(dto.GuiderPhoneNumber))
            .WhereIF(dto.NewtorkENumber.NotNullOrEmpty(), (snapshot, order) => snapshot.NetworkENumber.Contains(dto.NewtorkENumber))
            .WhereIF(dto.Satus.HasValue, (snapshot, order) => snapshot.ReplyResultType == dto.Satus)
            .WhereIF(dto.BeginCreationTime.HasValue && dto.EndCreationTime.HasValue, (snapshot, order) => order.CreationTime >= dto.BeginCreationTime && order.CreationTime <= dto.EndCreationTime)
            .Select((snapshot, order) => new GuiderReplyItemsOutDto
            {
                No = order.No,
                Title = order.Title
            }, true);

        return query;
    }

    /// <summary>
    /// 随手拍公开审批集合
    /// </summary>
    /// <returns></returns>
    public ISugarQueryable<GetOrderSnapshotPublishAuditItemsOutDto> GetOrderSnapshotPublishAuditItems(GetOrderSnapshotPublishAuditItemsInDto dto)
    {
        var query = _snapshotOrderPublishRepository.Queryable()
            .LeftJoin<Order>((publish, order) => publish.OrderId == order.Id)
            .WhereIF(dto.Status == 0, publish => publish.Status == EOrderSnapshotPublishStatus.Pending)
            .WhereIF(dto.Status == 1, publish => publish.Status == EOrderSnapshotPublishStatus.Agree)
            .WhereIF(dto.Status == 2, publish => publish.Status == EOrderSnapshotPublishStatus.Refuse)
            .OrderByDescending((publish, order) => new { publish.Status, publish.CreationTime })
            .Select((publish, order) => new GetOrderSnapshotPublishAuditItemsOutDto
            {
                Id = publish.Id,
                No = order.No,
                Title = order.Title
            }, true);

        return query;
    }

    /// <summary>
    /// 随手拍公开审批详情
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<GetOrderSnapshotPublishAuditDetailOutDto> GetOrderSnapshotPublishAuditDetailAsync(string id)
    {
        var publish = await _snapshotOrderPublishRepository.GetAsync(id);

        var order = await _orderRepository.Queryable()
            .Where(m => m.Id == publish.OrderId)
            .Select<GetOrderSnapshotPublishAuditDetailOutDto>()
            .FirstAsync();

        publish.Adapt(order);
        order.Id = publish.Id;
        return order;
    }

    /// <summary>
    /// 随手拍公开详情
    /// </summary>
    /// <param name="id">工单Id</param>
    /// <returns></returns>
    public async Task<GetOrderSnapshotPublishDetailOutDto> GetOrderSnapshotPublishDetailAsync(string id)
    {
        return await _orderRepository.Queryable()
            .Where(m => m.Id == id)
            .Select<GetOrderSnapshotPublishDetailOutDto>()
            .FirstAsync();
    }

    /// <summary>
    /// 随手拍公开集合
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [ExportExcel("随手拍公开")]
    public ISugarQueryable<GetOrderSnapshotPublishItemsOutDto> GetOrderSnapshotPublishItems(GetOrderSnapshotPublishItemsInDto dto)
    {
        var query = _orderSnapshotRepository.Queryable(includeDeleted: true)
            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
            .LeftJoin<SnapshotOrderPublish>((snapshot, order, publish) => order.Id == publish.OrderId)
            .WhereIF(dto.IndustryId.NotNullOrEmpty(), snapshot => snapshot.IndustryId == dto.IndustryId)
            .WhereIF(dto.AreaCode.NotNullOrEmpty(), (snapshot, order) => order.AreaCode == dto.AreaCode)
            .WhereIF(dto.AcceptTypeCode.NotNullOrEmpty(), (snapshot, order) => order.AcceptTypeCode == dto.AcceptTypeCode)
            .WhereIF(dto.BeginCreationTime.HasValue && dto.EndCreationTime.HasValue, (snapshot, order) => order.CreationTime >= dto.BeginCreationTime && order.CreationTime <= dto.EndCreationTime)
            .WhereIF(dto.Contact.NotNullOrEmpty(), (snapshot, order) => order.Contact.Contains(dto.Contact))
            .WhereIF(dto.FromPhone.NotNullOrEmpty(), (snapshot, order) => order.FromPhone.Contains(dto.FromPhone))
            .WhereIF(dto.IsPublished.HasValue, (snapshot, order, publish) => publish.Status == EOrderSnapshotPublishStatus.Agree)
            .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order) => order.No.Contains(dto.No))
            .WhereIF(dto.OrderStatus.HasValue, (snapshot, order) => order.Status == dto.OrderStatus)
            .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.Title))
            .Where((snapshot, order, publish) => order.Status >= EOrderStatus.Filed)
            .OrderByDescending((snapshot, order, publish) => new { publish.Status, snapshot.CreationTime })
            .Select((snapshot, order, publish) =>
            new GetOrderSnapshotPublishItemsOutDto
            {
                PublishStatus = publish.Status
            }, true);

        return query;
    }

    /// <summary>
    /// 获取工单标记集合
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [ExportExcel("工单标注")]
    public ISugarQueryable<SignOrderSnapshotItemsOutDto> GetSignOrderSnapshotItems(SignOrderSnapshotItemsInDto dto)
    {
        var query = _orderSnapshotRepository.Queryable()
            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
            .LeftJoin<WorkflowStep>((snapshot, order, step) => step.ExternalId == order.Id && step.Tag == TagDefaults.OrderMark && step.Status != EWorkflowStepStatus.Handled)
            .Where((snapshot, order, step) => snapshot.IndustryName == "安全隐患")
            .WhereIF(dto.Status == 1, (snapshot, order, step) => step.Id != null && (step.HandlerId == _sessionContext.UserId || _sessionContext.Roles.Contains(step.RoleId)) && snapshot.IsSafetyDepartment == null) // 待标记
            .WhereIF(dto.Status == 2, (snapshot, order, step) => snapshot.IsSafetyDepartment != null && snapshot.SignUserId == _sessionContext.UserId) // 已标记
            .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order, step) => order.No.Contains(dto.No))
            .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order, step) => order.Title.Contains(dto.Title))
            .OrderByDescending((snapshot, order, step) => snapshot.CreationTime)
            .Select((snapshot, order) => new SignOrderSnapshotItemsOutDto
            {
                OrderId = snapshot.Id,
                No = order.No,
                Title = order.Title,
                Content = order.Content,
                FullAddress = order.FullAddress,
                CreationTime = order.CreationTime,
                County = order.County,
                IsSafetyDepartment = snapshot.IsSafetyDepartment,
                NetworkENumber = snapshot.NetworkENumber,
                NetworkRemark = snapshot.NetworkRemark,
                ReplyDate = snapshot.ReplyDate,
                LabelTime = snapshot.SignTime,
                LabelUserName = snapshot.SignUserName
            });
#if DEBUG
        var sql = query.ToSqlString();
#endif
        return query;
    }

    /// <summary>
    /// 批量设置随手拍公开申请不通过
    /// </summary>
    /// <returns></returns>
    public async Task UpdateOrderSnapshotPublishsStatusRefuseAsync(IList<string> ids)
    {
        await _snapshotOrderPublishRepository.Updateable()
            .SetColumns(m => m.Status, EOrderSnapshotPublishStatus.Refuse)
            .SetColumns(m => m.RefuseRemark, _sessionContext.UserName + "批量设置不公开")
            .SetColumns(m => m.RefuseAuditTime, DateTime.Now)
            .Where(m => ids.Contains(m.Id))
            .ExecuteCommandAsync();
    }

    /// <summary>
    /// 审核随手拍公开申请通过/不通过
    /// </summary>
    /// <returns></returns>
    public async Task UpdateOrderSnapshotPublishStatusAsync(UpdateOrderSnapshotPublishStatusInDto dto)
    {
        var audit = await _snapshotOrderPublishRepository.GetAsync(dto.Id)
            ?? throw UserFriendlyException.SameMessage("审核记录不存在");
        audit.Status = dto.Status;
        audit.AuditTime = DateTime.Now;
        await _snapshotOrderPublishRepository.UpdateAsync(audit);
    }

    /// <summary>
    /// 随手拍工单标记
    /// </summary>
    /// <param name="id"></param>
    /// <param name="snapshotLabels"></param>
    /// <returns></returns>
    public async Task UpdateLabelAsync(string id, IList<Kv>? labels)
    {
        if (_systemSettingCacheManager.Snapshot == false) return;

        var snapshot = await _orderSnapshotRepository.GetAsync(m => m.Id == id);
        if (snapshot == null) return;
        if (snapshot != null && labels.IsNullOrEmpty())
        {
            throw UserFriendlyException.SameMessage("随手拍工单标记不能为空");
        }
        snapshot!.Labels = labels;
        snapshot.LabelName = string.Join('|', labels!.Select(m => m.Value));
        //if (labels.Any(m => m.Key == "yzg"))
        //    snapshot.IsRectifyDepartment = true;
        //if (labels.Any(m => m.Key == "wzg"))
        //    snapshot.IsRectifyDepartment = false;
        if (labels!.Any(m => m.Key == "ss"))
            snapshot.IsTruthDepartment = true;
        if (labels!.Any(m => m.Key == "bss"))
            snapshot.IsTruthDepartment = false;
        snapshot.LabelTime = DateTime.Now;
        snapshot.LabelUserName = _sessionContext.UserName;
        snapshot.LabelUserId = _sessionContext.UserId;
        await _orderSnapshotRepository.UpdateAsync(snapshot);

        var entity = new SnapshotLabelLog
        {
            OrderId = snapshot.Id,
            LabelName = snapshot.LabelName,
            Labels = labels
        };
        await _snapshotLabelLogRepository.AddAsync(entity);
    }

    public async Task SaveOrderWorkflowInfo(NextWorkflowDto<OrderHandleFlowDto> dto)
    {
        if (_systemSettingCacheManager.Snapshot == false) return;

        var snapshot = await _orderSnapshotRepository.GetAsync(dto.Data.OrderId);
        if (snapshot is null) return;

        // 标记节点标记随手拍安全生产
        if (TagDefaults.OrderMark.ToLower() == dto.Workflow.CurrentTag?.ToLower())
        {
            snapshot.IsSafetyDepartment = dto.Data.IsSafetyDepartment;
            snapshot.SignUserId = _sessionContext.UserId;
            snapshot.SignUserName = _sessionContext.UserName;
            snapshot.SignTime = DateTime.Now;
            snapshot.SignRemark = dto.Workflow.Remark;
            await _orderSnapshotRepository.UpdateAsync(snapshot);
            return;
        }

        // 安全隐患 归档节点保存随手拍数据
        if (dto.Data.IsDangerDepartment.HasValue && dto.Data.IsRectifyDepartment.HasValue)
        {
            snapshot.IsDangerDepartment = dto.Data.IsDangerDepartment.Value;
            snapshot.IsRectifyDepartment = dto.Data.IsRectifyDepartment.Value;
            snapshot.IndustryCase = dto.Data.IndustryCase;
            snapshot.IsAward = dto.Data.IsAward;
            snapshot.AwardOpenBank = dto.Data.AwardOpenBank;
            snapshot.AwardName = dto.Data.AwardName;
            snapshot.AwardBankCardNo = dto.Data.AwardBankCardNo;
            snapshot.ReplenishTypeId = dto.Data.ReplenishTypeId;
            if (snapshot.ReplenishTypeId.NotNullOrEmpty())
            {
                snapshot.ReplenishTypeName = _systemDicDataCacheManager
                    .SnapshotReplenishType
                    .First(m => m.DicDataValue == snapshot.ReplenishTypeId).DicDataName;
            }
            snapshot.AwardAmount = dto.Data.AwardAmount;
            await _orderSnapshotRepository.UpdateAsync(snapshot);
            return;
        }

        // 电气焊工单办理
        if (dto.Data.VerifyType.NotNullOrEmpty() || dto.Data.IsCheckList.HasValue || dto.Data.CompliantType.HasValue)
        {
            snapshot.VerifyType = dto.Data.VerifyType;
            snapshot.IsCheckList = dto.Data.IsCheckList;
            snapshot.CompliantType = dto.Data.CompliantType;
            if (dto.Data.VerifyType != null)
                dto.Workflow.Opinion += $" 核实方式: {dto.Data.VerifyType}";
            if (dto.Data.IsCheckList.HasValue)
                dto.Workflow.Opinion += $" 是否按清单检查: {(dto.Data.IsCheckList.Value ? "是" : "否")}";
            await _orderSnapshotRepository.UpdateAsync(snapshot);
            return;
        }
    }

    /// <summary>
    /// 获取工单标注日志集合
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [ExportExcel("工单标注日志")]
    public ISugarQueryable<LabelOrderSnapshotLogItemsOutDto> GetLabelOrderSnapshotLogItems(LabelOrderSnapshotLogItemsInDto dto)
    {
        var query = _snapshotLabelLogRepository.Queryable()
            .LeftJoin<Order>((log, order) => log.OrderId == order.Id)
            .LeftJoin<OrderSnapshot>((log, order, snapshot) => log.OrderId == snapshot.Id)
            .WhereIF(dto.No.NotNullOrEmpty(), (log, order) => order.No.Contains(dto.No))
            .WhereIF(dto.Title.NotNullOrEmpty(), (log, order) => order.Title.Contains(dto.Title))
            .WhereIF(dto.Contact.NotNullOrEmpty(), (log, order) => order.Contact.Contains(dto.Contact))
            .WhereIF(dto.FromName.NotNullOrEmpty(), (log, order) => order.FromName.Contains(dto.FromName))
            .WhereIF(dto.Label.NotNullOrEmpty(), (log, order) => log.LabelName.Contains(dto.Label))
            .WhereIF(dto.LabelUserName.NotNullOrEmpty(), (log, order) => log.CreatorName.Contains(dto.LabelUserName))
            .WhereIF(dto.BeginSignTime.HasValue && dto.EndSignTime.HasValue, (log, order) => log.CreationTime >= dto.BeginSignTime && log.CreationTime <= dto.EndSignTime)
            .OrderByDescending((log, order, snapshot) => log.CreationTime)
            .Select((log, order, snapshot) => new LabelOrderSnapshotLogItemsOutDto
            {
                OrderId = order.Id,
                LabelUserName = log.CreatorName,
                LabelTime = log.CreationTime,
                IndustryName = snapshot.IndustryName
            }, true);
        return query;
    }

    /// <summary>
    /// 返回办理页面基础数据
    /// </summary>
    /// <param name="rsp">isAqyh：是否属于安全隐患,IsDangerDepartment：是否已经输入过安全隐患相关字段)</param>
    /// <param name="orderId"></param>
    /// <returns></returns>
    public async Task<bool> GetNextStepsDatabaseAsync(NextStepsWithOpinionDto<RecommendStepOption> rsp, string orderId)
    {
        if (_systemSettingCacheManager.Snapshot == false) return default;

        var isAqyh = false;
        await _orderSnapshotRepository.Queryable()
            .Where(m => m.Id == orderId)
            .Select(m => new { m.Id, m.IndustryId, m.IsSafetyDepartment, m.IndustryName, m.IsDangerDepartment })
            .FirstAsync()
            .Then(async snapshot =>
            {
                if (snapshot.IsSafetyDepartment.HasValue && snapshot.IsSafetyDepartment == true)
                {
                    rsp.IsSafetyDepartment = true;
                }

                await _industryRepository.Queryable()
                    .Where(m => m.Id == snapshot.IndustryId)
                    .Select(m => new { m.Id, m.IndustryType })
                    .FirstAsync()
                    .Then(async industry =>
                    {
                        await _fileRepository.Queryable()
                        .Where(m => m.Key == industry.Id)
                        .Select(m => new FileJson { Id = m.Additions, FileName = m.Name, Path = m.Path, FileType = m.Type })
                        .ToListAsync()
                        .Then(async file =>
                        {
                            rsp.DocumentFiles = file;
                        });
                    });

                isAqyh = snapshot != null && string.CompareOrdinal(snapshot.IndustryName, "安全隐患") == 0;
                rsp.IsDangerDepartment = snapshot.IsDangerDepartment;
            }
            );


        rsp.IndustryCase = await _industryCaseRepository.Queryable()
            .Where(m => m.IsEnable == true)
            .Select(m => new Kv { Key = m.Id, Value = m.Name })
            .ToListAsync();

        rsp.SnapshotReplenishType = _systemDicDataCacheManager.SnapshotReplenishType;
        rsp.CompliantType = EnumExts.GetDescriptions<ECompliantType>();

        return isAqyh;
    }

    [ExportExcel("随手拍工单")]
    public ISugarQueryable<OrderSnapshotItemsOutDto> GetOrderSnapshotItems(OrderSnapshotItemsInDto dto)
    {
        var query = _orderSnapshotRepository.Queryable()
            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
            .LeftJoin<Industry>((snapshot, order, industry) => snapshot.IndustryId == industry.Id)
            .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order) => order.No.Contains(dto.No))
            .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.Title))
            .WhereIF(dto.ActualHandleOrgName.NotNullOrEmpty(), (snapshot, order) => order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
            .WhereIF(dto.AcceptType.NotNullOrEmpty(), (snapshot, order) => order.AcceptType == dto.AcceptType)
            .WhereIF(dto.AcceptorName.NotNullOrEmpty(), (snapshot, order) => order.AcceptorName == dto.AcceptorName)
            .WhereIF(dto.FromPhone.NotNullOrEmpty(), (snapshot, order) => order.FromPhone == dto.FromPhone)
            .WhereIF(dto.FromName.NotNullOrEmpty(), (snapshot, order) => order.FromName == dto.FromName)
            .WhereIF(dto.BeginExpiredTime.HasValue && dto.EndExpiredTime.HasValue, (snapshot, order) => order.ExpiredTime >= dto.BeginExpiredTime && order.ExpiredTime <= dto.EndExpiredTime)
            .WhereIF(dto.BeginCreationTime.HasValue && dto.EndCreationTime.HasValue, (snapshot, order) => order.CreationTime >= dto.BeginCreationTime && order.CreationTime <= dto.EndCreationTime)
            .WhereIF(dto.Status.HasValue, (snapshot, order) => order.Status == dto.Status)
            .WhereIF(dto.County.NotNullOrEmpty(), (snapshot, order) => order.County == dto.County)
            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == true, (snapshot, order) => order.OrderScreens.Count() > 0)
            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == false, (snapshot, order) => order.OrderScreens.Count() == 0)
            .WhereIF(dto.CurrentStepName.NotNullOrEmpty(), (snapshot, order) => order.CurrentStepName == dto.CurrentStepName)
            .WhereIF(dto.BeginFiledTime.HasValue && dto.EndFiledTime.HasValue, (snapshot, order) => order.FiledTime >= dto.BeginFiledTime && order.FiledTime <= dto.EndFiledTime)
            .WhereIF(dto.HotspotName.NotNullOrEmpty(), (snapshot, order) => order.HotspotName.Contains(dto.HotspotName))
            .WhereIF(dto.OrderTagCode.NotNullOrEmpty(), (snapshot, order) => order.OrderTagCode.Contains(dto.OrderTagCode))
            .WhereIF(dto.IsUrgent.HasValue, (snapshot, order) => order.IsUrgent == dto.IsUrgent)
            .WhereIF(dto.TransferPhone.NotNullOrEmpty(), (snapshot, order) => order.TransferPhone.Contains(dto.TransferPhone))
            .WhereIF(dto.OrgLevelOneCode.NotNullOrEmpty(), (snapshot, order) => order.OrgLevelOneCode == dto.OrgLevelOneCode)
            //.WhereIF(dto.DiscontentTurnTo.HasValue, (snapshot, order) => order == dto.OrgLevelOneCode)
            .WhereIF(dto.IndustryId.NotNullOrEmpty(), (snapshot, order) => snapshot.IndustryId == dto.IndustryId)
            .Select((snapshot, order, industry) => new OrderSnapshotItemsOutDto
            {
                CreationTime = order.CreationTime
            }
             , true);
        return query;
    }

    [ExportExcel("电气焊作业申报工单")]
    public ISugarQueryable<OrderSnapshotElectrogasItemsOutDto> GetOrderSnapshotElectrogasItems(OrderSnapshotItemsInDto dto)
    {
        var query = _orderSnapshotRepository.Queryable()
            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
            .LeftJoin<Industry>((snapshot, order, industry) => snapshot.IndustryId == industry.Id)
            .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order) => order.No.Contains(dto.No))
            .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.Title))
            .WhereIF(dto.ActualHandleOrgName.NotNullOrEmpty(), (snapshot, order) => order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
            .WhereIF(dto.AcceptType.NotNullOrEmpty(), (snapshot, order) => order.AcceptType == dto.AcceptType)
            .WhereIF(dto.AcceptorName.NotNullOrEmpty(), (snapshot, order) => order.AcceptorName == dto.AcceptorName)
            .WhereIF(dto.FromPhone.NotNullOrEmpty(), (snapshot, order) => order.FromPhone == dto.FromPhone)
            .WhereIF(dto.FromName.NotNullOrEmpty(), (snapshot, order) => order.FromName == dto.FromName)
            .WhereIF(dto.BeginExpiredTime.HasValue && dto.EndExpiredTime.HasValue, (snapshot, order) => order.ExpiredTime >= dto.BeginExpiredTime && order.ExpiredTime <= dto.EndExpiredTime)
            .WhereIF(dto.BeginCreationTime.HasValue && dto.EndCreationTime.HasValue, (snapshot, order) => order.CreationTime >= dto.BeginCreationTime && order.CreationTime <= dto.EndCreationTime)
            .WhereIF(dto.Status.HasValue, (snapshot, order) => order.Status == dto.Status)
            .WhereIF(dto.County.NotNullOrEmpty(), (snapshot, order) => order.County == dto.County)
            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == true, (snapshot, order) => order.OrderScreens.Count() > 0)
            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == false, (snapshot, order) => order.OrderScreens.Count() == 0)
            .WhereIF(dto.CurrentStepName.NotNullOrEmpty(), (snapshot, order) => order.CurrentStepName == dto.CurrentStepName)
            .WhereIF(dto.BeginFiledTime.HasValue && dto.EndFiledTime.HasValue, (snapshot, order) => order.FiledTime >= dto.BeginFiledTime && order.FiledTime <= dto.EndFiledTime)
            .WhereIF(dto.HotspotName.NotNullOrEmpty(), (snapshot, order) => order.HotspotName.Contains(dto.HotspotName))
            .WhereIF(dto.OrderTagCode.NotNullOrEmpty(), (snapshot, order) => order.OrderTagCode.Contains(dto.OrderTagCode))
            .WhereIF(dto.IsUrgent.HasValue, (snapshot, order) => order.IsUrgent == dto.IsUrgent)
            .WhereIF(dto.TransferPhone.NotNullOrEmpty(), (snapshot, order) => order.TransferPhone.Contains(dto.TransferPhone))
            .WhereIF(dto.OrgLevelOneCode.NotNullOrEmpty(), (snapshot, order) => order.OrgLevelOneCode == dto.OrgLevelOneCode)
            //.WhereIF(dto.DiscontentTurnTo.HasValue, (snapshot, order) => order == dto.OrgLevelOneCode)
            .WhereIF(dto.IndustryId.NotNullOrEmpty(), (snapshot, order) => snapshot.IndustryId == dto.IndustryId)
            .Where((snapshot, order, industry) => industry.IndustryType == EIndustryType.Declare)
            .Select((snapshot, order, industry) => new OrderSnapshotElectrogasItemsOutDto
            {
                CreationTime = order.CreationTime
            }
             , true);
        return query;
    }


    /// <summary>
    /// 获取工单已经标记集合
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [ExportExcel("工单标注")]
    public ISugarQueryable<LabeledOrderSnapshotItemsOutDto> GetLabeledOrderSnapshotItems(LabeledOrderSnapshotItemsInDto dto)
    {
        var query = _orderSnapshotRepository.Queryable()
            .LeftJoin<Order>((snapshot, order) => order.Id == snapshot.Id)
            .Where((snapshot, order) => order.Status >= EOrderStatus.Published)
            .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order) => order.No.Contains(dto.No))
            .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.Title))
            .WhereIF(dto.FromName.NotNullOrEmpty(), (snapshot, order) => order.FromName.Contains(dto.FromName))
            .WhereIF(dto.FromPhone.NotNullOrEmpty(), (snapshot, order) => order.FromPhone.Contains(dto.FromPhone))
            .WhereIF(dto.Label.NotNullOrEmpty(), (snapshot, order) => snapshot.LabelName.Contains(dto.Label))
            .WhereIF(dto.BeginSignTime.HasValue && dto.EndSignTime.HasValue, (snapshot, order) => snapshot.SignTime >= dto.BeginSignTime && snapshot.SignTime <= dto.EndSignTime)
            .OrderByDescending((snapshot, order) => snapshot.CreationTime)
            .Select((snapshot, order) => new LabeledOrderSnapshotItemsOutDto
            {
                LabelName = snapshot.LabelName,
                OrderId = order.Id,
                LabelTime = snapshot.LabelTime,
                LabelUserName = snapshot.LabelUserName,
                SourceChannel = order.SourceChannel,
            }, true);

        return query;
    }

    public async Task<OrderSnapshot> UpdateSafetyAsync(string orderId, bool isSafetyDepartment, string remark)
    {
        // 红包已经审核通过的工单不允许修改
        if (await _redPackAuditRepository.Queryable().AnyAsync(m => m.OrderId == orderId && m.Status == ERedPackAuditStatus.Agree))
        {
            return await _orderSnapshotRepository.GetAsync(orderId);
        }
        return await _orderSnapshotRepository.UpdateSafetyAsync(orderId, isSafetyDepartment, remark);
    }

    public ISugarQueryable<CitizenRewardOutDto> GetCitizenRewardItems(CitizenRewardInDto dto)
    {
        var query = _orderSnapshotRepository.Queryable()
            .LeftJoin<Order>((snapshot, order) => snapshot.Id == order.Id)
            .WhereIF(dto.No.NotNullOrEmpty(), (snapshot, order) => order.No.Contains(dto.No))
            .WhereIF(dto.Title.NotNullOrEmpty(), (snapshot, order) => order.Title.Contains(dto.Title))
            .WhereIF(dto.ActualHandleOrgName.NotNullOrEmpty(), (snapshot, order) => order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))
            .WhereIF(dto.AcceptType.NotNullOrEmpty(), (snapshot, order) => order.AcceptType == dto.AcceptType)
            .WhereIF(dto.AcceptorName.NotNullOrEmpty(), (snapshot, order) => order.AcceptorName == dto.AcceptorName)
            .WhereIF(dto.ActualHandlerName.NotNullOrEmpty(), (snapshot, order) => order.ActualHandlerName == dto.ActualHandlerName)
            .WhereIF(dto.FromPhone.NotNullOrEmpty(), (snapshot, order) => order.FromPhone == dto.FromPhone)
            .WhereIF(dto.FromName.NotNullOrEmpty(), (snapshot, order) => order.FromName == dto.FromName)
            .WhereIF(dto.BeginExpiredTime.HasValue && dto.EndExpiredTime.HasValue, (snapshot, order) => order.ExpiredTime >= dto.BeginExpiredTime && order.ExpiredTime <= dto.EndExpiredTime)
            .WhereIF(dto.BeginCreationTime.HasValue && dto.EndCreationTime.HasValue, (snapshot, order) => order.CreationTime >= dto.BeginCreationTime && order.CreationTime <= dto.EndCreationTime)
            .WhereIF(dto.Status.HasValue, (snapshot, order) => order.Status == dto.Status)
            .WhereIF(dto.County.NotNullOrEmpty(), (snapshot, order) => order.County == dto.County)
            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == true, (snapshot, order) => order.OrderScreens.Count() > 0)
            .WhereIF(dto.IsScreen.HasValue && dto.IsScreen == false, (snapshot, order) => order.OrderScreens.Count() == 0)
            .WhereIF(dto.CurrentStepName.NotNullOrEmpty(), (snapshot, order) => order.CurrentStepName == dto.CurrentStepName)
            .WhereIF(dto.BeginFiledTime.HasValue && dto.EndFiledTime.HasValue, (snapshot, order) => order.FiledTime >= dto.BeginFiledTime && order.FiledTime <= dto.EndFiledTime)
            .WhereIF(dto.HotspotName.NotNullOrEmpty(), (snapshot, order) => order.HotspotName.Contains(dto.HotspotName))
            .WhereIF(dto.OrderTagCode.NotNullOrEmpty(), (snapshot, order) => order.OrderTagCode.Contains(dto.OrderTagCode))
            .WhereIF(dto.IsUrgent.HasValue, (snapshot, order) => order.IsUrgent == dto.IsUrgent)
            .WhereIF(dto.TransferPhone.NotNullOrEmpty(), (snapshot, order) => order.TransferPhone.Contains(dto.TransferPhone))
            .WhereIF(dto.OrgLevelOneCode.NotNullOrEmpty(), (snapshot, order) => order.OrgLevelOneCode == dto.OrgLevelOneCode)
            .WhereIF(dto.IndustryId.NotNullOrEmpty(), (snapshot, order) => snapshot.IndustryId == dto.IndustryId)
            .Where((snapshot, order) => snapshot.IsAward == true)
            .Select((snapshot, order) => new CitizenRewardOutDto
            {
                CreationTime = order.CreationTime
            }
             , true);
        return query;

    }

    public async Task UpdateSpecialReasonAsync(string orderId, string errorId, string errorName)
    {
        await _orderSnapshotRepository.Updateable()
            .SetColumns(m => m.SpecialReasonId, errorId)
            .SetColumns(m => m.SpecialReasonName, errorName)
            .Where(m => m.Id == orderId)
            .ExecuteCommandAsync();
    }

    public async Task UpdateIsEmphasisAsync(UpdateIsEmphasisInDto dto)
    {
        await _orderSnapshotRepository.Updateable()
            .SetColumns(m => m.IsEmphasis == true)
            .Where(m => dto.Ids.Contains(m.Id))
            .ExecuteCommandAsync();
    }

    public async Task GetOrderDetailAsync(string id, Share.Dtos.Order.OrderDto dto, CancellationToken token)
    {
        if (_systemSettingCacheManager.Snapshot == false) return;

        await _orderSnapshotRepository.Queryable()
            .Where(snapshot => snapshot.Id == id)
            .Select(snapshot => new
            {
                snapshot.IndustryId,
                snapshot.IndustryName,
                snapshot.IsRectifyDepartment,
                snapshot.IsDangerDepartment,
                snapshot.IsSafetyDepartment,
                snapshot.SignRemark,
                snapshot.SignUserId,
                snapshot.SignUserName,
                snapshot.SignTime,
                snapshot.IndustryCase
            })
            .FirstAsync(token)
            .Then(async snapshot =>
            {
                dto.IndustryName = snapshot.IndustryName;
                if (snapshot.IndustryCase.NotNullOrEmpty())
                    dto.IndustryName = snapshot.IndustryName + " " + (await _industryCaseRepository.Queryable().Where(m => m.Id == snapshot.IndustryCase).FirstAsync())?.Name ?? string.Empty;
                dto.IndustryId = snapshot.IndustryId;
                dto.IsRectifyDepartment = snapshot.IsRectifyDepartment;
                dto.IsDangerDepartment = snapshot.IsDangerDepartment;
                dto.IsSafetyDepartment = snapshot.IsSafetyDepartment;
                dto.SignUserId = snapshot.SignUserId;
                dto.SignUserName = snapshot.SignUserName;
                dto.SignTime = snapshot.SignTime;
                dto.SignRemark = snapshot.SignRemark;
            });

    }

    public async Task<string> GetStartflowAsync(string? orderId, CancellationToken token)
    {
        try
        {
            if (orderId.IsNullOrEmpty()) return WorkflowModuleConsts.OrderHandle;
            if (_systemSettingCacheManager.Snapshot == false) return WorkflowModuleConsts.OrderHandle;
            if (_appOptions.Value.IsZiGong == false) return WorkflowModuleConsts.OrderHandle;

            var order = await _orderSnapshotRepository.Queryable()
                .LeftJoin<Industry>((snapshot, industry) => snapshot.IndustryId == industry.Id)
                .Where((snapshot, industry) => snapshot.Id == orderId)
                .Select((snapshot, industry) => new { snapshot.Id, industry.ModuleCode })
                .FirstAsync(token);
            if (order == null) return WorkflowModuleConsts.OrderHandle;

            return order.ModuleCode ?? WorkflowModuleConsts.OrderHandle;
        }
        catch (Exception e)
        {
            _logger.LogError("获取随手拍开启流程参数异常", e);
            return WorkflowModuleConsts.OrderHandle;
        }
    }

    public async Task UpdateOrderAsync(UpdateOrderDto dto, CancellationToken token)
    {
        if (_systemSettingCacheManager.Snapshot == false) return;

        var sspSourceChannel = new List<string>() { "ZGSSP", "SJP12345" };
        if (sspSourceChannel.Any(m => m == dto.SourceChannelCode) == false)
        {
            await _orderSnapshotRepository.Updateable()
                .SetColumns(m => m.IsDeleted, true)
                .Where(m => m.Id == dto.Id)
                .ExecuteCommandAsync(token);
        }
        else
        {
            await _orderSnapshotRepository.Queryable(includeDeleted: true)
                .Where(m => m.Id == dto.Id)
                .FirstAsync(token)
                .Then(async snapshot =>
                {
                    snapshot.IsDeleted = false;
                    snapshot.IndustryId = dto.IndustryId;
                    snapshot.IndustryName = dto.IndustryName;

                    await _orderSnapshotRepository.UpdateAsync(snapshot, token);
                });
        }
    }
}
