package com.ywt.outpatient.service.rpc;

import com.ywt.biz.common.constant.YwtCommonRespCode;
import com.ywt.biz.common.enums.*;
import com.ywt.biz.common.exception.YwtCommonException;
import com.ywt.biz.common.util.Checker;
import com.ywt.biz.common.util.DateUtil;
import com.ywt.biz.common.util.ImageUtil;
import com.ywt.biz.common.util.StringHelper;
import com.ywt.biz.common.util.serializers.JsonSerializer;
import com.ywt.gapi.ResultCode;
import com.ywt.gapi.base.voice_sms.SendVoiceSmsRequest;
import com.ywt.gapi.base.voice_sms.SendVoiceSmsResponse;
import com.ywt.gapi.base.voice_sms.VoiceSmsService;
import com.ywt.gapi.drug.CommentPrescriptionRequest;
import com.ywt.gapi.drug.CommentPrescriptionResponse;
import com.ywt.gapi.drug.DrugService;
import com.ywt.gapi.im.IMService;
import com.ywt.gapi.im.SessionMessage;
import com.ywt.gapi.message.SendTemplateMessageRequest;
import com.ywt.gapi.message.WeChatMessageService;
import com.ywt.gapi.nfyy.GetDoctorListNoGroupResponse;
import com.ywt.gapi.nfyy.GetPatientInfoResponse;
import com.ywt.gapi.nfyy.SavePatientCardResponse;
import com.ywt.gapi.order.GetCommonOrderBillRequest;
import com.ywt.gapi.order.GetCommonOrderBillResponse;
import com.ywt.gapi.order.UpdatePayCodeRequest;
import com.ywt.gapi.order.UpdatePayCodeResponse;
import com.ywt.gapi.third.taihe.GetAddInfoResponse;
import com.ywt.gapi.third.taihe.GetDoctorListResponse;
import com.ywt.outpatient.core.PagedList;
import com.ywt.outpatient.core.SqlHelper;
import com.ywt.outpatient.core.utils.BizUtil;
import com.ywt.outpatient.domain.entity.center.*;
import com.ywt.outpatient.domain.models.DoctorInfo;
import com.ywt.outpatient.domain.models.OrderCommonInfo;
import com.ywt.outpatient.domain.models.TransferExtras;
import com.ywt.outpatient.domain.models.TreatmentFeeConfig;
import com.ywt.outpatient.domain.models.config.ConstantTemplateIds;
import com.ywt.outpatient.core.Constants;
import com.ywt.outpatient.domain.models.enums.*;
import com.ywt.outpatient.domain.wechat.Keyword;
import com.ywt.outpatient.service.common.TaiheProvider;
import com.ywt.outpatient.service.rpc.common.*;
import com.ywt.outpatient.service.rpc.common.DrugProvider;
import com.ywt.outpatient.service.common.FileProvider;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderService {
    private static Logger logger = LoggerFactory.getLogger(OrderService.class);

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private SqlHelper sqlHelperYwtCenter;

    @Autowired
    private IdGenerator idGenerator;

    @Autowired
    private TreatmentRepository treatmentRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PatientRepository patientRepository;

    @Autowired
    private TransferTreatmentRepository transferTreatmentRepository;

    @Autowired
    private AttendingTreatmentRepository attendingTreatmentRepository;

    @Autowired
    private TransferOrderViewRepository transferOrderViewRepository;

    @Autowired
    private OrderEvaluationRepository orderEvaluationRepository;

    @Autowired
    private OrderPaymentRepository orderPaymentRepository;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private AttendingOrderViewRepository attendingOrderViewRepository;

    @Autowired
    private ReportRepository reportRepository;

    @Autowired
    private UrlDefServiceProvider urlDefServiceProvider;

    @Autowired
    private PushServiceProvider pushServiceProvider;

    @Autowired
    private DoctorRepository doctorRepository;

    @Autowired
    private ConfigServiceProvider configServiceProvider;

    @Autowired
    private ServicePackageRepository servicePackageRepository;

    @Autowired
    private TreatmentReportRepository treatmentReportRepository;

    @Autowired
    private MedicalCardRepository medicalCardRepository;

    @Autowired
    private RegisteredOrderRepository registeredOrderRepository;

    @Autowired
    private NfyyServiceProvider nfyyServiceProvider;

    @Autowired
    private RefundedRepository refundedRepository;

    @Autowired
    private ConsultOrderRepository consultOrderRepository;

    @Autowired
    private MedicalRecordsImageRepository medicalRecordsImageRepository;

    @Autowired
    private FollowUpOrderRepository followUpOrderRepository;

    @Autowired
    private MedicalRecordsRepository medicalRecordsRepository;

    @Autowired
    private SnsUserRepository snsUserRepository;

    @Autowired
    private HospitalRepository hospitalRepository;

    @Autowired
    private DepartmentRepository departmentRepository;

    @Autowired
    private WeChatServiceProvider weChatServiceProvider;

    @Autowired
    private AccountRepository accountRepository;

    @Autowired
    private AccountDetailRepository accountDetailRepository;

    @Autowired
    private MsgTplRepository msgTplRepository;

    @Autowired
    private FollowUpConfigRepository followUpConfigRepository;

    @Autowired
    private DoctorScheduleRepository doctorScheduleRepository;

    @Autowired
    private ScheduleConfigRepository scheduleConfigRepository;

    @Autowired
    private AdditionalRegistrationRepository additionalRegistrationRepository;

    @Autowired
    private NfyyProvider nfyyProvider;

    @Autowired
    private WeChatProvider weChatProvider;

    @Autowired
    private SmsProvider smsProvider;

    @Autowired
    private FileProvider fileProvider;

    @Autowired
    private TaiheProvider taiheProvider;

    @Autowired
    private WxProvider wxProvider;

    @Autowired
    private HisAddRegisteredFlagRepository hisAddRegisteredFlagRepository;

    @Autowired
    private OutpatientOrderRepository outpatientOrderRepository;
    @Autowired
    private UserPatientRepository userPatientRepository;

    @Autowired
    private DrugProvider drugProvider;

    @Autowired
    BizConfigurer bizConfigurer;

    @DubboReference
    private DrugService drugServiceBlockingStub;

    @Autowired
    private WeChatMsgProvider weChatMsgProvider;

    @Autowired
    private MicroConsultRepository microConsultRepository;

    @Autowired
    private TreatmentOrderViewRepository treatmentOrderViewRepository;

    @DubboReference
    private WeChatMessageService weChatMessageServiceBlockingStub;

    @DubboReference
    private IMService imServiceBlockingStub;

    @Autowired
    private SnsUserInfoRepository snsUserInfoRepository;

    @Autowired
    private DoctorService doctorService;

    @DubboReference
    private VoiceSmsService voiceSmsServiceBlockingStub;

    @Autowired
    private RefundLogRepository refundLogRepository;

    @Autowired
    private OfflineConsultationRepository offlineConsultationRepository;

    @Autowired
    private OfflineConsultationService offlineConsultationService;

    @Autowired
    private ConsultingService consultingService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;


    int expireTime = 60 * 60 * 24 * 7;

    public Order getOrderById(int id) {
        return orderRepository.findById(id).orElse(null);
    }

    public Order getOrder(int businessId, int type) {
        return orderRepository.getOrder(businessId, type);
    }

    public Treatment getTreatmentById(int id) {
        return treatmentRepository.findById(id).orElse(null);
    }

    public TransferTreatment getTransferTreatmentById(int id) {
        return transferTreatmentRepository.findById(id).orElse(null);
    }

    public AttendingTreatment getAttendingTreatmentById(int id) {
        return attendingTreatmentRepository.findById(id).orElse(null);
    }

    public ConsultOrder getConsultOrder(int id) {
        return consultOrderRepository.findById(id).orElse(null);
    }

    public FollowUpOrder getFollowUpOrder(int id) {
        return followUpOrderRepository.findById(id).orElse(null);
    }

    /**
     * 创建订单
     * edit by dyh  2017/10/26
     *
     * @param patientId
     * @param doctorId
     * @param unionDoctorId
     * @param type
     * @param diagnosis
     * @param images
     * @return
     */
    public ServiceResult createOrder(int patientId, int doctorId, int unionDoctorId, int type,
                                     String diagnosis, String images, String extra, int terminal) {
        ServiceResult result = new ServiceResult();

        //患者
        Patient patient = patientRepository.findById(patientId).orElse(null);

        if (patient == null || patient.getDeleted()) {
            return result.failed("患者不存在");
        }

        //医生
        User doctorUser = userRepository.findById(doctorId).orElse(null);

        //关联医生
        User unionDoctorUser = userRepository.findById(unionDoctorId).orElse(null);

        if (doctorUser == null || unionDoctorUser == null) {
            return result.failed("创建失败：没找到相关用户信息");
        }

        //会话Id
        String sessionId = UUID.randomUUID().toString();

        //type:  类型（1-询诊，2-转诊，3-主诊）
        if (type == 1) {
            // 远程会诊价格
            BigDecimal treatmentAmount = configServiceProvider.getTreatmentPrice();

            int treatmentId = idGenerator.generateTreatmentId();
            Treatment treatment = new Treatment();
            treatment.setId(treatmentId);
            //这里是用户表id
            treatment.setUserId(patient.getUserId());
            treatment.setPatientRealName(patient.getRealName());
            treatment.setPatientMobile(patient.getMobile());
            treatment.setPatientSex(Checker.getIntegerValue(patient.getSex()));
            treatment.setDoctorId(doctorId);
            treatment.setDoctorRealName(doctorUser.getRealname());
            treatment.setUnionDoctorId(unionDoctorId);
            treatment.setUnionDoctorRealName(unionDoctorUser.getRealname());
            treatment.setTitle("远程会诊");
            treatment.setAmount(treatmentAmount);
            treatment.setRemark("");
            treatment.setCreateTime(new Date());
            treatment.setDeleted(false);
            //这里是患者表id
            treatment.setPatientId(patientId);
            treatment.setSessionId(sessionId);
            treatment.setTreatmentStatus(TreatmentStatusEnum.Pending.getValue());
            treatment.setPackageId(0);

            treatmentRepository.save(treatment);

            int orderId = idGenerator.generateOrderId();
            String orderNo = idGenerator.generateOrderNo("");

            Order order = new Order();
            order.setId(orderId);
            order.setOrderNo(orderNo);
            order.setOrderStatus(OrderStatusEnum.Pending_Payment.getValue());
            order.setUserId(patient.getUserId());
            order.setPatientMobile(patient.getMobile());
            order.setOrderAmount(treatmentAmount);
            order.setPaymentStatus(PaymentStatusEnum.Pending.getValue());
            order.setRemark("");
            order.setCreateTime(new Date());
            order.setDeleted(false);
            order.setOrderType(type);
            order.setBusinessId(treatmentId);
            order.setDoctorId(doctorId);
            order.setTitle("");

            orderRepository.save(order);

            Map<String, Object> map = new HashMap<>();
            map.put("sessionId", sessionId);
            map.put("orderId", orderId);
            result.setData(map);
        }
        //转诊
        else if (type == 2) {
            //根据表顺序添加
            TransferTreatment transferTreatment = new TransferTreatment();
            int transferTreatmentId = idGenerator.generateTransferTreatmentId();
            transferTreatment.setId(transferTreatmentId);
            //患者表
            transferTreatment.setUserId(patient.getUserId());
            transferTreatment.setPatientRealName(patient.getRealName());
            transferTreatment.setPatientMobile(patient.getMobile());
            transferTreatment.setPatientId(patientId);
            transferTreatment.setPatientSex(Checker.getIntegerValue(patient.getSex()));
            //转出医生
            transferTreatment.setFromDoctorId(doctorId);
            transferTreatment.setFromDoctorName(doctorUser.getRealname());
            //转入医生
            transferTreatment.setToDoctorId(unionDoctorId);
            transferTreatment.setToDoctorName(unionDoctorUser.getRealname());
            transferTreatment.setTitle("");
            transferTreatment.setAmount(BigDecimal.ZERO);
            transferTreatment.setRemark("");
            transferTreatment.setIs_deleted(false);
            transferTreatment.setCreateTime(new Date());
            transferTreatment.setSessionId(sessionId);
            //转诊信息
            transferTreatment.setDiagnosis(diagnosis);
            transferTreatment.setHospitalName("");
            transferTreatment.setDeptName("");
            transferTreatment.setBedNumber("");
//            transferTreatment.setTransferDate(); //转诊日期在创建订单的时候可为空
//            transferTreatment.getTransferPeriod();
//            transferTreatment.setTransferStatus();
            transferTreatment.setUpdateTime(new Date());

            // 附带业务参数解析
            if (!StringHelper.isNullOrEmpty(extra)) {
                TransferExtras extras = JsonSerializer.from(extra, TransferExtras.class);
                if (extras != null) {
                    Integer conditionType = Checker.getIntegerValue(extras.getConditionType());
                    Integer destDept = Checker.getIntegerValue(extras.getDestDept());
                    transferTreatment.setMedicalType(conditionType);
                    transferTreatment.setReferralDept(destDept);
                }
            }

            //保存
            transferTreatmentRepository.save(transferTreatment);

            int orderId = idGenerator.generateOrderId();
            Order order = new Order();
            order.setId(orderId);
            order.setOrderNo(idGenerator.generateOrderNo(""));
            order.setUserId(patient.getUserId());
            order.setPatientMobile(patient.getMobile());
            order.setCreateTime(new Date());
            order.setOrderAmount(BigDecimal.ZERO);
            order.setOrderStatus(OrderStatusEnum.Pending_Payment.getValue());
            order.setPaymentStatus(PaymentStatusEnum.Pending.getValue());
            order.setRemark("");
            order.setDeleted(false);
            order.setOrderType(type);
            order.setBusinessId(transferTreatmentId);
            order.setDoctorId(doctorId);
            order.setTitle("");

            orderRepository.save(order);

            Map<String, Object> map = new HashMap<>();
            map.put("sessionId", sessionId);
            map.put("orderId", orderId);
            result.setData(map);

            //短信通知
            smsProvider.notifyAfterCreateTransferOrder(doctorUser.getRealname(), unionDoctorUser.getRealname(),
                    unionDoctorUser.getMobile(), unionDoctorUser.getId());

            //模板消息发送
            int receiverDoctorId = Checker.getIntegerValue(transferTreatment.getToDoctorId());
            int doctorHospitalId = doctorService.getHospitalIdByDoctorId(receiverDoctorId);
            switch (doctorHospitalId) {
                default:
                    String first = String.format("尊敬的%s医生，您好！", transferTreatment.getToDoctorName());
                    String keyword1 = String.format("%s医生向您发起了双向转诊。", transferTreatment.getFromDoctorName());
                    String keyword2 = DateUtil.convertToString(transferTreatment.getCreateTime(), "yyyy年M月dd日 HH:mm");
                    String remark = "";
                    String url = String.format("%s/thnetdocwe/diagnosis/twoWayChat/%d/%d",
                            bizConfigurer.getYwtHttpsMsiteDomain(), orderId, transferTreatment.getToDoctorId());
//            wxProvider.notifyTpl1031(transferTreatment.getToDoctorId(), first, keyword1, keyword2, remark, "", url);
                    weChatMsgProvider.sendByTpl1031(transferTreatment.getToDoctorId(), "", url, first, remark, keyword1, keyword2);
                    break;
                case Constants.NFYYBYFY_HOSPITAL_ID:
                    first = String.format("尊敬的%s医生，您好！", transferTreatment.getToDoctorName()) + String.format("%s医生向您发起了双向转诊。", transferTreatment.getFromDoctorName());
                    keyword1 = transferTreatment.getFromDoctorName();
                    keyword2 = "双向转诊";
                    String keyword3 = DateUtil.convertToString(transferTreatment.getCreateTime(), "yyyy年M月dd日 HH:mm");
                    remark = "";
                    url = String.format("%s/nfyybyfydocwe/diagnosis/twoWayChat/%d/%d",
                            bizConfigurer.getYwtHttpsMsiteDomain(), orderId, transferTreatment.getToDoctorId());
                    weChatMsgProvider.sendByTpl2014(transferTreatment.getToDoctorId(), first, remark, "", url,
                            keyword1, keyword2, keyword3);
                    break;
            }

            // 发送编辑好文案的电话给医生
            trySendingVoiceMsg(unionDoctorUser.getMobile());
        }
        //主诊
        else if (type == 3) {
            AttendingTreatment attendingTreatment = new AttendingTreatment();
            int attendingTreatmentId = idGenerator.generateAttendingTreatmentId();
            attendingTreatment.setId(attendingTreatmentId);
            //患者表
            attendingTreatment.setUserId(patient.getUserId());
            attendingTreatment.setPatientRealName(patient.getRealName());
            attendingTreatment.setPatientMobile(patient.getMobile());
            attendingTreatment.setPatientId(patientId);
            attendingTreatment.setPatientSex(Checker.getIntegerValue(patient.getSex()));
            //发起医生
            attendingTreatment.setFromDoctorId(doctorId);
            attendingTreatment.setFromDoctorName(doctorUser.getRealname());
            //主诊医生
            attendingTreatment.setToDoctorId(unionDoctorId);
            attendingTreatment.setToDoctorName(unionDoctorUser.getRealname());
            attendingTreatment.setTitle("");
            attendingTreatment.setAmount(BigDecimal.ZERO);
            attendingTreatment.setRemark("");
            attendingTreatment.setDeleted(false);
            //主诊信息
            attendingTreatment.setSessionId(sessionId);
            attendingTreatment.setDiagnosis(diagnosis);

//            主诊同意后需要填写的信息
//            attendingTreatment.setAttendingDate();
//            attendingTreatment.setAttendingPeriod();
//            attendingTreatment.setAttendingStatus(); //主诊业务状态（位标识：1-拒绝，2-同意，4-已通知用户，8-已支付，16-已评价）

            attendingTreatment.setCreateTime(new Date());
            attendingTreatment.setUpdateTime(new Date());
            attendingTreatmentRepository.save(attendingTreatment);
            int orderId = idGenerator.generateOrderId();

            Order order = new Order();
            order.setId(orderId);
            order.setOrderNo(idGenerator.generateOrderNo(""));
            order.setUserId(patient.getUserId());
            order.setPatientMobile(patient.getMobile());
            order.setCreateTime(new Date());
            order.setOrderAmount(BigDecimal.ZERO);
            order.setOrderStatus(OrderStatusEnum.Pending_Payment.getValue());
            order.setPaymentStatus(PaymentStatusEnum.Pending.getValue());
            order.setRemark("");
            order.setDeleted(false);
            order.setOrderType(type);
            order.setBusinessId(attendingTreatmentId);
            order.setDoctorId(doctorId);
            order.setTitle("");

            orderRepository.save(order);

            Map<String, Object> map = new HashMap<>();
            map.put("sessionId", sessionId);
            map.put("orderId", orderId);
            result.setData(map);

            //短信通知
            smsProvider.notifyAfterCreateAttendingOrder(
                    doctorUser.getRealname(), unionDoctorUser.getRealname(), unionDoctorUser.getMobile());
        } else {
            return result.failed("暂不支持的类型");
        }

//        // 发送短信通知
//        messageServiceProvider.notifyAfterCreateOrder(unionDoctorUser.getMobile(), doctorUser.getRealname() + "医生", type);

        //消息推送
        pushServiceProvider.notifyAfterCreateOrder(doctorUser.getRealname() + "医生", type, unionDoctorUser.getId());
        return result.succeed("订单创建成功");
    }

    /**
     * 创建远程会诊订单
     *
     * @param fromDoctorId 发起医生Id
     * @param toDoctorId   被邀请医生Id
     * @param patientId    患都Id
     * @param packageId    套餐Id
     * @return
     */
    public ServiceResult createTreatmentOrder(int fromDoctorId, int toDoctorId, int patientId, int packageId, int terminal) {
        ServiceResult result = new ServiceResult();
        Patient patient = patientRepository.findById(patientId).orElse(null);

        if (patient == null || patient.getDeleted()) {
            return result.failed("患者不存在");
        }

        User fromDoctorUser = userRepository.findById(fromDoctorId).orElse(null);    //邀请医生

        if (fromDoctorUser == null || fromDoctorUser.getIsDeleted()) {
            return result.failed("邀请医生不存在");
        }

        User toDoctorUser = userRepository.findById(toDoctorId).orElse(null);     //被邀请医生

        if (toDoctorUser == null || toDoctorUser.getIsDeleted()) {
            return result.failed("被邀请医生不存在");
        }

//        ServicePackage servicePackage = servicePackageRepository.findOne(packageId);
//
//        if (servicePackage == null || servicePackage.getDeleted() || servicePackage.getType() != OrderTypeEnum.Treatment.getValue()) {
//            return result.failed("服务套餐不存在");
//        }

        //会话Id
        String sessionId = StringHelper.getUUIDWithoutHyphen();

        //远程会诊费用
        int treatmentFee = 0;
        Doctor doctor = doctorRepository.findById(fromDoctorId).orElse(null);


        if (StringHelper.isNullOrWhiteSpace(doctor.getTreatmentFeeConfig())) {
            treatmentFee = configServiceProvider.getTreatmentFee();
        } else {
            TreatmentFeeConfig config = JsonSerializer.from(doctor.getTreatmentFeeConfig(), TreatmentFeeConfig.class);
            if (config != null && config.getPackageItemFee() != null) {
                treatmentFee = config.getPackageItemFee();
            } else {
                treatmentFee = configServiceProvider.getTreatmentFee();
            }
        }

        // 远程会诊价格，单位：分->元
        BigDecimal treatmentAmount = new BigDecimal(treatmentFee / 100d);

        int treatmentId = idGenerator.generateTreatmentId();
        Treatment treatment = new Treatment();
        treatment.setId(treatmentId);
        treatment.setUserId(patient.getUserId());
        treatment.setPatientRealName(patient.getRealName());
        treatment.setPatientMobile(patient.getMobile());
        treatment.setDoctorId(fromDoctorId);
        treatment.setDoctorRealName(fromDoctorUser.getRealname());
        treatment.setUnionDoctorId(toDoctorId);
        treatment.setUnionDoctorRealName(toDoctorUser.getRealname());
        treatment.setTitle(OrderTypeEnum.TREATMENT.getDisplayName());
        treatment.setAmount(treatmentAmount);
        treatment.setRemark("");
        treatment.setCreateTime(new Date());
        treatment.setDeleted(false);
        treatment.setPatientId(patientId);
        treatment.setSessionId(sessionId);
        treatment.setTreatmentStatus(TreatmentStatusEnum.Pending.getValue());
        treatment.setPackageId(packageId);

        treatmentRepository.save(treatment);

        int orderId = idGenerator.generateOrderId();
        String orderNo = idGenerator.generateOrderNo("");

        Order order = new Order();
        order.setId(orderId);
        order.setOrderNo(orderNo);
        order.setOrderStatus(OrderStatusEnum.Pending_Payment.getValue());
        order.setUserId(patient.getUserId());
        order.setPatientMobile(patient.getMobile());
        order.setOrderAmount(treatmentAmount);
        order.setPaymentStatus(PaymentStatusEnum.Pending.getValue());
        order.setRemark("");
        order.setCreateTime(new Date());
        order.setDeleted(false);
        order.setOrderType(OrderTypeEnum.TREATMENT.getValue());
        order.setBusinessId(treatmentId);
        order.setDoctorId(fromDoctorId);
        order.setTitle("");

        orderRepository.save(order);

        Map<String, Object> map = new HashMap<>();
        map.put("sessionId", sessionId);
        map.put("orderId", orderId);
        map.put("userId", order.getUserId());
        map.put("treatment", treatment);
        result.setData(map);

        try {
            String fromDoctorName = fromDoctorUser.getRealname() + "医生";
            pushServiceProvider.notifyAfterCreateOrder(fromDoctorName, OrderTypeEnum.TREATMENT.getValue(), toDoctorUser.getId());

            //发送短信
            smsProvider.notifyAfterCreateTreatmentOrder(fromDoctorUser.getRealname(), toDoctorUser.getRealname(),
                    toDoctorUser.getMobile(), toDoctorId);

            smsProvider.notifyPatientTreatmentOrder(patient.getRealName(), patient.getMobile(), fromDoctorId);
        } catch (Exception e) {
            logger.error("消息推送错误，createTreatmentOrder(): {}", e.getMessage(), e);
        }
        return result.succeed("订单创建成功");
    }


    /**
     * 创建预约挂号订单
     *
     * @param hospitalId       医院ID
     * @param deptCode         科室Code
     * @param deptName         科室名称
     * @param doctorCode       医生Code
     * @param doctorName       医生名称
     * @param registeredFee    挂号费
     * @param medicalFee       诊查费
     * @param registeredDate   预约日期
     * @param period           预约时间段
     * @param startTime        预约开始时间：HH:MI
     * @param endTime          预约结束时间：HH:MI
     * @param userId           用户ID
     * @param medicalCardId    诊疗卡ID
     * @param scheduleItemCode 门诊排班项记录标识
     * @param paymentChannel   支付渠道
     * @param source           订单来源
     * @return
     */
    public ServiceResult createRegisteredOrder(
            int hospitalId, String deptCode, String deptName, String doctorCode,
            String doctorName, int registeredFee, int medicalFee, long registeredDate,
            int period, String startTime, String endTime, int userId, int medicalCardId,
            String scheduleItemCode, int paymentChannel, int source) {
        ServiceResult serviceResult = new ServiceResult();

        if (paymentChannel != PaymentChannelEnum.MedicalCard.getValue() &&
                paymentChannel != PaymentChannelEnum.Cash.getValue()) {
            return serviceResult.failed("支付方式不正确");
        }

//        if((datePeriodEnum != DatePeriodEnum.Morning && datePeriodEnum != DatePeriodEnum.Afternoon)){
//            return serviceResult.failed("非法请求");
//        }


        MedicalCard medicalCard = medicalCardRepository.findById(medicalCardId).orElse(null);

        if (medicalCard == null || medicalCard.getStatus() == MedicalCardStatusEnum.DELETED.getValue()) {
            return serviceResult.failed("诊疗卡不存在");
        }

        User user = userRepository.findById(userId).orElse(null);

        if (user == null || user.getIsDeleted()) {
            return serviceResult.failed(("用户不存在"));
        }

        int paymentStatus = PaymentStatusEnum.Pending.getValue();
//        int registeredStatus = RegisteredStatusEnum.Paid.getValue();

//        if (paymentChannel == PaymentChannelEnum.Cash.getValue()) {
//            //现场支付
//            paymentStatus = PaymentStatusEnum.Success.getValue();
//        }
        GetDoctorListNoGroupResponse res = nfyyProvider.getDoctorListNoGroup(doctorName, "");

        if ((res == null) || (res.getCode() != ResultCode.SUCCEED_VALUE) || (res.getDoctorsList().size() == 0)) {
            return serviceResult.failed("医生不存在");
        }

        int orderId = idGenerator.generateOrderId();
        String orderNo = idGenerator.generateOrderNo("");
        com.ywt.gapi.nfyy.Doctor doctor = res.getDoctors(0);

        RegisteredOrder registeredOrder = new RegisteredOrder();
        registeredOrder.setId(idGenerator.genRegisteredOrderId());
        registeredOrder.setUserId(userId);
        registeredOrder.setHospitalId(hospitalId);
        registeredOrder.setHospitalName("南方医科大学南方医院");
        registeredOrder.setDeptId(0);
        registeredOrder.setDoctorId(0);
        registeredOrder.setDoctorName(doctorName);
        registeredOrder.setDoctorTitle(Checker.getStringValue(doctor.getDoctorTitle()));
        registeredOrder.setTotal(registeredFee + medicalFee);
        registeredOrder.setRegisteredDate(new Date(registeredDate));
        registeredOrder.setRegisteredPeriod(period);
        registeredOrder.setStartTime(startTime);
        registeredOrder.setEndTime(endTime);
        registeredOrder.setHisPatientId(medicalCard.getHisPatientId());
        registeredOrder.setMedicalCardId(medicalCardId);
        registeredOrder.setPatientSex(medicalCard.getSex());
        registeredOrder.setPatientName(medicalCard.getPatientName());
        registeredOrder.setPaymentChannel(paymentChannel);
        registeredOrder.setDeleted(false);
        registeredOrder.setUpdateTime(new Date());
        registeredOrder.setCreateTime(new Date());
        registeredOrder.setScheduleItemCode(scheduleItemCode);
        registeredOrder.setDoctorCode(doctorCode);
        registeredOrder.setDoctorName(doctorName);
        registeredOrder.setDeptCode(deptCode);
        registeredOrder.setDeptName(deptName);
        registeredOrder.setRegisteredFee(registeredFee);
        registeredOrder.setMedicalFee(medicalFee);
        registeredOrder.setPaymentStatus(paymentStatus);
        registeredOrder.setRegisteredStatus(0);
        registeredOrder.setSource(source);
        registeredOrder.setRegisteredType(RegisteredTypeEnum.GENERAL.getValue());
        registeredOrder.setOrderId(orderId);
        registeredOrder.setOrderNo(orderNo);

        registeredOrderRepository.save(registeredOrder);

        int orderType = OrderTypeEnum.REGISTERED.getValue();


        Order order = new Order();
        order.setId(orderId);
        order.setOrderNo(orderNo);
        order.setOrderStatus(OrderStatusEnum.Pending_Payment.getValue());
        order.setUserId(registeredOrder.getUserId());
        order.setPatientMobile(user.getMobile());
        order.setOrderAmount(new BigDecimal(registeredOrder.getTotal() / 100));
        order.setPaymentStatus(paymentStatus);
        order.setRemark("");
        order.setCreateTime(new Date());
        order.setDeleted(false);
        order.setOrderType(orderType);
        order.setBusinessId(registeredOrder.getId());
        order.setDoctorId(0);
        order.setTitle("");

        orderRepository.save(order);

        String strAmount = String.valueOf(registeredOrder.getTotal() / 100);
        //调用HIS
        ServiceResult createOrderResult = nfyyServiceProvider.createOrder(scheduleItemCode, registeredOrder.getHisPatientId(),
                "", "", "", strAmount, registeredOrder.getStartTime(), registeredOrder.getEndTime(), RegisteredTypeEnum.GENERAL.getValue(), registeredOrder.getPatientName());

        if (createOrderResult.success()) {
            Map<String, Object> map = createOrderResult.getData();
            registeredOrder.setHisSeqCode(map.get("seqCode").toString());
            registeredOrder.setHisRegFee(map.get("regFee").toString());
            registeredOrder.setHisAdmitRange(map.get("admitRange").toString());
            registeredOrder.setHisAdmitAddress(map.get("admitAddress").toString());
            registeredOrder.setHisOrderContent(map.get("orderContent").toString());
            registeredOrder.setHisTransactionId(map.get("transactionId").toString());
            registeredOrder.setHisOrderCode(map.get("orderCode").toString());
            registeredOrder.setRegisteredStatus(RegisteredStatusEnum.Booked.getValue());

            registeredOrderRepository.save(registeredOrder);

            int status = 0; //0-现场支付 1-诊疗卡支付（预约成功，取号成功） 2-诊疗卡支付（预约成功，取号失败）
            String msg = "已为您保留预约号，请在就诊当日到医院人工缴费窗口取号，如未就诊将计爽约一次";   //现场支付提示语

            if (paymentChannel == PaymentChannelEnum.MedicalCard.getValue()) {
                //诊疗卡支付
                ServiceResult confirmResult = payByMedicalCard(order, registeredOrder);

                if (confirmResult.success()) {
                    //预约成功，取号成功
                    status = 1;
                    msg = "您的申请已经成功提交，请注意查看预约信息订单。";

//                    registeredOrder.setRegisteredStatus(registeredOrder.getRegisteredStatus() | RegisteredStatusEnum.Took.getValue());
//                    registeredOrderRepository.save(registeredOrder);
                } else {
                    //预约成功，取号失败
                    status = 2;
                    msg = "但余额不足，支付失败，请至现场缴费！";
                }
            }

            try {
                String date = DateUtil.convertToString(registeredOrder.getRegisteredDate(), "yyyy-MM-dd");

                if (!StringHelper.isNullOrWhiteSpace(startTime)) {
                    date += " " + startTime;
                }

                //发送模板消息至南方医务通公众号
                weChatProvider.notifyRegistered(registeredOrder.getUserId(), registeredOrder.getPatientName(),
                        SexEnum.getSexDisplayName(registeredOrder.getPatientSex().intValue()), "南方医科大学南方医院",
                        registeredOrder.getDeptName(), registeredOrder.getDoctorName(), registeredOrder.getHisOrderCode(),
                        status, registeredOrder.getTotal(), registeredOrder.getHisPatientId(), date,
                        registeredOrder.getDoctorTitle(), registeredOrder.getHisAdmitAddress());

                //发送模板消息至南方医院太和分院公众号
                String url = "";
                String miniProgram = "";
                if (registeredOrder.getHospitalId() == Constants.TAIHE_HOSPITAL_ID) {
                    // 太和跳往公众号
                    url = bizConfigurer.getYwtHttpsMsiteDomain() + Constants.TH_REGISTER_INFO_ORDER_CENTER_URL;
                } else if (registeredOrder.getHospitalId() == Constants.NFYYBYFY_HOSPITAL_ID) {
                    // 白云跳往小程序
                    String pagePath = Constants.BY_REGISTER_INFO_ORDER_CENTER_LIST;
                    miniProgram = BizUtil.getMiniProgramParam(Constants.NFYYBYFY_WXMP_APP_ID, pagePath);
                }
                String tplId = "TPL_1006";
                String first = "您好，您已预约挂号成功。";
                String remark = "";
                String userInfo = String.format("%s（ID号%s）您已成功预约%s号，",
                        registeredOrder.getPatientName(), registeredOrder.getHisPatientId(),
                        date + registeredOrder.getDeptName() + registeredOrder.getDoctorName() + registeredOrder.getDoctorTitle());

                if (status != 1) {
                    if (registeredOrder.getDeptName().contains("惠侨")) {
                        remark = userInfo + "请携带身份证和诊疗卡（复诊）提前半小时至惠侨楼二楼取号。" +
                                "如过时将作延迟就诊处理。如当次未就诊记爽约一次，爽约三次将对预约进行限制。" +
                                "如您无法就诊请提前一天取消预约。祝您身体健康！";
                    } else {
                        remark = userInfo + "请携带身份证和诊疗卡（复诊）提前半小时至门诊各挂号窗口或自助机取号。" +
                                "如过时将作延迟就诊处理。如当次未就诊记爽约一次，爽约三次将对预约进行限制。" +
                                "如您无法就诊请提前一天取消预约。祝您身体健康！";
                    }
                } else {
                    if (registeredOrder.getDeptName().contains("惠侨")) {
                        remark = String.format("%s本次挂号扣费 %.2f元,请携带就诊卡提前半小时到%s取号。" +
                                        "如过时将作延迟就诊处理。如当次未就诊记爽约一次，爽约三次将对预约进行限制。" +
                                        "如无法就诊请提前一天取消预约。祝您身体健康！",
                                userInfo, registeredOrder.getTotal() / 100d, registeredOrder.getHisAdmitAddress());
                    } else {
                        remark = String.format("%s本次挂号扣费 %.2f元,请携带就诊卡提前半小时到%s报到。" +
                                        "如过时将作延迟就诊处理。如当次未就诊记爽约一次，爽约三次将对预约进行限制。" +
                                        "如无法就诊请提前一天取消预约。祝您身体健康！",
                                userInfo, registeredOrder.getTotal() / 100d, registeredOrder.getHisAdmitAddress());
                    }
                }
                String keyword5 = "";
                if (registeredOrder.getHospitalId() == Constants.TAIHE_HOSPITAL_ID) {
                    keyword5 = String.format("%s %s (%s-%s)",
                            DateUtil.convertToString(registeredOrder.getRegisteredDate(), "yyyy-MM-dd")
                            , RegisteredDatePeriod.getDisplayName(Checker.getIntegerValue(registeredOrder.getRegisteredPeriod()))
                            , registeredOrder.getStartTime()
                            , registeredOrder.getEndTime());
                } else {
                    keyword5 = String.format("%s %s-%s"
                            , DateUtil.convertToString(registeredOrder.getRegisteredDate(), "yyyy-MM-dd")
                            , registeredOrder.getStartTime()
                            , registeredOrder.getEndTime());
                }

                weChatMsgProvider.send(registeredOrder.getUserId(), tplId, url, miniProgram, first, remark,
                        registeredOrder.getPatientName(), registeredOrder.getMedicalCardNo(), registeredOrder.getDeptName(),
                        registeredOrder.getDoctorName(),
                        keyword5);
            } catch (Exception e) {
                logger.error("createRegisteredOrder(): 发送模板消息出错，{}", e.getMessage(), e);
            }

            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("orderId", orderId);
            dataMap.put("orderType", orderType);
            dataMap.put("status", status);

            serviceResult.setData(dataMap);
            return serviceResult.succeed(msg);
        } else {
            return serviceResult.failed(createOrderResult.getMsg());
        }
    }

    /**
     * 创建加号预约挂号订单
     *
     * @param hospitalId       医院ID
     * @param deptCode         科室Code
     * @param deptName         科室名称
     * @param doctorCode       医生Code
     * @param doctorName       医生名称
     * @param registeredFee    挂号费
     * @param medicalFee       诊查费
     * @param registeredDate   预约日期
     * @param period           预约时间段
     * @param startTime        预约开始时间：HH:MI
     * @param endTime          预约结束时间：HH:MI
     * @param userId           用户ID
     * @param medicalCardId    诊疗卡ID
     * @param scheduleItemCode 门诊排班项记录标识
     * @param paymentChannel   支付渠道
     * @param source           订单来源
     * @return
     */
    public ServiceResult createAddRegisteredOrder(
            int hospitalId, String deptCode, String deptName, String doctorCode,
            String doctorName, int registeredFee, int medicalFee, long registeredDate,
            int period, String startTime, String endTime, int userId, int medicalCardId,
            String scheduleItemCode, int paymentChannel, int source) {
        ServiceResult serviceResult = new ServiceResult();

        if (paymentChannel != PaymentChannelEnum.MedicalCard.getValue() &&
                paymentChannel != PaymentChannelEnum.Cash.getValue()) {
            return serviceResult.failed("支付方式不正确");
        }

        MedicalCard medicalCard = medicalCardRepository.findById(medicalCardId).orElse(null);

        if (medicalCard == null || medicalCard.getStatus() == MedicalCardStatusEnum.DELETED.getValue()) {
            return serviceResult.failed("诊疗卡不存在");
        }

        //限制只有太和医院的诊疗卡可以进行加号预约
        if (medicalCard.getHospitalId() != Constants.TAIHE_HOSPITAL_ID) {
            return serviceResult.failed("没有加号的资格");
        }

        HisAddRegisteredFlag flag = hisAddRegisteredFlagRepository.getFlag(medicalCard.getHisPatientId());
        if (flag == null || flag.getStatus() != 1) {
            return serviceResult.failed("您没有被允许加号的资格");
        }

        GetAddInfoResponse getAddInfoResponse = taiheProvider.getAddInfo(
                medicalCard.getHisPatientId(), "", "", "");

        if (getAddInfoResponse.getCode() != ResultCode.SUCCEED_VALUE) {
            return serviceResult.failed(getAddInfoResponse.getMsg());
        }

//        int flagStatus = getAddInfoResponse.getAllow();
        String pattern = "";

        if (getAddInfoResponse.getCreateTime().length() == 19) {
            pattern = "yyyy-MM-dd HH:mm:ss";
        } else {
            pattern = "yyyy-MM-dd";
        }

        Date createTime = DateUtil.stringToDate(getAddInfoResponse.getCreateTime(), pattern);

        if (getAddInfoResponse.getAllow() != 1) {
            //不允许加号
            flag.setStatus(2);
            flag.setDays(getAddInfoResponse.getDays());
            flag.setAllowDate(createTime);
            flag.setUpdateTime(new Date());
            hisAddRegisteredFlagRepository.save(flag);

            return serviceResult.failed("不允许加号");
        }

        //判断是否已过期
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(createTime);
        calendar.set(Calendar.HOUR, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.add(Calendar.DATE, getAddInfoResponse.getDays() + 1);

        if (new Date().after(calendar.getTime())) {
            //已过期
            flag.setStatus(4);
            flag.setDays(getAddInfoResponse.getDays());
            flag.setAllowDate(createTime);
            flag.setUpdateTime(new Date());
            hisAddRegisteredFlagRepository.save(flag);

            return serviceResult.failed("加号标识已失效");
        }

        //可进行加号
        String nfyyPatientId = "";
        GetPatientInfoResponse getPatientInfoResponse = nfyyProvider.getPatientInfo(
                "", "", medicalCard.getIdNo(), medicalCard.getPatientName());

        if (getPatientInfoResponse.getCode() == ResultCode.SUCCEED_VALUE &&
                getPatientInfoResponse.getPatientInfo() != null) {
            //已经有诊疗卡，是否需要进行绑定？
            nfyyPatientId = getPatientInfoResponse.getPatientInfo().getPatientId();
        } else {
            //没有诊疗卡，建索引
            SavePatientCardResponse savePatientCardResponse = nfyyProvider.savePatientCard(
                    medicalCard.getIdNo(), medicalCard.getPatientName(), medicalCard.getSex(),
                    medicalCard.getBirthday(), medicalCard.getTelephoneNo());

            if (savePatientCardResponse.getCode() == ResultCode.SUCCEED_VALUE) {
                nfyyPatientId = savePatientCardResponse.getPatientId();
            } else {
                return serviceResult.failed(savePatientCardResponse.getMsg());
            }
        }

        User user = userRepository.findById(userId).orElse(null);

        if (user == null || user.getIsDeleted()) {
            return serviceResult.failed(("用户不存在"));
        }

        int paymentStatus = PaymentStatusEnum.Pending.getValue();

        GetDoctorListNoGroupResponse res = nfyyProvider.getDoctorListNoGroup(doctorName, "");

        if (res == null || res.getCode() != ResultCode.SUCCEED_VALUE || res.getDoctorsList().size() == 0) {
            return serviceResult.failed("医生不存在");
        }

        com.ywt.gapi.nfyy.Doctor doctor = res.getDoctors(0);
        int orderId = idGenerator.generateOrderId();
        String orderNo = idGenerator.generateOrderNo("");

        RegisteredOrder registeredOrder = new RegisteredOrder();
        registeredOrder.setId(idGenerator.genRegisteredOrderId());
        registeredOrder.setUserId(userId);
        registeredOrder.setHospitalId(1);
        registeredOrder.setDeptId(0);
        registeredOrder.setDoctorId(0);
        registeredOrder.setDoctorName(doctorName);
        registeredOrder.setDoctorTitle(Checker.getStringValue(doctor.getDoctorTitle()));
        registeredOrder.setTotal(registeredFee + medicalFee);
        registeredOrder.setRegisteredDate(new Date(registeredDate));
        registeredOrder.setRegisteredPeriod(period);
        registeredOrder.setStartTime(startTime);
        registeredOrder.setEndTime(endTime);
        registeredOrder.setHisPatientId(medicalCard.getHisPatientId());
        registeredOrder.setMedicalCardId(medicalCardId);
        registeredOrder.setPatientSex(medicalCard.getSex());
        registeredOrder.setPatientName(medicalCard.getPatientName());
        registeredOrder.setPaymentChannel(paymentChannel);
        registeredOrder.setDeleted(false);
        registeredOrder.setUpdateTime(new Date());
        registeredOrder.setCreateTime(new Date());
        registeredOrder.setScheduleItemCode(scheduleItemCode);
        registeredOrder.setDoctorCode(doctorCode);
        registeredOrder.setDoctorName(doctorName);
        registeredOrder.setDeptCode(deptCode);
        registeredOrder.setDeptName(deptName);
        registeredOrder.setRegisteredFee(registeredFee);
        registeredOrder.setMedicalFee(medicalFee);
        registeredOrder.setPaymentStatus(paymentStatus);
        registeredOrder.setRegisteredStatus(0);
        registeredOrder.setSource(source);
        registeredOrder.setRegisteredType(RegisteredTypeEnum.ADDITIONAL.getValue());
        registeredOrder.setFlagId(flag.getId());
        registeredOrder.setOrderId(orderId);
        registeredOrder.setOrderNo(orderNo);
        registeredOrderRepository.save(registeredOrder);

        int orderType = OrderTypeEnum.REGISTERED.getValue();

        Order order = new Order();
        order.setId(orderId);
        order.setOrderNo(orderNo);
        order.setOrderStatus(OrderStatusEnum.Pending_Payment.getValue());
        order.setUserId(registeredOrder.getUserId());
        order.setPatientMobile(user.getMobile());
        order.setOrderAmount(new BigDecimal(registeredOrder.getTotal() / 100d));
        order.setPaymentStatus(paymentStatus);
        order.setRemark("");
        order.setCreateTime(new Date());
        order.setDeleted(false);
        order.setOrderType(orderType);
        order.setBusinessId(registeredOrder.getId());
        order.setDoctorId(0);
        order.setTitle("");

        orderRepository.save(order);

        String strAmount = String.valueOf(registeredOrder.getTotal() / 100d);

        //调用HIS
        ServiceResult createOrderResult = nfyyServiceProvider.createOrder(
                scheduleItemCode, nfyyPatientId, "", "", "",
                strAmount, registeredOrder.getStartTime(), registeredOrder.getEndTime(),
                RegisteredTypeEnum.ADDITIONAL.getValue(), registeredOrder.getPatientName());

        if (createOrderResult.success()) {
            flag.setStatus(3);
            flag.setDays(getAddInfoResponse.getDays());
            flag.setAllowDate(createTime);
            flag.setUpdateTime(new Date());
            flag.setNfyyHisPatientId(nfyyPatientId);
            hisAddRegisteredFlagRepository.save(flag);

            Map<String, Object> map = createOrderResult.getData();
            registeredOrder.setHisSeqCode(map.get("seqCode").toString());
            registeredOrder.setHisRegFee(map.get("regFee").toString());
            registeredOrder.setHisAdmitRange(map.get("admitRange").toString());
            registeredOrder.setHisAdmitAddress(map.get("admitAddress").toString());
            registeredOrder.setHisOrderContent(map.get("orderContent").toString());
            registeredOrder.setHisTransactionId(map.get("transactionId").toString());
            registeredOrder.setHisOrderCode(map.get("orderCode").toString());
            registeredOrder.setRegisteredStatus(RegisteredStatusEnum.Booked.getValue());

            registeredOrderRepository.save(registeredOrder);

            int status = 0; //0-现场支付 1-诊疗卡支付（预约成功，取号成功） 2-诊疗卡支付（预约成功，取号失败）
            String msg = "已为您保留预约号，请在就诊当日到医院人工缴费窗口取号，如未就诊将计爽约一次";   //现场支付提示语

            try {
                wxProvider.notifyAddRegisteredTaihe(
                        registeredOrder.getUserId(), registeredOrder.getDoctorName(), registeredOrder.getDoctorTitle(),
                        "南方医科大学南方医院", registeredOrder.getPatientName(),
                        registeredOrder.getRegisteredDate(), registeredOrder.getStartTime(),
                        registeredOrder.getDeptName());
            } catch (Exception e) {
                logger.error("createAddRegisteredOrder(): 发送模板消息出错，{}", e.getMessage(), e);
            }

            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("orderId", orderId);
            dataMap.put("orderType", orderType);
            dataMap.put("status", status);

            serviceResult.setData(dataMap);
            return serviceResult.succeed(msg);
        } else {
            return serviceResult.failed(createOrderResult.getMsg());
        }
    }

    /**
     * 诊疗卡支付（预约订单）
     *
     * @param order           订单
     * @param registeredOrder 预约订单
     * @return
     */
    public ServiceResult payByMedicalCard(Order order, RegisteredOrder registeredOrder) {
        ServiceResult serviceResult = new ServiceResult();
//        String strAmount = String.valueOf(registeredOrder.getTotal() / 100);
        String strAmount = registeredOrder.getHisRegFee();

        String payModeCode = "CPP";
        BigDecimal amount = new BigDecimal(strAmount);

        OrderPayment payment = new OrderPayment();
        payment.setId(idGenerator.genOrderPaymentId());
        payment.setOrderId(order.getId());
        payment.setOrderNo(order.getOrderNo());
        payment.setPaymentNo(idGenerator.genPaymentNo(""));
        payment.setUserId(registeredOrder.getUserId());
        payment.setPaymentChannel(PaymentChannelEnum.MedicalCard.getValue());
        payment.setPaymentStatus(PaymentStatusEnum.Processing.getValue());
        payment.setCallbackTime(null);
        payment.setOrderAmount(amount);
        payment.setPaymentAmount(amount);
        payment.setRemark(null);
        payment.setDeleted(false);
        payment.setCreateTime(new Date());
        payment.setHisOrderCode(registeredOrder.getHisOrderCode());
        payment.setHisPatientId(registeredOrder.getHisPatientId());
        payment.setHisPayModeCode(payModeCode);

        orderPaymentRepository.save(payment);

        ServiceResult confirmResult = nfyyServiceProvider.confirm(registeredOrder.getHisOrderCode(),
                registeredOrder.getHisPatientId(), strAmount, payModeCode);

        if (confirmResult.success()) {
            payment.setPaymentStatus(PaymentStatusEnum.Success.getValue());
            payment.setCallbackTime(new Date());

            Map<String, Object> map = confirmResult.getData();
            String callbackData = JsonSerializer.toJson(map);

            payment.setCallbackData(callbackData);
            orderPaymentRepository.save(payment);

            registeredOrder.setPaymentStatus(PaymentStatusEnum.Success.getValue());
            registeredOrder.setPaymentChannel(PaymentChannelEnum.MedicalCard.getValue());
            registeredOrder.setHisClinicCode(map.get("admNo").toString());
            registeredOrder.setRegisteredStatus(registeredOrder.getRegisteredStatus() | RegisteredStatusEnum.Took.getValue());
            registeredOrderRepository.save(registeredOrder);

            order.setPaymentStatus(PaymentStatusEnum.Success.getValue());
            orderRepository.save(order);

            return serviceResult.succeed("支付成功");
        } else {
            payment.setPaymentStatus(PaymentStatusEnum.Failed.getValue());
            payment.setCallbackTime(new Date());
            payment.setCallbackData(String.format("诊疗卡支付失败，原因：%s", confirmResult.getMsg()));

            orderPaymentRepository.save(payment);

            return serviceResult.failed("支付失败，" + confirmResult.getMsg());
        }
    }

    public ServiceResult payByMedicalCard(int orderId, int userId) {
        ServiceResult serviceResult = new ServiceResult();

        Order order = getOrderById(orderId);

        if (order == null || order.getDeleted()) {
            return serviceResult.failed("订单不存在");
        }

        if (order.getOrderType() != OrderTypeEnum.REGISTERED.getValue() || order.getUserId() != userId) {
            return serviceResult.failed("非法请求");
        }

        RegisteredOrder registeredOrder = registeredOrderRepository.findById(order.getBusinessId()).orElse(null);

        if (registeredOrder == null || registeredOrder.getDeleted()) {
            return serviceResult.failed("挂号订单不存在");
        }

        return payByMedicalCard(order, registeredOrder);
    }

    /**
     * 取消订单
     *
     * @param doctorId
     * @param orderId
     * @return
     */
    public ServiceResult cancelOrder(int doctorId, int orderId) {
        ServiceResult result = new ServiceResult();
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return result.failed("订单不存在");
        }
        if (order.getDoctorId() != doctorId) {
            return result.failed("订单不存在");
        }

        if (order.getPaymentStatus() == PaymentStatusEnum.Processing.getValue()) {
            return result.failed("您暂时不能取消该订单");
        }

        if (order.getOrderStatus() != OrderStatusEnum.Pending_Payment.getValue()) {
            return result.failed("该订单不能取消");
        }

        order.setOrderStatus(OrderStatusEnum.Cancel.getValue());
        orderRepository.save(order);

        return result.succeed("成功取消订单");
    }

    /**
     * 得到询诊订单
     *
     * @param doctorId
     * @param pageIndex
     * @param pageSize
     * @param name
     * @return
     */
    public PagedList<TreatmentOrderView> getTreatmentOrderList(int doctorId, int pageIndex, int pageSize, String name) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " (doctor_id = ? or union_doctor_id = ?)";
        paramList.add(doctorId);
        paramList.add(doctorId);

        if (!StringHelper.isNullOrEmpty(name)) {
            whereSql += " and (patient_real_name like ? or doctor_real_name like ?)";
            paramList.add(name);
            paramList.add(name);
        }

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", TreatmentOrderView.class, paramList.toArray());
    }

    public PagedList<TreatmentOrderView> getTreatmentOrderListByUserId(int userId, String mobile, int pageIndex, int pageSize) {
        String whereSql = " user_id = ? or (patient_mobile = ? and (payment_status = ? or payment_status = ?))";
        Object[] params = new Object[]{userId, mobile, PaymentStatusEnum.Pending.getValue(), PaymentStatusEnum.Processing.getValue()};
        int[] argTypes = new int[]{Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.INTEGER};

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", TreatmentOrderView.class, params, argTypes);
    }


    /**
     * 获取转诊订单列表
     *
     * @param doctorId
     * @param pageIndex
     * @param pageSize
     * @param name
     * @return
     */
    public PagedList<TransferOrderView> getTransferOrderList(int doctorId, int pageIndex, int pageSize, String name) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " (from_doctor_id = ? or to_doctor_id = ?)";
        paramList.add(doctorId);
        paramList.add(doctorId);

        if (!StringHelper.isNullOrEmpty(name)) {
            whereSql += " and (patient_real_name like ? or to_doctor_name like ? or from_doctor_name like ?)";
            paramList.add(name);
            paramList.add(name);
            paramList.add(name);
        }

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", TransferOrderView.class, paramList.toArray());
    }

    public PagedList<TransferOrderView> getTransferOrderListByUserId(int userId, String mobile, int pageIndex, int pageSize) {
        String whereSql = " (user_id = ? or patient_mobile = ?) and transfer_status & ? = ?";
        Object[] params = new Object[]{userId, mobile, TransferStatusEnum.InformPatient.getValue(), TransferStatusEnum.InformPatient.getValue()};
        int[] argTypes = new int[]{Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.INTEGER};

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", TransferOrderView.class, params, argTypes);
    }

    /**
     * 获取主诊订单列表
     *
     * @param doctorId
     * @param pageIndex
     * @param pageSize
     * @param name
     * @return
     */
    public PagedList<AttendingOrderView> getAttendingOrderList(int doctorId, int pageIndex, int pageSize, String name) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " (from_doctor_id = ? or to_doctor_id = ?)";
        paramList.add(doctorId);
        paramList.add(doctorId);

        if (!StringHelper.isNullOrEmpty(name)) {
            whereSql += " and (patient_real_name like ? or to_doctor_name like ? or from_doctor_name like ?)";
            paramList.add(name);
            paramList.add(name);
            paramList.add(name);
        }

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", AttendingOrderView.class, paramList.toArray());
    }

    public PagedList<AttendingOrderView> getAttendingOrderListByUserId(int userId, String mobile, int pageIndex, int pageSize) {
        String whereSql = " (user_id = ? or (patient_mobile = ? and (payment_status = ? or payment_status = ?)))" +
                " and attending_status & ? = ?";
        Object[] paramList = new Object[]{
                userId, mobile, PaymentStatusEnum.Pending.getValue(), PaymentStatusEnum.Processing.getValue(),
                AttendingStatusEnum.InformPatient.getValue(), AttendingStatusEnum.InformPatient.getValue()};
        int[] argTypes = new int[]{Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER};

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", AttendingOrderView.class, paramList, argTypes);
    }

    /**
     * 结束订单
     *
     * @param orderId
     * @return
     */
    public ServiceResult endOrder(int orderId, int userId) {
        ServiceResult result = new ServiceResult();
        Order order = orderRepository.findById(orderId).orElse(null);
        if (order == null || order.getDeleted()) {
            return result.failed("订单不存在");
        }
        if (order.getDoctorId() != userId) {
            return result.failed("订单不存在");
        }
        //只有支付成功并且已付款的订单，才能结束订单
        if (order.getOrderStatus() == OrderStatusEnum.Already_Paid.getValue()) {
            order.setOrderStatus(OrderStatusEnum.Over.getValue());
            orderRepository.save(order);
            return result.succeed("成功结束订单");
        }
        return result.failed("无法进行该操作");
    }

    /**
     * 得到订单状态
     *
     * @param orderId
     * @return
     */
    public Order getOrderStatus(int orderId) {
        return orderRepository.findById(orderId).orElse(null);
    }

    /**
     * 安排转诊
     *
     * @param doctorId
     * @param orderId
     * @param isArranged
     * @param hospital
     * @param dept
     * @param bed
     * @param date
     * @param period
     * @return
     */
    public ServiceResult arrangeTransfer(int doctorId, int orderId, boolean isArranged, String hospital, String dept, String bed, Date date, int period) {
        ServiceResult result = new ServiceResult();
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return result.failed("订单不存在");
        }

        if (order.getOrderType() != OrderTypeEnum.TRANSFER.getValue()) {
            return result.failed("订单类型不正确");
        }

        Map<String, Object> map = new HashMap<>();
        TransferTreatment transferTreatment = transferTreatmentRepository.findById(order.getBusinessId()).orElse(null);

        if (transferTreatment == null) {
            return result.failed("转诊订单不存在");
        }

        if (transferTreatment.getToDoctorId() != doctorId) {
            return result.failed("您无权给当前订单安排转诊");
        }

        String keyword1 = "";    //自动回复内容

        if (isArranged) {
            //可以安排转诊
            if (StringHelper.isNullOrEmpty(hospital)) {
                return result.failed("医院名称不能为空");
            }

            if (StringHelper.isNullOrEmpty(dept)) {
                return result.failed("科室名称不能为空");
            }

            if (StringHelper.isNullOrEmpty(bed)) {
                bed = "";
//                return result.failed("床位号不能为空");
            }

            if (date == null) {
                return result.failed("转入日期不能为空");
            }

            DatePeriodEnum datePeriod = DatePeriodEnum.valueOf(period);

            if (datePeriod == null) {
                return result.failed("转入时段不正确");
            }

            transferTreatment.setHospitalName(hospital);
            transferTreatment.setDeptName(dept);
            transferTreatment.setBedNumber(bed);
            transferTreatment.setTransferDate(date);
            transferTreatment.setTransferPeriod(period);
            transferTreatment.setTransferStatus(TransferStatusEnum.Accept.getValue());

            map.put("sessionId", transferTreatment.getSessionId());
            map.put("orderId", String.valueOf(orderId));
            result.setData(map);

            keyword1 = String.format("床位信息：\r\n医院：%s\r\n科室：%s\r\n床位号：%s\r\n转入时间：%s %s"
                    , hospital, dept, bed, DateUtil.convertToString(date, "yyyy-MM-dd"), datePeriod.getDisplayName());
        } else {
            //不能安排转诊
            transferTreatment.setTransferStatus(TransferStatusEnum.Refuse.getValue());

            map.put("sessionId", transferTreatment.getSessionId());
            map.put("orderId", String.valueOf(orderId));
            result.setData(map);

            keyword1 = "无法安排，抱歉！";
        }

        transferTreatmentRepository.save(transferTreatment);

        //发送模板消息通知基层医生
        // 收到消息的医生 id
        int receiverDoctorId = Checker.getIntegerValue(transferTreatment.getFromDoctorId());
        int doctorHospitalId = doctorService.getHospitalIdByDoctorId(receiverDoctorId);
        String url;
        String first;
        String remark;
        String keyword2;
        switch (doctorHospitalId) {
            case Constants.NFYYBYFY_HOSPITAL_ID:
                url = urlDefServiceProvider.getByNetDocTransferChatUrl(orderId, receiverDoctorId);
                first = String.format("尊敬的%s医生，您好！%s医生有回复。",
                        transferTreatment.getFromDoctorName(), transferTreatment.getToDoctorName());
                remark = "";
                keyword1 = transferTreatment.getToDoctorName();
                keyword2 = "双向转诊";
                String keyword3 = DateUtil.convertToString(new Date(), "yyyy年MM月dd日 HH:mm");
                weChatMsgProvider.sendByTpl2014(receiverDoctorId, first, remark, "", url, keyword1, keyword2, keyword3);
                break;
            default:
                url = urlDefServiceProvider.getThNetDocTransferChatUrl(orderId, receiverDoctorId);
                first = String.format("尊敬的%s医生，您好！%s医生有回复。",
                        transferTreatment.getFromDoctorName(), transferTreatment.getToDoctorName());
                remark = "";
                keyword2 = DateUtil.convertToString(new Date(), "yyyy年MM月dd日 HH:mm");
                weChatMsgProvider.sendByTpl1031(receiverDoctorId, "", url, first, remark, keyword1, keyword2);
                break;
        }

        return result.succeed("处理成功");
    }


    /**
     * 转诊结果通知用户
     *
     * @param doctorId
     * @param orderId
     * @return
     */
    public ServiceResult notifyTransfer(int doctorId, int orderId, int terminal) {
        ServiceResult result = new ServiceResult();
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return result.failed("订单不存在");
        }

        if (order.getOrderType() != OrderTypeEnum.TRANSFER.getValue()) {
            return result.failed("订单类型不正确");
        }

        if (order.getDoctorId() != doctorId) {
            return result.failed("您无权给当前订单安排转诊");
        }

        TransferTreatment transferTreatment = transferTreatmentRepository.findById(order.getBusinessId()).orElse(null);

        if (transferTreatment == null) {
            return result.failed("转诊订单不存在");
        }

        if (transferTreatment.getTransferStatus() == TransferStatusEnum.Accept.getValue()) {
            //已安排转诊
            int status = transferTreatment.getTransferStatus() | TransferStatusEnum.InformPatient.getValue();
            transferTreatment.setTransferStatus(status);

            transferTreatmentRepository.save(transferTreatment);

            try {
                //短信通知患者
                smsProvider.notifyPatientTransferOrder(transferTreatment.getPatientRealName(), transferTreatment.getPatientMobile(),
                        transferTreatment.getFromDoctorId());

                //发送模板信息通知用户
                String transferDate = getDateString(transferTreatment.getTransferDate(), transferTreatment.getTransferPeriod());
                String url = String.format("https://m.ywtinfo.com/nfywtwe/orderCenter/detail/%d?type=2", order.getId());
                String first = "您的转诊申请已经通过，预约信息为：";
                String remark = String.format("医院：%s，科室：%s，医生：%s，床位：%s，转入时间：%s，请点击查看并确认订单。",
                        transferTreatment.getHospitalName(), transferTreatment.getDeptName(), transferTreatment.getToDoctorName(),
                        transferTreatment.getBedNumber(), transferDate);
                String miniProgram = "";
                int targetTerminal = BizUtil.getAssociatedPatientTerminalValue(terminal);

                String pagePath = String.format(Constants.TH_PATIENT_TRANSFER_DETAIL_URL, orderId);
                miniProgram = BizUtil.getMiniProgramParam(Constants.TH_PATIENT_WXMP_APP_ID, pagePath);

                //南方医务通
                weChatMsgProvider.sendByTpl1018(order.getUserId(), miniProgram, url, first, remark,
                        transferTreatment.getPatientRealName(), transferTreatment.getPatientMobile(), "--");
//                weChatServiceProvider.sendOfficialTplMsgApplication(order.getUserId(), transferTreatment.getPatientRealName(),
//                        order.getPatientMobile(), first, remark, url);

                //医务通互联网医院
                weChatMsgProvider.sendByTpl1030(order.getUserId(), first, remark, miniProgram, "",
                        transferTreatment.getPatientRealName(), order.getPatientMobile(), "--");

                //南方医院太和分院
                weChatMsgProvider.sendByTpl8050(order.getUserId(), miniProgram, "", first, remark,
                        transferTreatment.getPatientRealName(), order.getPatientMobile(), "--");

                //南方医院白云分院
                weChatMsgProvider.sendByTpl2011(order.getUserId(), BizUtil.getMiniProgramParam(Constants.NFYYBYFY_WXMP_APP_ID, pagePath),
                        "", first, remark, transferTreatment.getPatientRealName(), order.getPatientMobile(), "--");
            } catch (Exception e) {
                logger.error("notifyTransfer(): 转诊结果通知用户出错, {}", e.getMessage(), e);
            }

            Map<String, Object> map = new HashMap<>();
            map.put("transfer", transferTreatment);
            return result.succeed("处理成功", map);
        }

        return result.failed("订单状态不正确");
    }


    /**
     * 患者确认转诊订单
     *
     * @param userId
     * @param orderId
     * @param isSelectedAmbulance
     * @return
     */
    public ServiceResult checkTransfer(int userId, int orderId, boolean isSelectedAmbulance) {
        ServiceResult result = new ServiceResult();
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return result.failed("订单不存在");
        }

        if (order.getOrderType() != OrderTypeEnum.TRANSFER.getValue()) {
            return result.failed("订单类型不正确");
        }

        TransferTreatment transferTreatment = transferTreatmentRepository.findById(order.getBusinessId()).orElse(null);

        if (transferTreatment == null) {
            return result.failed("转诊订单不存在");
        }

        User user = userRepository.findById(userId).orElse(null);

        if (user == null || user.getIsDeleted()) {
            return result.failed("用户不存在");
        }

        if (transferTreatment.getTransferStatus() == (TransferStatusEnum.Accept.getValue() | TransferStatusEnum.InformPatient.getValue())) {
            //转诊业务状态为"已安排床位" 并且为 "已通知用户" 时，用户才能进行确认订单状态
            int status = transferTreatment.getTransferStatus();

            if (isSelectedAmbulance) {
                status = status | TransferStatusEnum.SelectAmbulance.getValue();
            }

            status = status | TransferStatusEnum.PatientAffirm.getValue();
            transferTreatment.setTransferStatus(status);

            transferTreatmentRepository.save(transferTreatment);

            if (order.getUserId() < 1) {
                order.setUserId(userId);
                orderRepository.save(order);
            }

            String doctorMobiles = "";
            User fromDoctor = userRepository.findById(transferTreatment.getFromDoctorId()).orElse(null);
            User toDoctor = userRepository.findById(transferTreatment.getToDoctorId()).orElse(null);

            if (fromDoctor != null && !StringHelper.isNullOrEmpty(fromDoctor.getMobile())) {
                doctorMobiles += fromDoctor.getMobile();
            }

            if (toDoctor != null && !StringHelper.isNullOrEmpty(toDoctor.getMobile())) {
                if (!"".equals(doctorMobiles)) {
                    doctorMobiles += "," + toDoctor.getMobile();
                } else {
                    doctorMobiles = toDoctor.getMobile();
                }
            }


//            messageServiceProvider.notifyAfterUserCheckOrder(
//                    transferTreatment.getPatientRealName(), transferTreatment.getHospitalName(), transferTreatment.getDeptName(),
//                    transferTreatment.getBedNumber(), transferDate, doctorMobiles);


            try {
                String transferDate = getDateString(transferTreatment.getTransferDate(), transferTreatment.getTransferPeriod());

                //消息推送
                pushServiceProvider.notifyAfterUserCheckOrder(transferTreatment.getPatientRealName(), transferTreatment.getHospitalName(), transferTreatment.getDeptName(),
                        transferTreatment.getBedNumber(), transferDate, transferTreatment.getFromDoctorId(), transferTreatment.getToDoctorId());

                String url = String.format("https://m.ywtinfo.com/nfywtwe/orderCenter/detail/%d?type=2", order.getId());
                String first = "您的转诊申请已确认，预约信息为：";
                String remark = String.format("医院：%s，科室：%s，医生：%s，床位：%s，转入时间：%s，请按时到%s报到。",
                        transferTreatment.getHospitalName(), transferTreatment.getDeptName(), transferTreatment.getToDoctorName(),
                        transferTreatment.getBedNumber(), transferDate, transferTreatment.getHospitalName());

                //南方医院太和分院
                String pagePath = String.format(Constants.TH_PATIENT_TRANSFER_DETAIL_URL, orderId);
                String miniProgram = BizUtil.getMiniProgramParam(Constants.TH_PATIENT_WXMP_APP_ID, pagePath);
                weChatMsgProvider.sendByTpl8050(order.getUserId(), miniProgram, "", first, remark,
                        transferTreatment.getPatientRealName(), order.getPatientMobile(), "--");
                //南方医务通
                weChatMsgProvider.sendByTpl1018(userId, miniProgram, url, first, remark,
                        transferTreatment.getPatientRealName(), transferTreatment.getPatientMobile(), "--");

//                weChatServiceProvider.sendOfficialTplMsgApplication(
//                        order.getUserId(), transferTreatment.getPatientRealName(),
//                        order.getPatientMobile(), first, remark, url);

                //医务通互联网医院
                weChatMsgProvider.sendByTpl1030(order.getUserId(), first, remark, "", "",
                        transferTreatment.getPatientRealName(), order.getPatientMobile(), "--");

                //南方医院白云分院
                weChatMsgProvider.sendByTpl2011(order.getUserId(), first, remark, "", "",
                        transferTreatment.getPatientRealName(), order.getPatientMobile(), "--");
                // 发送消息到医生端
                int receiverDoctorId = Checker.getIntegerValue(transferTreatment.getToDoctorId());
                int doctorHospitalId = doctorService.getHospitalIdByDoctorId(receiverDoctorId);
                switch (doctorHospitalId) {
                    default:
                        //医务通互联网医院医生版
                        first = String.format("尊敬的医生，您好！%s患者确认了转诊！", transferTreatment.getPatientRealName());
                        remark = "";
                        String strStatus = "确认转诊";
                        url = String.format("%s/thnetdocwe/diagnosis/twoWayChat/%d/%d",
                                bizConfigurer.getYwtHttpsMsiteDomain(), orderId, transferTreatment.getToDoctorId());
                        weChatMsgProvider.sendByTpl1042(transferTreatment.getToDoctorId(), "", url, first, remark,
                                transferTreatment.getPatientRealName(), transferTreatment.getDiagnosis(), strStatus);

                        url = String.format("%s/thnetdocwe/diagnosis/twoWayChat/%d/%d",
                                bizConfigurer.getYwtHttpsMsiteDomain(), orderId, transferTreatment.getFromDoctorId());
                        weChatMsgProvider.sendByTpl1042(transferTreatment.getFromDoctorId(), "", url, first, remark,
                                transferTreatment.getPatientRealName(), transferTreatment.getDiagnosis(), strStatus);
                        break;
                    case Constants.NFYYBYFY_HOSPITAL_ID:
                        first = String.format("尊敬的医生，您好！%s患者确认了转诊！", transferTreatment.getPatientRealName());
                        remark = "";
                        strStatus = "确认转诊";
                        url = String.format("%s/nfyybyfydocwe/diagnosis/twoWayChat/%d/%d",
                                bizConfigurer.getYwtHttpsMsiteDomain(), orderId, transferTreatment.getToDoctorId());
                        weChatMsgProvider.sendByTpl2014(transferTreatment.getToDoctorId(), first, remark, "",
                                url, transferTreatment.getPatientRealName(), transferTreatment.getDiagnosis(), strStatus);

                        url = String.format("%s/nfyybyfydocwe/diagnosis/twoWayChat/%d/%d",
                                bizConfigurer.getYwtHttpsMsiteDomain(), orderId, transferTreatment.getFromDoctorId());
                        weChatMsgProvider.sendByTpl2014(transferTreatment.getFromDoctorId(), first, remark, "",
                                url, transferTreatment.getPatientRealName(), transferTreatment.getDiagnosis(), strStatus);
                        break;
                }
            } catch (Exception e) {
                logger.error("checkTransfer(): 发送通知消息出错, {}", e.getMessage(), e);
            }

            return result.succeed("处理成功");
        }

        return result.failed("处理失败，订单状态不符合");
    }

    /**
     * 能否安排主诊
     *
     * @param orderId
     * @param doctorId
     * @return
     */
    public ServiceResult arrangeAttending(int orderId, int doctorId, int isArranged) {
        ServiceResult result = new ServiceResult();
        //得到订单对象
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return result.failed("该订单不存在");
        }

        AttendingTreatment attendingTreatment = attendingTreatmentRepository.findById(order.getBusinessId()).orElse(null);

        if (attendingTreatment.getAttendingStatus() != null) {
            return result.failed("订单状态不正确");
        }

        Map<String, Object> map = new HashMap<>();

        //能否安排转诊（0-无法安排，1-可以安排）
        if (isArranged == 1) {
            attendingTreatment.setAttendingStatus(AttendingStatusEnum.Accept.getValue());

            map.put("sessionId", attendingTreatment.getSessionId());
            map.put("orderId", String.valueOf(orderId));
        } else {
            attendingTreatment.setAttendingStatus(AttendingStatusEnum.Refuse.getValue());
            map.put("sessionId", attendingTreatment.getSessionId());
            map.put("orderId", String.valueOf(orderId));
        }

        attendingTreatment.setUpdateTime(new Date());
        attendingTreatmentRepository.save(attendingTreatment);

        result.setData(map);
        return result.succeed("操作成功");
    }

    /**
     * 主诊信息通知患者
     *
     * @param orderId
     * @param doctorId
     * @param amount
     * @param date
     * @param period
     * @return
     */
    public ServiceResult notifyAttending(int orderId, int doctorId, double amount, long date, int period) {
        ServiceResult result = new ServiceResult();
        if (amount <= 0 || date <= 0 || period <= 0 || period >= 4) {
            result.failed("参数错误");
        }

        //得到订单对象
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return result.failed("该订单不存在");
        }

        AttendingTreatment attendingTreatment = attendingTreatmentRepository.findById(order.getBusinessId()).orElse(null);

        if (order.getDoctorId() != doctorId)
            return result.failed("没有操作此订单的权限");

        if (attendingTreatment.getAttendingStatus() != AttendingStatusEnum.Accept.getValue()) {
            return result.failed("订单状态不正确");
        }

        BigDecimal orderAmount = BigDecimal.valueOf(amount);
        int status = attendingTreatment.getAttendingStatus() | AttendingStatusEnum.InformPatient.getValue();

        attendingTreatment.setAmount(orderAmount);
        attendingTreatment.setAttendingDate(new Date(date));
        attendingTreatment.setAttendingPeriod(period);
        attendingTreatment.setUpdateTime(new Date());
        attendingTreatment.setAttendingStatus(status);
        attendingTreatmentRepository.save(attendingTreatment);

        order.setOrderAmount(orderAmount);
        orderRepository.save(order);

        smsProvider.notifyPatientAttendingOrder(attendingTreatment.getPatientRealName(), order.getPatientMobile());

        Map<String, Object> map = new HashMap<>();
        map.put("attendingTreatment", attendingTreatment);

        return result.succeed("操作成功", map);
    }

    /**
     * 创建订单评论
     *
     * @param userId
     * @param orderId
     * @param score
     * @param content
     * @return
     */
    public ServiceResult createOrderEvaluation(int userId, int orderId, int score, String content) {
        ServiceResult result = new ServiceResult();

        //得到订单对象
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return result.failed("该订单不存在");
        }

        if (order.getUserId() != userId) {
            return result.failed("没有操作此订单的权限");
        }

        if (order.getOrderType() == OrderTypeEnum.ATTENDING.getValue()) {
            //主诊
            AttendingTreatment attending = attendingTreatmentRepository.findById(order.getBusinessId()).orElse(null);

            if (attending == null || attending.getDeleted()) {
                return result.failed("主诊订单不存在");
            }

            if ((attending.getAttendingStatus() & AttendingStatusEnum.PatientEvaluate.getValue()) == AttendingStatusEnum.PatientEvaluate.getValue()) {
                return result.failed("订单已评价，请不要重复评价");
            }

            if ((attending.getAttendingStatus() & AttendingStatusEnum.AlreadyPay.getValue()) != AttendingStatusEnum.AlreadyPay.getValue()) {
                return result.failed("该订单暂时不能评价");
            }

            //生成评价记录
            genOrderEvaluation(orderId, order.getOrderNo(), content, score, userId, attending.getToDoctorId());
            genOrderEvaluation(orderId, order.getOrderNo(), content, score, userId, attending.getFromDoctorId());

            attending.setAttendingStatus(attending.getAttendingStatus() | AttendingStatusEnum.PatientEvaluate.getValue());
            attendingTreatmentRepository.save(attending);

            return result.succeed("处理成功");
        }

        if (order.getOrderType() == OrderTypeEnum.TRANSFER.getValue()) {
            //转诊
            TransferTreatment transfer = transferTreatmentRepository.findById(order.getBusinessId()).orElse(null);

            if (transfer == null || transfer.getIs_deleted()) {
                return result.failed("转诊订单不存在");
            }

            if ((transfer.getTransferStatus() & TransferStatusEnum.PatientEvaluate.getValue()) == TransferStatusEnum.PatientEvaluate.getValue()) {
                return result.failed("订单已评价，请不要重复评价");
            }

            if ((transfer.getTransferStatus() & TransferStatusEnum.PatientAffirm.getValue()) != TransferStatusEnum.PatientAffirm.getValue()) {
                return result.failed("该订单暂时不能评价");
            }

            //生成评价记录
            genOrderEvaluation(orderId, order.getOrderNo(), content, score, userId, transfer.getToDoctorId());
            genOrderEvaluation(orderId, order.getOrderNo(), content, score, userId, transfer.getFromDoctorId());

            transfer.setTransferStatus(transfer.getTransferStatus() | TransferStatusEnum.PatientEvaluate.getValue());
            transferTreatmentRepository.save(transfer);

            return result.succeed("处理成功");
        }

        if (order.getOrderType() == OrderTypeEnum.CONSULT.getValue()) {
            //咨询
            ConsultOrder consultOrder = consultOrderRepository.findById(order.getBusinessId()).orElse(null);

            if (consultOrder == null || consultOrder.getDeleted()) {
                return result.failed("咨询订单不存在");
            }

            if ((consultOrder.getConsultStatus() & ConsultStatusEnum.Evaluate.getValue()) == ConsultStatusEnum.Evaluate.getValue()) {
                return result.failed("订单已评价，请不要重复评价");
            }

            if ((consultOrder.getConsultStatus() & ConsultStatusEnum.End.getValue()) != ConsultStatusEnum.End.getValue()) {
                return result.failed("该订单暂时不能评价");
            }

            //生成评价记录
            genOrderEvaluation(orderId, order.getOrderNo(), content, score, userId, consultOrder.getDoctorId());

            consultOrder.setConsultStatus(consultOrder.getConsultStatus() | ConsultStatusEnum.Evaluate.getValue());
            consultOrderRepository.save(consultOrder);

            return result.succeed("处理成功");
        }

        if (order.getOrderType() == OrderTypeEnum.FOLLOWUP.getValue()) {
            return createFollowUpEvaluation(order, content, score);
        }
        if (order.getOrderType() == OrderTypeEnum.PRESCRIPTION.getValue()) {
            return createPrescriptionEvaluation(order, content, score);
        }

        //会诊
        Treatment treatment = treatmentRepository.findById(order.getBusinessId()).orElse(null);

        if (treatment == null || treatment.isDeleted()) {
            return result.failed("会诊订单不存在");
        }

        // 判断是否已评价
        int treatmentStatus = Checker.getIntegerValue(treatment.getTreatmentStatus());
        if ((treatmentStatus & TreatmentStatusEnum.Evaluate.getValue()) == TreatmentStatusEnum.Evaluate.getValue()) {
            return result.failed("订单不能重复评论");
        }

        // 已结算（未评价）状态也给予其评价的功能
        boolean informPatientBoolean = (treatmentStatus & TreatmentStatusEnum.InformPatient.getValue()) == TreatmentStatusEnum.InformPatient.getValue()
                && treatmentStatus < 2 * TreatmentStatusEnum.InformPatient.getValue();
        boolean settlementBoolean = (treatmentStatus & TreatmentStatusEnum.Settlement.getValue()) == TreatmentStatusEnum.Settlement.getValue()
                && treatmentStatus < 2 * TreatmentStatusEnum.Settlement.getValue();
        if (!informPatientBoolean && !settlementBoolean) {
            return result.failed("订单状态不正确");
        }

        //生成评价记录
        genOrderEvaluation(orderId, order.getOrderNo(), content, score, userId, treatment.getDoctorId());
        genOrderEvaluation(orderId, order.getOrderNo(), content, score, userId, treatment.getUnionDoctorId());

        if (order.getOrderStatus() != OrderStatusEnum.Settlement.getValue()) {
            order.setOrderStatus(OrderStatusEnum.Evaluate.getValue());
            orderRepository.save(order);
        }

        treatmentStatus = treatmentStatus | TreatmentStatusEnum.Evaluate.getValue();
        treatment.setTreatmentStatus(treatmentStatus);
        treatmentRepository.save(treatment);
        return result.succeed("操作成功");
    }

    private OrderEvaluation genOrderEvaluation(int orderId, String orderNo, String content, int score, int userId, int doctorId) {
        OrderEvaluation orderEvaluation = new OrderEvaluation();

        orderEvaluation.setContent(content);
        orderEvaluation.setCreateTime(new Date());
        orderEvaluation.setId(idGenerator.generateOrderEvaluationId());
        orderEvaluation.setOrderNo(orderNo);
        orderEvaluation.setOrderId(orderId);
        orderEvaluation.setScore(score);
        orderEvaluation.setUserId(userId);
        orderEvaluation.setType(1);
        orderEvaluation.setDoctorId(doctorId);
        orderEvaluationRepository.save(orderEvaluation);

        return orderEvaluation;
    }

    private ServiceResult createFollowUpEvaluation(Order order, String content, int score) {
        ServiceResult serviceResult = new ServiceResult();
        FollowUpOrder followUpOrder = followUpOrderRepository.findById(order.getBusinessId()).orElse(null);

        if (followUpOrder == null || followUpOrder.getDeleted()) {
            return serviceResult.failed("随访记录不存在");
        }

        if ((followUpOrder.getFollowUpStatus() & FollowUpStatusEnum.Evaluate.getValue()) == FollowUpStatusEnum.Evaluate.getValue()) {
            return serviceResult.failed("订单已评价，请不要重复评价");
        }

        boolean isEnd = false; //随访是否结束
        if ((followUpOrder.getFollowUpStatus() & FollowUpStatusEnum.End.getValue()) == FollowUpStatusEnum.End.getValue()) {
            isEnd = true;
        } else {
            Calendar ca1 = Calendar.getInstance();
            Calendar ca2 = Calendar.getInstance();

            ca1.setTime(followUpOrder.getCreateTime());
            ca1.add(Calendar.DATE, 1);

            if (ca2.after(ca1)) {
                //超过24h，随访自动结束
                isEnd = true;
            }
        }

        if (isEnd) {
            genOrderEvaluation(order.getId(), order.getOrderNo(), content, score, order.getUserId(), followUpOrder.getDoctorId());
            followUpOrder.setFollowUpStatus(followUpOrder.getFollowUpStatus() | FollowUpStatusEnum.Evaluate.getValue());
            followUpOrderRepository.save(followUpOrder);

            return serviceResult.succeed("处理成功");
        }

        return serviceResult.failed("该随访尚未结束，暂不能评价。");
    }

    private ServiceResult createConsultEvaluation(Order order, String content, int score) {
        ServiceResult result = new ServiceResult();
        ConsultOrder consultOrder = consultOrderRepository.findById(order.getBusinessId()).orElse(null);

        if (consultOrder == null || consultOrder.getDeleted()) {
            return result.failed("咨询订单不存在");
        }

        if ((consultOrder.getConsultStatus() & ConsultStatusEnum.Evaluate.getValue()) == ConsultStatusEnum.Evaluate.getValue()) {
            return result.failed("订单已评价，请不要重复评价");
        }

        boolean isEnd = false; //随访是否结束

        if ((consultOrder.getConsultStatus() & ConsultStatusEnum.End.getValue()) == ConsultStatusEnum.End.getValue()) {
            isEnd = true;
        } else {
            Calendar ca1 = Calendar.getInstance();
            Calendar ca2 = Calendar.getInstance();

            ca1.setTime(consultOrder.getCreateTime());
            ca1.add(Calendar.DATE, 2);

            if (ca2.after(ca1)) {
                //超过48h，咨询自动结束
                isEnd = true;
            }
        }

        if (isEnd) {
            //生成评价记录
            genOrderEvaluation(order.getId(), order.getOrderNo(), content, score, order.getUserId(), consultOrder.getDoctorId());
            consultOrder.setConsultStatus(consultOrder.getConsultStatus() | ConsultStatusEnum.Evaluate.getValue());
            consultOrderRepository.save(consultOrder);

            return result.succeed("处理成功");
        }
        return result.failed("该随访尚未结束，暂不能评价。");
    }

    private ServiceResult createPrescriptionEvaluation(Order order, String content, int score) {
        ServiceResult serviceResult = new ServiceResult();

        try {
            CommentPrescriptionRequest req = CommentPrescriptionRequest.newBuilder()
                    .setPreId(order.getBusinessId())
                    .build();
            CommentPrescriptionResponse res = drugServiceBlockingStub.commentPrescription(req);

            if (res.getCode() == ResultCode.SUCCEED_VALUE) {
                genOrderEvaluation(order.getId(), order.getOrderNo(), content, score, order.getUserId(), order.getDoctorId());
                return serviceResult.succeed("处理成功");
            }

            return serviceResult.failed(res.getMsg());
        } catch (Exception e) {
            logger.error("createPrescriptionEvaluation(): {}", e.getMessage(), e);
            return serviceResult.failed(e.getMessage());
        }
    }

    @Deprecated
    public ServiceResult wxPayCallback(
            String returnCode, String resultCode, String outTradeNo, String transactionId, int totalFee,
            int cashFee, String attach, String bankType, String timeEnd, String errCode, String errCodeDes) {
        ServiceResult serviceResult = new ServiceResult();

        if ("SUCCESS".equals(returnCode)) {
//            Order order = orderRepository.getOrderByOrderNo(outTradeNo);
//
//            if (order == null) {
//                return serviceResult.failed("订单不存在");
//            }
//
//            int orderAmount = (int) (order.getOrderAmount().doubleValue() * 100.0);
//
//            if (orderAmount != totalFee) {
//                return serviceResult.failed("支付金额与订单金额不一致");
//            }

            // 防止重复回调
            double paymentAmount = totalFee / 100.0;
//            String[] attachArr = attach.split("&");
            String paymentNo = outTradeNo;  //attachArr[0].split("=")[1];

            String sql =
                    "update order_payment set " +
                            "payment_status = ?, " +
                            "callback_time = now(), " +
                            "result_code = ?, " +
                            "transaction_id = ?, " +
                            "cash_fee = ?, " +
                            "attach = ?, " +
                            "bank_type = ?, " +
                            "time_end = ?, " +
                            "err_code = ?, " +
                            "err_code_des = ? " +
                            "where payment_no = ? and payment_amount = ? and callback_time is null";

            PaymentStatusEnum paymentStatusEnum = "SUCCESS".equals(resultCode) ?
                    PaymentStatusEnum.Success :
                    PaymentStatusEnum.Failed;

            Object[] params = new Object[]
                    {
                            paymentStatusEnum.getValue(),
//                            new Date(),
                            resultCode,
                            transactionId,
                            cashFee,
                            attach,
                            bankType,
                            timeEnd,
                            errCode,
                            errCodeDes,
                            paymentNo,
                            paymentAmount
                    };
            int[] types = new int[]
                    {
                            Types.INTEGER,
//                            Types.DATE,
                            Types.VARCHAR,
                            Types.VARCHAR,
                            Types.INTEGER,
                            Types.VARCHAR,
                            Types.VARCHAR,
                            Types.VARCHAR,
                            Types.VARCHAR,
                            Types.VARCHAR,
                            Types.VARCHAR,
                            Types.DOUBLE
                    };

            int count = jdbcTemplate.update(sql, params, types);

            if (count == 0) {
                return serviceResult.failed("重复回调或支付金额与订单金额不一致");
            }

            OrderPayment payment = orderPaymentRepository.findByPaymentNo(paymentNo);
            Order order = orderRepository.findById(payment.getOrderId()).orElse(null);

            if ("SUCCESS".equals(resultCode)) {
                //支付成功，更新订单状态
                order.setPaymentStatus(PaymentStatusEnum.Success.getValue());

                if (Checker.getIntegerValue(order.getUserId()) <= 0) {
                    //订单表关联userId
                    order.setUserId(payment.getUserId());
                }

                if (order.getOrderType() == OrderTypeEnum.ATTENDING.getValue()) {
                    AttendingTreatment attendingTreatment = getAttendingTreatmentById(order.getBusinessId());

                    if (attendingTreatment != null) {
                        attendingTreatment.setAttendingStatus(attendingTreatment.getAttendingStatus() | AttendingStatusEnum.AlreadyPay.getValue());
                        attendingTreatmentRepository.save(attendingTreatment);

                        String attendingDate = DateUtil.convertToString(attendingTreatment.getAttendingDate(), "yyyy年MM月dd日");
                        DatePeriodEnum datePeriodEnum = DatePeriodEnum.valueOf(attendingTreatment.getAttendingPeriod());

                        if (datePeriodEnum != null) {
                            attendingDate += datePeriodEnum.getDisplayName();
                        }

                        Map<String, Object> map = new HashMap<>();
                        map.put("patient", attendingTreatment.getPatientRealName());
                        map.put("attendingDate", attendingDate);
                        map.put("toDoctorId", attendingTreatment.getToDoctorId());
                        map.put("fromDoctorId", attendingTreatment.getFromDoctorId());
                        map.put("type", order.getOrderType());
                        map.put("orderId", order.getId());
                        map.put("prepayId", order.getPrepayId());
                        map.put("userId", payment.getUserId());

                        serviceResult.setData(map);

                    }


                } else if (order.getOrderType() == OrderTypeEnum.TREATMENT.getValue()) {
                    Treatment treatment = getTreatmentById(order.getBusinessId());
                    treatment.setTreatmentStatus(TreatmentStatusEnum.Paid.getValue());

                    if (Checker.getIntegerValue(treatment.getUserId()) <= 0) {
                        treatment.setUserId(payment.getUserId());   //关联userId
                    }

                    treatmentRepository.save(treatment);

                    //关联userId
                    String updateSql = String.format("update patient set user_id = %d where id = %d and user_id <= 0",
                            payment.getUserId(), treatment.getId());
                    jdbcTemplate.execute(updateSql);

                    order.setOrderStatus(OrderStatusEnum.Already_Paid.getValue());

                    //互联网医院v1.0.4，南方医务通”原来预约挂号的微信模板消息保留，其他的去掉。 2018-11-14
//                    weChatServiceProvider.sendOfficialTplMsgPaid(payment.getUserId(), "你好，远程会诊订单支付成功！",
//                            payment.getOrderNo(), totalFee, "", "");
                } else if (order.getOrderType() == OrderTypeEnum.CONSULT.getValue()) {
                    //咨询
                    ConsultOrder consultOrder = getConsultOrder(order.getBusinessId());
                    consultOrder.setPaymentStatus(PaymentStatusEnum.Success.getValue());
                    consultOrder.setConsultStatus(ConsultStatusEnum.Paid.getValue());
                    consultOrder.setUpdateTime(new Date());

                    consultOrderRepository.save(consultOrder);

                    try {
                        //短信通知
                        User user = userRepository.findById(consultOrder.getDoctorId()).orElse(null);
                        smsProvider.notifyAfterCreateConsultOrder(user.getRealname(), consultOrder.getName(), user.getMobile(),
                                user.getId());

                        //消息推送
                        pushServiceProvider.notifyAfterUserPaidConsultOrder(consultOrder.getName(), consultOrder.getDoctorId());

                        //互联网医院v1.0.4，“我的工作站”原来的，“问诊”、“处方”、“远程会诊”、“双向转诊”、“药事快讯“微信模板消息去掉。2018-11-15
                        //推送消息到医生端公众号
                        //根据创建订单时记录的terminal，指定推送消息到哪个医生版terminal
//                        int targetTerminal = BizUtil.getAssociatedDoctorTerminalValue(order.getTerminal());
//                        String url = targetTerminal == TerminalEnum.TAI_HE_INTERNET_HOSPITAL_DOCTOR_WX_OFFICIAL.getValue() ?
//                                String.format(Constants.TH_NET_DOCTOR_CONSULT_CHAT_URL, order.getId()) :
//                                String.format(Constants.DOCTOR_CONSULT_CHAT_URL, order.getId());
//                        weChatProvider.notifyDoctorConsultPaid(user.getId(), consultOrder.getName(),
//                                SexEnum.getSexDisplayName(consultOrder.getSex()), consultOrder.getAge(),
//                                consultOrder.getDescription(), url);
                    } catch (Exception e) {
                        logger.error("咨询订单短信通知，wxPayCallback(): {}", e.getMessage(), e);
                    }
                } else if (order.getOrderType() == OrderTypeEnum.ADDITIONAL_REGISTRATION.getValue()) {
                    AdditionalRegistration registration = additionalRegistrationRepository.findById(order.getBusinessId()).orElse(null);
                    registration.setPaymentStatus(PaymentStatusEnum.Success.getValue());
                    registration.setStatus(AdditionalRegistrationStatusEnum.Paid.getValue());
                    registration.setUpdateTime(new Date());

                    additionalRegistrationRepository.save(registration);

                    String remark = String.format("%s，您好！已经在%s%s给您加号。请准时前往%s，直接找到我，并出示本条微信消息作为加号凭证。",
                            registration.getName(),
                            DateUtil.convertToString(registration.getScheduleDate(), "yyyy年MM月dd日"),
                            registration.getScheduleTime() == 1 ? "上午" : registration.getScheduleTime() == 2 ? "下午" : "晚上",
                            registration.getScheduleAddress());

                    Map<String, Object> map = new HashMap<>();
                    map.put("doctorId", registration.getDoctorId());
                    map.put("type", order.getOrderType());
                    map.put("orderId", order.getId());
                    map.put("prepayId", order.getPrepayId());
                    map.put("userId", payment.getUserId());
                    map.put("remark", remark);

                    serviceResult.setData(map);
                }

            } else {
                // 支付失败
                order.setPaymentStatus(PaymentStatusEnum.Failed.getValue());
            }

            orderRepository.save(order);
            return serviceResult.succeed("回调处理成功");
        }

        return serviceResult.failed("通信失败");
    }

    /**
     * 生成支付流水
     *
     * @param orderId
     * @param userId
     * @param paymentStatus
     * @param prepayId
     * @return
     */
    public ServiceResult updateOrderPaymentStatus(int orderId, int userId, int paymentStatus, String prepayId, String paymentNo) {
        ServiceResult result = new ServiceResult();
        Order order = orderRepository.findById(orderId).orElse(null);
        order.setPrepayId(prepayId);

        orderRepository.save(order);

        int id = idGenerator.genOrderPaymentId();
        OrderPayment payment = new OrderPayment();
        payment.setId(id);
        payment.setOrderId(order.getId());
        payment.setOrderNo(order.getOrderNo());
        payment.setPaymentNo(paymentNo);
        payment.setUserId(userId);
        payment.setPaymentChannel(PaymentChannelEnum.WeChat.getValue());
        payment.setPaymentStatus(PaymentStatusEnum.Pending.getValue());
        payment.setOrderAmount(order.getOrderAmount());
        payment.setPaymentAmount(order.getOrderAmount());
        payment.setCreateTime(new Date());
        payment.setDeleted(false);
        payment.setPrepayId(prepayId);

        orderPaymentRepository.save(payment);

        return result.succeed("处理成功");
    }

    public PagedList<Report> getReportListByUserId(int userId, int pageIndex, int pageSize) {
        String whereSql = " user_id = ?";
        Object[] params = new Object[]{userId};

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", Report.class, params);
    }

    /**
     * 创建报告
     *
     * @param orderId
     * @param orderNo
     * @param sessionId
     * @param fileKey
     * @param fileSaveMode
     * @param fromDoctorId
     * @param toDoctorId
     * @param userId
     * @param pages
     * @param total
     * @param suggestion
     * @return
     */
    public ServiceResult createReport(int orderId, String orderNo, String sessionId, String fileKey, int fileSaveMode,
                                      int fromDoctorId, int toDoctorId, int userId, int pages, int total, String suggestion) {
        ServiceResult serviceResult = new ServiceResult();

        Report report = new Report();
        report.setId(idGenerator.genReportId());
        report.setCreateTime(new Date());
        report.setFileKey(fileKey);
        report.setFileSaveMode(fileSaveMode);
        report.setFromDoctorId(fromDoctorId);
        report.setOrderId(orderId);
        report.setOrderNo(orderNo);
        report.setSessionId(sessionId);
        report.setToDoctorId(toDoctorId);
        report.setUserId(userId);
        report.setPages(pages);
        report.setTotal(total);
        report.setSuggestion(suggestion);

        reportRepository.save(report);

        return serviceResult.succeed("处理成功");
    }

    public Report getReport(int reportId) {
        return reportRepository.findById(reportId).orElse(null);
    }

    public List<ServicePackage> getServicePackageList(int type) {
        return servicePackageRepository.getServicePackageList(type);
    }

    public TreatmentReport saveTreatmentReport(TreatmentReport report) {
        report.setId(idGenerator.genTreatmentReportId());
        report.setStatus(TreatmentReportStatusEnum.Pending.getValue());
        report.setCreateTime(new Date());
        report.setDeleted(false);
        report.setFileKey(StringHelper.getUUIDWithoutHyphen());

        treatmentReportRepository.save(report);

        try {
            BufferedImage image = ImageUtil.graphicsGeneration(report.getName(), SexEnum.getSexDisplayName(report.getSex()), report.getAge(), report.getFromHospital(), report.getToHospital(),
                    report.getToDoctorName(), report.getToDoctorTitle(), report.getDiagnosis(), report.getSuggestion(), report.getSign());
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageIO.write(image, "png", out);
            fileProvider.uploadFile(Constants.TREATMENT_REPORT_ALI_PATH, report.getFileKey(), out.toByteArray());


        } catch (Exception e) {
            logger.error("saveTreatmentReport(){}", e.getMessage());
        }

        return report;
    }

    /**
     * 返回远程会诊报告图片二进制流
     *
     * @param orderId
     * @return
     */
    public byte[] getTreatmentReportByte(int orderId) {
        TreatmentReport report = treatmentReportRepository.getReportByOrderId(orderId);

        if (report != null && !report.getDeleted()) {
            String key = Constants.TREATMENT_REPORT_ALI_PATH + "/" + report.getFileKey();
            return fileProvider.readFile(key);
        }

        return null;
    }

    /**
     * 通知患者已生成会诊报告
     *
     * @param orderId
     * @return
     */
    public ServiceResult notifyTreatmentReport(int orderId, int doctorId) {
        ServiceResult serviceResult = new ServiceResult();
        Order order = getOrderById(orderId);

        if (order == null || order.getDeleted()) {
            return serviceResult.failed("订单不存在");
        }

        TreatmentReport report = treatmentReportRepository.getReportByOrderId(orderId);

        if (report == null || report.getDeleted()) {
            return serviceResult.failed("报告不存在");
        }

        if (report.getFromDoctorId() != doctorId) {
            return serviceResult.failed("非法操作");
        }

        report.setStatus(TreatmentReportStatusEnum.Notified.getValue());
        treatmentReportRepository.save(report);

        order.setOrderStatus(OrderStatusEnum.InformPatient.getValue());
        orderRepository.save(order);

        String sql = String.format("update treatment set treatment_status = treatment_status | %d where id = %d",
                TreatmentStatusEnum.InformPatient.getValue(), order.getBusinessId());
        jdbcTemplate.update(sql);

        try {
            //发送短信通知用户
            smsProvider.notifyPatientTreatmentReport(report.getName(), order.getPatientMobile(), report.getFromDoctorId());

            //互联网医院v1.0.4，南方医务通”原来预约挂号的微信模板消息保留，其他的去掉。 2018-11-14
            //发送模板消息通知用户
//            weChatServiceProvider.sendOfficialTplMsgReport(
//                    report.getUserId(), order.getCreateTime(), report.getName(), report.getToDoctorName(), report.getToDoctorTitle(),
//                    String.format("https://m.ywtinfo.com/nfywtwe/report/detail/%d", report.getOrderId()));

            String pagePath = String.format(Constants.TH_PATIENT_REPORT_URL, report.getOrderId());
            String miniProgram = BizUtil.getMiniProgramParam(Constants.TH_PATIENT_WXMP_APP_ID, pagePath);
            String url = "";
            String first = "您好，您的远程会诊专家报告生成！";
            String remark = "请点击查看详情";
            String keyword1 = DateUtil.convertToString(order.getCreateTime(), "yyyy年MM月dd日 HH:mm:ss");
            String keyword2 = report.getName();
            String keyword3 = String.format("%s %s", report.getToDoctorName(), report.getToDoctorTitle());
            weChatMsgProvider.sendByTpl1035(report.getUserId(), miniProgram, url, first, remark, keyword1, keyword2, keyword3);

            //南方医院太和分院
            weChatMsgProvider.sendByTpl8052(report.getUserId(), miniProgram, url, first, remark, keyword1, keyword2, keyword3);

            //南方医务通
            weChatMsgProvider.sendByTpl1022(report.getUserId(), miniProgram, url, first, remark, keyword1, keyword2, keyword3);

            // 白云分院
            weChatMsgProvider.sendByTpl2012(report.getUserId(), BizUtil.getMiniProgramParam(Constants.NFYYBYFY_WXMP_APP_ID, pagePath),
                    url, first, remark, String.format("%s医生", report.getToDoctorName()), report.getName(), "--",
                    DateUtil.convertToString(order.getCreateTime()));
        } catch (Exception e) {
            logger.error("notifyTreatmentReport(): 发送信息通知用户出错, {}", e.getMessage(), e);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("report", report);
        return serviceResult.succeed("处理成功", map);
    }

    public void saveTreatment(Treatment treatment) {
        treatmentRepository.save(treatment);
    }

    public void saveOrder(Order order) {
        orderRepository.save(order);
    }

    public OrderCommonInfo getOrderCommonInfo(int orderId) {
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return null;
        }

        OrderCommonInfo orderCommonInfo = new OrderCommonInfo();
        orderCommonInfo.setOrderId(order.getId());
        orderCommonInfo.setAmount(order.getOrderAmount());
        orderCommonInfo.setOrderNo(order.getOrderNo());
        orderCommonInfo.setCreateTime(order.getCreateTime());
        orderCommonInfo.setPaymentStatus(order.getPaymentStatus());
        orderCommonInfo.setStatus(order.getOrderStatus());
        orderCommonInfo.setUserId(order.getUserId());
        orderCommonInfo.setOrderType(Checker.getIntegerValue(order.getOrderType()));
        orderCommonInfo.setOrderTitle(Checker.getStringValue(order.getTitle()));

        int fromDoctorId = 0;
        int toDoctorId = 0;
        int patientId = 0;
        String patientName = "";

        if (order.getOrderType() == OrderTypeEnum.TREATMENT.getValue()) {
            Treatment treatment = treatmentRepository.findById(order.getBusinessId()).orElse(null);

            if (treatment != null) {
                fromDoctorId = Checker.getIntegerValue(treatment.getDoctorId());
                toDoctorId = Checker.getIntegerValue(treatment.getUnionDoctorId());
                patientId = Checker.getIntegerValue(treatment.getPatientId());
                patientName = Checker.getStringValue(treatment.getPatientRealName());
            }
        } else if (order.getOrderType() == OrderTypeEnum.TRANSFER.getValue()) {
            TransferTreatment transfer = transferTreatmentRepository.findById(order.getBusinessId()).orElse(null);

            if (transfer != null) {
                fromDoctorId = Checker.getIntegerValue(transfer.getFromDoctorId());
                toDoctorId = Checker.getIntegerValue(transfer.getToDoctorId());
                patientId = Checker.getIntegerValue(transfer.getPatientId());
                patientName = Checker.getStringValue(transfer.getPatientRealName());
            }
        } else if (order.getOrderType() == OrderTypeEnum.ATTENDING.getValue()) {
            AttendingTreatment attending = attendingTreatmentRepository.findById(order.getBusinessId()).orElse(null);

            if (attending != null) {
                fromDoctorId = Checker.getIntegerValue(attending.getFromDoctorId());
                toDoctorId = Checker.getIntegerValue(attending.getToDoctorId());
                patientId = Checker.getIntegerValue(attending.getPatientId());
                patientName = Checker.getStringValue(attending.getPatientRealName());
            }
        }

        orderCommonInfo.setFromDoctorId(fromDoctorId);
        orderCommonInfo.setToDoctorId(toDoctorId);
        orderCommonInfo.setPatientId(patientId);
        orderCommonInfo.setPatientName(patientName);

        return orderCommonInfo;
    }

    public PagedList<TreatmentReport> getTreatmentReportList(int userId, int pageIndex, int pageSize) {
        String whereSql = " user_id = ? and status = 1";
        Object[] params = new Object[]{userId};

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", TreatmentReport.class, params);
    }

    /**
     * 用户确认主诊订单状态，相当于 2.0.3 版本的支付功能
     *
     * @param userId
     * @param orderId
     * @return
     */
    public ServiceResult checkAttending(int userId, int orderId) {
        ServiceResult result = new ServiceResult();
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return result.failed("订单不存在");
        }

        if (order.getOrderType() != OrderTypeEnum.ATTENDING.getValue()) {
            return result.failed("订单类型不正确");
        }

        AttendingTreatment attendingTreatment = attendingTreatmentRepository.findById(order.getBusinessId()).orElse(null);

        if (attendingTreatment == null) {
            return result.failed("订单不存在");
        }

        User user = userRepository.findById(userId).orElse(null);

        if (user == null || user.getIsDeleted()) {
            return result.failed("用户不存在");
        }

        if (attendingTreatment.getAttendingStatus() == (AttendingStatusEnum.Accept.getValue() | AttendingStatusEnum.InformPatient.getValue())) {
            //会诊业务状态为"同意" 并且为 "已通知用户" 时，用户才能进行确认订单状态
            attendingTreatment.setAttendingStatus(attendingTreatment.getAttendingStatus() | AttendingStatusEnum.AlreadyPay.getValue());

            attendingTreatmentRepository.save(attendingTreatment);

            if (order.getUserId() < 1) {
                order.setUserId(userId);
                orderRepository.save(order);
            }

            Map<String, Object> map = new HashMap<>();
            map.put("attendingTreatment", attendingTreatment);

            return result.succeed("处理成功", map);
        }

        return result.failed("处理失败，订单状态不符合");
    }

    public String getAttendingStatusName(AttendingTreatment attendingTreatment) {
        Calendar ca2 = Calendar.getInstance();

        if (attendingTreatment.getAttendingStatus() == null) {
            Calendar ca1 = Calendar.getInstance();
            ca1.setTime(attendingTreatment.getCreateTime());
            ca1.add(Calendar.DATE, 1);

            if (ca2.after(ca1)) {
                //医生24h内没有收到回复
                return "已结束";
            }
        } else if ((attendingTreatment.getAttendingStatus() & AttendingStatusEnum.Refuse.getValue()) == AttendingStatusEnum.Refuse.getValue()) {
            //主诊医生拒绝订单
            return "已结束";
        } else if ((attendingTreatment.getAttendingStatus() & AttendingStatusEnum.AlreadyPay.getValue()) == AttendingStatusEnum.AlreadyPay.getValue()) {
            //已支付，相当于用户已确认，标记订单结束
            return "已结束";
        } else if ((attendingTreatment.getAttendingStatus() & AttendingStatusEnum.InformPatient.getValue()) == AttendingStatusEnum.InformPatient.getValue()) {
            //已通知用户，用户未确认（或支付），标记订单为待确认状态
            return "待确认";
        }

        return "";
    }

    /**
     * 获取挂号订单列表
     *
     * @param userId    用户Id
     * @param orderId   订单Id
     * @param pageIndex 页码
     * @param pageSize  页大小
     * @return
     */
    public PagedList<RegisteredOrderView> getRegisteredOrderList(int userId, int orderId, int pageIndex, int pageSize) {
        String fields = "*";
        String orderBy = "create_time desc";
        String whereSql = " user_id = ? and his_order_code is not null and his_order_code != '' and deleted = 0";
        Object[] params = new Object[]{userId};
        if (orderId > 0) {
            whereSql += " and order_id = ? ";
            params = new Object[]{userId, orderId};
        }

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, fields, whereSql, orderBy, RegisteredOrderView.class, params);
    }

    public RegisteredOrder getLatestRegisteredOrderByMedicalCardId(int medicalCardId) {
        return registeredOrderRepository.getRegisteredOrderByMedicalCardId(medicalCardId);
    }

    /**
     * 取消预约挂号订单
     *
     * @param orderId 订单Id
     * @param userId  用户Id
     * @return
     */
    public ServiceResult cancelRegisteredOrder(int orderId, int userId) {
        ServiceResult serviceResult = new ServiceResult();
        Order order = getOrderById(orderId);

        if (order == null || order.getDeleted()) {
            return serviceResult.failed("订单不存在");
        }

        if (order.getOrderType() != OrderTypeEnum.REGISTERED.getValue() || order.getUserId() != userId) {
            return serviceResult.failed("非法请求");
        }

        RegisteredOrder registeredOrder = registeredOrderRepository.findById(order.getBusinessId()).orElse(null);

        if (registeredOrder == null || registeredOrder.getDeleted()) {
            return serviceResult.failed("挂号订单不存在");
        }

        if (StringHelper.isNullOrWhiteSpace(registeredOrder.getHisOrderCode())) {
            return serviceResult.failed("订单未预约成功");
        }

        if (StringHelper.isNullOrWhiteSpace(registeredOrder.getHisClinicCode())) {
            //用户未确认，订单没有支付
            int type = 1;

            if (registeredOrder.getRegisteredType() != null
                    && registeredOrder.getRegisteredType() == RegisteredTypeEnum.ADDITIONAL.getValue()) {
                type = 2;
            }

            ServiceResult cancelOrderResult = nfyyServiceProvider.cancelOrder(registeredOrder.getHisOrderCode(), type);

            int result = 0;
            Refunded refunded = new Refunded();
            refunded.setId(idGenerator.genRefundedId());
            refunded.setOrderId(orderId);
            refunded.setOrderCode(registeredOrder.getHisOrderCode());
            refunded.setUserId(registeredOrder.getUserId());
            refunded.setClinicCode(registeredOrder.getHisClinicCode());
            refunded.setCancelRemark(cancelOrderResult.getMsg());
            refunded.setType(1);
            refunded.setCreateTime(new Date());

            if (cancelOrderResult.success()) {
                result = 0;
                refunded.setResult(result);

                registeredOrder.setRegisteredStatus(registeredOrder.getRegisteredStatus() | RegisteredStatusEnum.Cancel.getValue());
                registeredOrderRepository.save(registeredOrder);

                if (type == 2) {
                    //取消的是加号预约
                    HisAddRegisteredFlag flag = hisAddRegisteredFlagRepository.findById(registeredOrder.getFlagId()).orElse(null);

                    if (flag != null && new Date().before(flag.getEndDate())) {
                        //加号在有效期内，可重新进行预约
                        flag.setStatus(1);
                        hisAddRegisteredFlagRepository.save(flag);
                    }

                    wxProvider.notifyCancelAdditionalTaihe(
                            registeredOrder.getUserId(), registeredOrder.getDoctorName(), registeredOrder.getDoctorTitle());
                }

                //发送模板消息
                sendMsgForCancel(registeredOrder);
            } else {
                result = 1;
                refunded.setResult(result);
            }

            refundedRepository.save(refunded);

//            状态（1-订单未支付 2-订单已支付）
            Map<String, Object> map = new HashMap<>();
            map.put("status", 1);
            return result == 0 ? serviceResult.succeed(cancelOrderResult.getMsg(), map) :
                    serviceResult.failed(cancelOrderResult.getMsg());
        } else {
            String regDateStr = DateUtil.convertToString(registeredOrder.getRegisteredDate(), "yyyy-MM-dd");
            if (registeredOrder.getStartTime() != null) {
                regDateStr = regDateStr + " " + registeredOrder.getStartTime() + ":00";
            } else {
                regDateStr = regDateStr + " " + "00:00:00";
            }
            if (DateUtil.hourBetween(regDateStr) < 24 && DateUtil.hourBetween(regDateStr) > 0) {
                serviceResult.failed("已过平台退号时间，请至医院人工窗口或自助机退号。");
            }

            //进行退号处理
            ServiceResult cancelRegResult = nfyyServiceProvider.cancelReg(registeredOrder.getHisClinicCode());

            int result = 0;
            int returnFee = 0;
            String transactionId = "";

            Refunded refunded = new Refunded();

            if (cancelRegResult.success()) {
                result = 0;
                returnFee = Checker.parseInt(cancelRegResult.getData().get("returnFee").toString());
                transactionId = Checker.getStringValue(cancelRegResult.getData().get("transactionId").toString());

                registeredOrder.setRegisteredStatus(registeredOrder.getRegisteredStatus() | RegisteredStatusEnum.Back.getValue());
                registeredOrderRepository.save(registeredOrder);

                //发送模板消息
                sendMsgForCancel(registeredOrder);
            } else {
                result = 1;
            }

            refunded.setId(idGenerator.genRefundedId());
            refunded.setOrderId(orderId);
            refunded.setOrderCode(registeredOrder.getHisOrderCode());
            refunded.setUserId(registeredOrder.getUserId());
            refunded.setClinicCode(registeredOrder.getHisClinicCode());
            refunded.setResult(result);
            refunded.setRefundedRemark(cancelRegResult.getMsg());
            refunded.setRefundedTransactionId(transactionId);
            refunded.setReturnFee(returnFee * 100);
            refunded.setCreateTime(new Date());
            refunded.setType(2);

            refundedRepository.save(refunded);

            //            状态（1-订单未支付 2-订单已支付）
            Map<String, Object> map = new HashMap<>();
            map.put("status", 2);
            return result == 0 ? serviceResult.succeed(cancelRegResult.getMsg(), map) :
                    serviceResult.failed(cancelRegResult.getMsg());
        }
    }

    private void sendMsgForCancel(RegisteredOrder registeredOrder) {
        try {
            String first = "您好，您已成功退号！";
            String remark = "";
            String[] keywords = new String[]{
                    registeredOrder.getHospitalName(),
                    registeredOrder.getDeptName(),
                    registeredOrder.getDoctorName(),
                    registeredOrder.getPatientName(),
                    LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm"))
            };
            Map<String, Object> data = new HashMap<>();
            data.put("first", new Keyword(first));
            data.put("remark", new Keyword(remark));

            for (int i = 0; i < keywords.length; i++) {
                data.put(String.format("keyword%d", i + 1), new Keyword(keywords[i]));
            }

            //《南方医院太和分院》公众号
            SendTemplateMessageRequest req = SendTemplateMessageRequest.newBuilder()
                    .setData(JsonSerializer.toJson(data))
                    .setTemplateCode("TPL_1002")
                    .setUrl("https://m.ywtinfo.com/nfthwe/orderCenter")
                    .setMiniProgram("")
                    .setUserId(registeredOrder.getUserId())
                    .build();
            weChatMessageServiceBlockingStub.sendTemplateMessage(req);

            //《南方医务通》公众号
            req = SendTemplateMessageRequest.newBuilder()
                    .setData(JsonSerializer.toJson(data))
                    .setTemplateCode("TPL_1056")
                    .setUrl("https://m.ywtinfo.com/nfywtwe/orderCenter")
                    .setMiniProgram("")
                    .setUserId(registeredOrder.getUserId())
                    .build();
            weChatMessageServiceBlockingStub.sendTemplateMessage(req);
        } catch (Exception e) {
            logger.error("sendTemplateMessage(): {}", e.getMessage(), e);
        }
    }

    /**
     * 咨询订单接诊/退诊
     *
     * @param orderId
     * @param doctorId
     * @param isArranged 1-接诊 0-退诊
     * @return
     */
    @Deprecated
    public ServiceResult arrangeConsult(int orderId, int doctorId, int isArranged) {
        ServiceResult result = new ServiceResult();
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return result.failed("该订单不存在");
        }

        int patientId = 0;
        ConsultOrder consultOrder = consultOrderRepository.findById(order.getBusinessId()).orElse(null);

        if (consultOrder.getConsultStatus() != ConsultStatusEnum.Paid.getValue()) {
            return result.failed("订单状态不正确");
        }

        if (consultOrder.getDoctorId() != doctorId) {
            return result.failed("非法请求");
        }

        if (isArranged == 1) {
            consultOrder.setConsultStatus(consultOrder.getConsultStatus() | ConsultStatusEnum.Accept.getValue());
            consultOrder.setAcceptTime(new Date());

            User user = userRepository.findById(order.getUserId()).orElse(null);

            //把该订单串者信息列为该医生的患者
            Patient patient = patientRepository.getPatient(doctorId, user.getMobile(), consultOrder.getName());

            if (patient == null || patient.getDeleted()) {
                String idCardNo = "";
                if (consultOrder.getUserPatientId() != null && consultOrder.getUserPatientId() > 0) {
                    UserPatient userPatient = userPatientRepository.findById(consultOrder.getUserPatientId()).orElse(null);
                    if (!Checker.isNone(userPatient)) {
                        idCardNo = Checker.getStringValue(userPatient.getIdNo());
                    }
                }

                patientId = idGenerator.generatePatientId();
                patient = new Patient();
                patient.setId(patientId);
                patient.setIdCardNo(idCardNo);
                patient.setRealName(consultOrder.getName());
                patient.setAge(consultOrder.getAge());
                patient.setSex(consultOrder.getSex());
                patient.setMobile(consultOrder.getMobile());
                patient.setDoctorId(doctorId);
                patient.setUserId(consultOrder.getUserId());
                patient.setCreateTime(new Date());
                patient.setUpdateTime(new Date());
                patient.setDeleted(false);
                patient.setChiefComplaint("");
                patient.setDiagnosis("");
                patient.setRemark("");
                patientRepository.save(patient);
            } else {
                patientId = patient.getId();

                if (patient.getUserId() == 0) {
                    patient.setUserId(consultOrder.getUserId());
                    patientRepository.save(patient);
                }
            }

            consultOrder.setPatientId(patientId);
            consultOrderRepository.save(consultOrder);

            try {
                //患者端去掉医生接诊通知 2018-04-27 23:14:28
                User doctorUser = userRepository.findById(consultOrder.getDoctorId()).orElse(null);
//                String url = String.format("https://m.ywtinfo.com/nfywtwe/consult/chat/%d?doctorName=%s&doctorId=%d",
//                        orderId, doctorUser.getRealname(), consultOrder.getDoctorId());
//                weChatServiceProvider.sendOfficialTplMsgConsult(
//                        consultOrder.getUserId(), "", doctorUser.getRealname(), consultOrder.getDescription(), url);
                int hospitalId = Checker.getIntegerValue(consultOrder.getHospitalId());
                String templateId;
                String page;
                Map<String, String> keywordMap;
                int terminal;
                SnsUserInfo snsUserInfo;
                String openId;
                switch (hospitalId) {
                    case Constants.TAIHE_HOSPITAL_ID:
                    default:
                        //医生接诊后发送模板消息至"医务通支付助手"。
                        terminal = TerminalEnum.TAI_HE_INTERNET_HOSPITAL_PATIENT_MINI_PROGRAM.getValue();
                        snsUserInfo = snsUserInfoRepository.getSnsUserInfoByUserId(consultOrder.getUserId(), terminal);
                        openId = !Checker.isNone(snsUserInfo) ? snsUserInfo.getOpenId() : "";
                        templateId = ConstantTemplateIds.CONSULT_DOCTOR_ACCEPT;
                        page = String.format(Constants.TAI_HE_INTERNET_HOSPITAL_PATIENT_MINI_PROGRAM_CONSULT_CHAT_URL, orderId);
                        keywordMap = new HashMap<>();
                        keywordMap.put("name3", doctorUser.getRealName());
                        keywordMap.put("thing2", "医生已接诊，请点击进入查看！");
                        weChatMsgProvider.sendMPSubscribeMessage(terminal, openId, templateId, page, keywordMap);
                        break;
                    case Constants.NFYYBYFY_HOSPITAL_ID:
                        // 白云小程序
                        terminal = TerminalEnum.NFYYBYFY_WXAPP.getValue();
                        snsUserInfo = snsUserInfoRepository.getSnsUserInfoByUserId(consultOrder.getUserId(), terminal);
                        openId = !Checker.isNone(snsUserInfo) ? snsUserInfo.getOpenId() : "";
                        templateId = ConstantTemplateIds.CONSULT_DOCTOR_ACCEPT_BY;
                        page = String.format(Constants.TAI_HE_INTERNET_HOSPITAL_PATIENT_MINI_PROGRAM_CONSULT_CHAT_URL, orderId);
                        keywordMap = new HashMap<>();
                        keywordMap.put("name3", doctorUser.getRealName());
                        keywordMap.put("thing2", "医生已接诊，请点击进入查看！");
                        weChatMsgProvider.sendMPSubscribeMessage(terminal, openId, templateId, page, keywordMap);
                        break;
                }

            } catch (Exception e) {
                logger.error("arrangeConsult(): 发送模板消息失败， {}", e.getMessage(), e);
            }
        } else {
            consultOrder.setConsultStatus(consultOrder.getConsultStatus() | ConsultStatusEnum.Refuse.getValue());
        }

        consultOrder.setUpdateTime(new Date());
        consultOrderRepository.save(consultOrder);

        try {
            User doctorUser = userRepository.findById(consultOrder.getDoctorId()).orElse(null);
            String pagePath = String.format(Constants.TH_PATIENT_CONSULT_CHAT_URL, orderId);
            String miniProgram = BizUtil.getMiniProgramParam(Constants.TH_PATIENT_WXMP_APP_ID, pagePath);
            String first = String.format("%s医生有回复", doctorUser.getRealname());
            String remark = "请点击查看";
            weChatMsgProvider.sendByTpl1037(
                    consultOrder.getUserId(), miniProgram, "", first, remark, doctorUser.getRealname(),
                    DateUtil.convertToString(consultOrder.getUpdateTime(), "yyyy-MM-dd"));

            // 白云分院
            weChatMsgProvider.sendByTpl2012(consultOrder.getUserId(), BizUtil.getMiniProgramParam(Constants.NFYYBYFY_WXMP_APP_ID, pagePath),
                    "", first, remark, String.format("%s医生", doctorUser.getRealname()), consultOrder.getName(), "--",
                    DateUtil.convertToString(consultOrder.getCreateTime()));
        } catch (Exception e) {
            logger.error("arrangeConsult(): 发送模板消息失败， {}", e.getMessage(), e);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("sessionId", consultOrder.getSessionId());
        map.put("orderId", String.valueOf(orderId));
        map.put("patientId", patientId);

        return result.succeed("处理成功", map);
    }

    /**
     * 结束咨询订单
     *
     * @param orderId
     * @param doctorId
     * @return
     */
    public ServiceResult endConsultOrder(int orderId, int doctorId) {
        ServiceResult result = new ServiceResult();
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return result.failed("该订单不存在");
        }

        ConsultOrder consultOrder = consultOrderRepository.findById(order.getBusinessId()).orElse(null);

        if (consultOrder.getConsultStatus() != (ConsultStatusEnum.Accept.getValue() | ConsultStatusEnum.Paid.getValue())) {
            return result.failed("订单状态不正确");
        }

        int teamOpDocId = Checker.getIntegerValue(consultOrder.getTeamOperateDoctorId());
        if (teamOpDocId > 0 && teamOpDocId != doctorId) {
            return result.failed("非法请求");
        }
        if (teamOpDocId <= 0 && Checker.getIntegerValue(consultOrder.getDoctorId()) != doctorId) {
            return result.failed("非法请求");
        }

        consultOrder.setConsultStatus(consultOrder.getConsultStatus() | ConsultStatusEnum.End.getValue());
        consultOrderRepository.save(consultOrder);

        return result.succeed("已结束订单");
    }

    public List<Order> getListByUserId(int userId, String mobile) {
        return orderRepository.getOrderListByUserId(userId, mobile);
    }

    /**
     * 太和公众号就诊记录接口使用
     * 互联网医院v1.0.4，就诊记录里面保留“预约挂号、加号预约、门诊缴费”订单。2018-11-15
     * 太和公众号门诊记录过滤门诊缴费单 2019-05-20
     *
     * @param userId
     * @param mobile
     * @param beginDate
     * @param endDate
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public PagedList<Order> getOrderList(int userId, String mobile, String beginDate, String endDate, int pageIndex, int pageSize) {
        String orderBy = "create_time desc";
        String sql = "";
        List<Object> params = new LinkedList<>();
        List<Integer> argTypes = new LinkedList<>();

        if (!StringHelper.isNullOrWhiteSpace(mobile)) {
            sql += "(user_id = ? or patient_mobile = ?) ";
            params.add(userId);
            params.add(mobile);
            argTypes.add(Types.INTEGER);
            argTypes.add(Types.VARCHAR);
        } else {
            sql += "user_id = ? ";
            params.add(userId);
            argTypes.add(Types.INTEGER);
        }

        if (!"".equals(beginDate) && !"".equals(endDate)) {
            sql += "and create_time >= ? and create_time < ? ";
            params.add(beginDate);
            params.add(endDate);
            argTypes.add(Types.VARCHAR);
            argTypes.add(Types.VARCHAR);
        }
        sql += "and (order_type = ? or (order_type = ? and payment_status = ?)) ";
        params.add(OrderTypeEnum.REGISTERED.getValue());
        params.add(OrderTypeEnum.OFFLINE_CONSULT.getValue());
        params.add(PaymentStatusEnum.Success.getValue());
        argTypes.add(Types.INTEGER);
        argTypes.add(Types.INTEGER);
        argTypes.add(Types.INTEGER);

        sql += " and deleted = 0";

        return sqlHelperYwtCenter.getPagedList(
                pageIndex, pageSize, "*", sql, orderBy, Order.class, params.toArray(),
                argTypes.stream().mapToInt(i -> i).toArray());
    }

    public RegisteredOrder getRegisteredOrder(int id) {
        return registeredOrderRepository.findById(id).orElse(null);
    }

    /**
     * 获取询诊订单状态
     *
     * @param consultOrder
     * @return
     */
    public Map<String, Integer> getConsultStatusName(ConsultOrder consultOrder) {
        return getConsultStatusName(consultOrder.getPaymentStatus(), consultOrder.getConsultStatus(), consultOrder.getAcceptTime(), consultOrder.getCreateTime());
    }

    public Map<String, Integer> getConsultStatusName(int paymentStatus, int consultStatus, Date acceptTime, Date createTime) {
        Map<String, Integer> map = new HashMap<>();

        if (paymentStatus != PaymentStatusEnum.Success.getValue()) {
            map.put("待支付", 1);
            return map;
        }

        if ((consultStatus & ConsultStatusEnum.Refunded.getValue()) == ConsultStatusEnum.Refunded.getValue()) {
            map.put("已退款", 8);
            return map;
        }

        if ((consultStatus & ConsultStatusEnum.Cancel.getValue()) == ConsultStatusEnum.Cancel.getValue()) {
            map.put("已取消", 2);
            return map;
        }

        if ((consultStatus & ConsultStatusEnum.Refuse.getValue()) == ConsultStatusEnum.Refuse.getValue()) {
            map.put("已退诊", 3);
            return map;
        }

        if ((consultStatus & ConsultStatusEnum.Evaluate.getValue()) == ConsultStatusEnum.Evaluate.getValue()) {
            map.put("已评价", 7);
            return map;
        }

        if ((consultStatus & ConsultStatusEnum.End.getValue()) == ConsultStatusEnum.End.getValue()) {
            map.put("已结束", 4);
            return map;
        }

        if ((consultStatus & ConsultStatusEnum.Accept.getValue()) == ConsultStatusEnum.Accept.getValue()) {
            Calendar ca1 = Calendar.getInstance();
            Calendar ca2 = Calendar.getInstance();

            ca1.setTime(acceptTime);
            ca1.add(Calendar.DATE, 2);

            if (ca2.after(ca1)) {
                map.put("已结束", 4);  //接诊后超过48小时医生未结束问诊
                return map;
            }

            map.put("接诊中", 5);
            return map;
        }
        if ((consultStatus & ConsultStatusEnum.Paid.getValue()) == ConsultStatusEnum.Paid.getValue()) {
            Calendar ca1 = Calendar.getInstance();
            Calendar ca2 = Calendar.getInstance();

            ca1.setTime(createTime);
            ca1.add(Calendar.DATE, 2);

            if (ca2.before(ca1)) {
                map.put("待接诊", 6);  //接诊后超过48小时医生未结束问诊
                return map;
            }
        }

        map.put("已结束", 4);
        return map;
    }

    /**
     * 获取询诊订单状态(新增评价)
     *
     * @param consultOrder
     * @return
     */
    public Map<String, Integer> getConsultStatusNameWithEvaluate(ConsultOrder consultOrder) {
        return getConsultStatusNameWithEvaluate(consultOrder.getPaymentStatus(), consultOrder.getConsultStatus(), consultOrder.getAcceptTime(), consultOrder.getCreateTime());
    }

    public Map<String, Integer> getConsultStatusNameWithEvaluate(int paymentStatus, int consultStatus, Date acceptTime, Date createTime) {
        Map<String, Integer> map = new HashMap<>();

        if (paymentStatus != PaymentStatusEnum.Success.getValue()) {
            map.put("待支付", 1);
            return map;
        }

        if ((consultStatus & ConsultStatusEnum.Refunded.getValue()) == ConsultStatusEnum.Refunded.getValue()) {
            map.put("已退款", 8);
            return map;
        }

        if ((consultStatus & ConsultStatusEnum.Cancel.getValue()) == ConsultStatusEnum.Cancel.getValue()) {
            map.put("已取消", 2);
            return map;
        }

        if ((consultStatus & ConsultStatusEnum.Refuse.getValue()) == ConsultStatusEnum.Refuse.getValue()) {
            map.put("已退诊", 3);
            return map;
        }

        if ((consultStatus & ConsultStatusEnum.Evaluate.getValue()) == ConsultStatusEnum.Evaluate.getValue()) {
            map.put("已评价", 7);
            return map;
        }

        // 结束但未评价 --》 待评价   add start
        if ((consultStatus & ConsultStatusEnum.End.getValue()) == ConsultStatusEnum.End.getValue() &&
                (consultStatus & ConsultStatusEnum.Evaluate.getValue()) != ConsultStatusEnum.Evaluate.getValue()) {
            map.put("待评价", 9);
            return map;
        }
        // end add

        if ((consultStatus & ConsultStatusEnum.End.getValue()) == ConsultStatusEnum.End.getValue()) {
            map.put("已结束", 4);
            return map;
        }

        if ((consultStatus & ConsultStatusEnum.Accept.getValue()) == ConsultStatusEnum.Accept.getValue()) {
            Calendar ca1 = Calendar.getInstance();
            Calendar ca2 = Calendar.getInstance();

            ca1.setTime(acceptTime);
            ca1.add(Calendar.DATE, 2);

            if (ca2.after(ca1)) {
                //map.put("已结束", 4);  //接诊后超过48小时医生未结束问诊
                map.put("待评价", 9);  //接诊后超过48小时医生未结束问诊
                return map;
            }

            map.put("接诊中", 5);
            return map;
        }
        if ((consultStatus & ConsultStatusEnum.Paid.getValue()) == ConsultStatusEnum.Paid.getValue()) {
            Calendar ca1 = Calendar.getInstance();
            Calendar ca2 = Calendar.getInstance();

            ca1.setTime(createTime);
            ca1.add(Calendar.DATE, 2);

            if (ca2.before(ca1)) {
                map.put("待接诊", 6);  //接诊后超过48小时医生未结束问诊
                return map;
            }
        }

        map.put("已结束", 4);
        return map;
    }

    /**
     * 获取加诊订单状态
     *
     * @param additionalRegistration
     * @return
     */
    public Map<String, Integer> getAdditionalRegistrationStatusName(AdditionalRegistration additionalRegistration) {
        return getAdditionalRegistrationStatusName(additionalRegistration.getPaymentStatus(), additionalRegistration.getStatus(), additionalRegistration);
    }

    public Map<String, Integer> getAdditionalRegistrationStatusName(int paymentStatus, int status, AdditionalRegistration additionalRegistration) {
        Map<String, Integer> map = new HashMap<>();

        if (paymentStatus != PaymentStatusEnum.Success.getValue()) {
            map.put("待支付", 1);
            return map;
        }

        if ((status & AdditionalRegistrationStatusEnum.Refunded.getValue()) == AdditionalRegistrationStatusEnum.Refunded.getValue()) {
            map.put("已退款", 8);
            return map;
        }

        if ((status & AdditionalRegistrationStatusEnum.Evaluate.getValue()) == AdditionalRegistrationStatusEnum.Evaluate.getValue()) {
            map.put("已评价", 7);
            return map;
        }

        if ((status & AdditionalRegistrationStatusEnum.Cancel.getValue()) == AdditionalRegistrationStatusEnum.Cancel.getValue()) {
            map.put("已取消", 2);
            return map;
        }

        if ((status & AdditionalRegistrationStatusEnum.Refuse.getValue()) == AdditionalRegistrationStatusEnum.Refuse.getValue()) {
            map.put("已退诊", 3);
            return map;
        }


        if ((status & AdditionalRegistrationStatusEnum.End.getValue()) == AdditionalRegistrationStatusEnum.End.getValue()) {
            map.put("已结束", 4);
            return map;
        }

        if ((status & AdditionalRegistrationStatusEnum.Paid.getValue()) == AdditionalRegistrationStatusEnum.Paid.getValue()) {

            String dateTime = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date());    // 表示查询的那一天
            String dayDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

            String morning = dayDate + PointInTimeEnum.Morning.getDisplayName();
            Date morningDate = DateUtil.stringToDate(morning, "yyyy-MM-dd HH:mm:ss");

            String afternoon = dayDate + PointInTimeEnum.Afternoon.getDisplayName();
            Date afternoonDate = DateUtil.stringToDate(afternoon, "yyyy-MM-dd HH:mm:ss");

            String night = dayDate + PointInTimeEnum.Night.getDisplayName();
            Date nightDate = DateUtil.stringToDate(night, "yyyy-MM-dd HH:mm:ss");

            String scheduleDate = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(additionalRegistration.getScheduleDate());    // 表示预约的那一天
            Date newDate = new Date();

            int time = additionalRegistration.getScheduleTime();
            if (dateTime.equals(scheduleDate)) {  //表示时间为同一天
                //先对现在的时间进行判断
                if (newDate.after(nightDate)) {  // 当前时间为当天晚上10点后，则表示都是已结束
                    map.put("已结束", 4);
                } else if (newDate.after(afternoonDate)) { //当前时间为当天下午7点后，晚上10点之前，则上午、下午都是已结束，晚上是待接诊

                    if (time == 1 || time == 2) {
                        map.put("已结束", 4);
                    } else {
                        map.put("待接诊", 6);
                    }
                } else if (newDate.after(morningDate)) {  //当前时间为当天12点后，下午5点之前，则上午是已结束，下午，晚上是待接诊
                    if (time == 1) {
                        map.put("已结束", 4);
                    } else {
                        map.put("待接诊", 6);
                    }
                } else {       //当前时间为当天12点之前，上午，下午，晚上是待接诊
                    map.put("待接诊", 6);
                }


            } else if (newDate.after(additionalRegistration.getScheduleDate())) {    //此时表示现在时间比订单时间至少大一天，换句话就是这个订单至少是一天前的订单
                map.put("已结束", 4);
            } else {    //此时表示现在时间比订单时间至少小一天，换句话就是这个订单至少是明天的订单
                map.put("待接诊", 6);
            }

        }
        map.put("待接诊", 6);

        return map;
    }


    public Map<String, Integer> getTransferStatusName(Integer transferStatus, Date createTime) {
        Map<String, Integer> map = new HashMap<>();
        if (transferStatus == null) {
            Calendar ca1 = Calendar.getInstance();
            Calendar ca2 = Calendar.getInstance();

            ca1.setTime(createTime);
            ca1.add(Calendar.DATE, 1);

            if (ca2.after(ca1)) {
                //转出医生24h内没有收到回复
                map.put("已结束", 1);
                return map;
            }
        } else if ((transferStatus & TransferStatusEnum.Refuse.getValue()) == TransferStatusEnum.Refuse.getValue()
                || (transferStatus & TransferStatusEnum.PatientAffirm.getValue()) == TransferStatusEnum.PatientAffirm.getValue()) {
            //无法安排床位或用户已确认，标记订单已结束
            map.put("已结束", 1);
            return map;
        } else if ((transferStatus & TransferStatusEnum.InformPatient.getValue()) == TransferStatusEnum.InformPatient.getValue()
        ) {
            //已通知患者，患者未确认
            map.put("待确认", 0);
            return map;
        }

        map.put("待确认", 0);
        return map;
    }

    /**
     * 新增带评价状态
     *
     * @param transferStatus
     * @param createTime
     * @return
     */
    public Map<String, Integer> getTransferStatusNameWithEvaluate(Integer transferStatus, Date createTime) {
        Map<String, Integer> map = new HashMap<>();

        if (transferStatus == null) {
            Calendar ca1 = Calendar.getInstance();
            Calendar ca2 = Calendar.getInstance();

            ca1.setTime(createTime);
            ca1.add(Calendar.DATE, 1);

            if (ca2.after(ca1)) {
                //转出医生24h内没有收到回复
                map.put("待评价", 2);
                return map;
            }
        } else if ((transferStatus & TransferStatusEnum.PatientAffirm.getValue()) == TransferStatusEnum.PatientAffirm.getValue() &&
                (transferStatus & TransferStatusEnum.PatientEvaluate.getValue()) != TransferStatusEnum.PatientEvaluate.getValue()) {
            map.put("待评价", 2);
            return map;
        } else if ((transferStatus & TransferStatusEnum.PatientEvaluate.getValue()) == TransferStatusEnum.PatientEvaluate.getValue()) {
            map.put("已评价", 3);
            return map;
        } else if ((transferStatus & TransferStatusEnum.Refuse.getValue()) == TransferStatusEnum.Refuse.getValue()) {
            //无法安排床位或用户已评价，标记订单已结束
            map.put("已结束", 1);
            return map;
        } else if ((transferStatus & TransferStatusEnum.InformPatient.getValue()) == TransferStatusEnum.InformPatient.getValue()
        ) {
            //已通知患者，患者未确认
            map.put("待确认", 0);
            return map;
        }

        map.put("待确认", 0);
        return map;
    }


    /**
     * 获取随访订单状态
     *
     * @param followUpOrder
     * @return
     */
    public Map<String, Integer> getFollowUpStatusName(FollowUpOrder followUpOrder) {
        return getFollowUpStatusName(followUpOrder.getCreateTime(), followUpOrder.getFollowUpStatus());
    }

    /**
     * 获取随访订单状态
     *
     * @param createTime
     * @return
     */
    public Map<String, Integer> getFollowUpStatusName(Date createTime, int followUpStatus) {
        Map<String, Integer> map = new HashMap<>();
        if (followUpStatus == FollowUpStatusEnum.End.getValue() || followUpStatus == FollowUpStatusEnum.Evaluate.getValue()
                || (followUpStatus & FollowUpStatusEnum.End.getValue()) == FollowUpStatusEnum.End.getValue()
                || (followUpStatus & FollowUpStatusEnum.Evaluate.getValue()) == FollowUpStatusEnum.Evaluate.getValue()) {
            map.put("已结束", 2);
            return map;
        }

        Calendar ca1 = Calendar.getInstance();
        Calendar ca2 = Calendar.getInstance();

        ca1.setTime(createTime);
        ca1.add(Calendar.DATE, 1);

        if (ca2.after(ca1)) {
            //超过24h，随访自动结束
            map.put("已结束", 2);
        } else {
            map.put("随访中", 1);
        }
        return map;
    }


    /**
     * 获取随访订单状态(新增评价)
     *
     * @param followUpOrder
     * @return
     */
    public Map<String, Integer> getFollowUpStatusNameWithEvaluate(FollowUpOrder followUpOrder) {
        return getFollowUpStatusNameWithEvaluate(followUpOrder.getCreateTime(), followUpOrder.getFollowUpStatus());
    }

    /**
     * 获取随访订单状态
     *
     * @param createTime
     * @return
     */
    public Map<String, Integer> getFollowUpStatusNameWithEvaluate(Date createTime, int followUpStatus) {
        Map<String, Integer> map = new HashMap<>();
        if (followUpStatus == FollowUpStatusEnum.Evaluate.getValue()
                || (followUpStatus & FollowUpStatusEnum.Evaluate.getValue()) == FollowUpStatusEnum.Evaluate.getValue()) {
            map.put("已评价", 3);
            return map;
        }

        if (followUpStatus == FollowUpStatusEnum.End.getValue()
                || (followUpStatus & FollowUpStatusEnum.End.getValue()) == FollowUpStatusEnum.End.getValue()) {
            map.put("待评价", 2);
            return map;
        }

        Calendar ca1 = Calendar.getInstance();
        Calendar ca2 = Calendar.getInstance();

        ca1.setTime(createTime);
        ca1.add(Calendar.DATE, 1);

        if (ca2.after(ca1)) {
            //超过24h，随访自动结束
            map.put("待评价", 2);
        } else {
            map.put("随访中", 1);
        }
        return map;
    }


    /**
     * 获取医生咨询订单列表
     *
     * @param doctorId  医生Id
     * @param pageIndex 页码
     * @param pageSize  页大小
     * @return
     */
    public PagedList<ConsultOrderView> getDoctorConsultOrderList(int doctorId, int pageIndex, int pageSize) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " doctor_id = ? and payment_status = ?";
        paramList.add(doctorId);
        paramList.add(PaymentStatusEnum.Success.getValue());

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", ConsultOrderView.class, paramList.toArray());
    }

    /**
     * 医生可分享查看的咨询记录
     *
     * @param doctorId
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public PagedList<ConsultOrderView> getSharedConsultOrderList(int doctorId, int pageIndex, int pageSize) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " doctor_id = ? and payment_status = ? and (consult_status & 16 = 16) and (ext_status & 1 = 1)";
        paramList.add(doctorId);
        paramList.add(PaymentStatusEnum.Success.getValue());
        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", ConsultOrderView.class, paramList.toArray());
    }

    @Deprecated
    public ServiceResult createConsultOrder(int userId, int doctorId, String patientName, String mobile, int sex,
                                            int age, String desc, int hospitalId, int deptId, int amount, String images,
                                            int recordId, String idNo, int userPatientId, int terminal, int extStatus,
                                            int consultType) {
        ServiceResult serviceResult = new ServiceResult();
        MedicalRecords record = null;

        if (userId == doctorId) {
            return serviceResult.failed("您不能向自己发起咨询");
        }

        if (recordId > 0) {
            record = medicalRecordsRepository.findById(recordId).orElse(null);

            if (record != null) {
                record.setMobile(mobile);
                record.setDoctorId(doctorId);
                record.setType(MedicalRecordsTypeEnum.PatientInfo.getValue());
                record.setSex(sex);
                record.setAge(age);
                record.setCreateTime(new Date());
                record.setUpdateTime(new Date());
                record.setChiefComplaint(desc);
                record.setDeleted(false);
                record.setPatientName(patientName);
                record.setIdNo(idNo);

                medicalRecordsRepository.save(record);
            } else {
                return serviceResult.failed("用户病历不存在");
            }
        } else {
            record = new MedicalRecords();
            record.setId(idGenerator.genMedicalRecordsId());
            record.setUserId(userId);
            record.setMobile(mobile);
            record.setDoctorId(doctorId);
            record.setType(MedicalRecordsTypeEnum.PatientInfo.getValue());
            record.setSex(sex);
            record.setAge(age);
            record.setCreateTime(new Date());
            record.setUpdateTime(new Date());
            record.setChiefComplaint(desc);
            record.setDeleted(false);
            record.setPatientName(patientName);
            record.setIdNo(idNo);

            record.setPatientId(0);
            medicalRecordsRepository.save(record);
        }

        ConsultOrder consultOrder = new ConsultOrder();
        consultOrder.setId(idGenerator.genConsultOrderId());
        consultOrder.setUserId(userId);
        consultOrder.setName(patientName);
        consultOrder.setMobile(mobile);
        consultOrder.setAge(age);
        consultOrder.setSex(sex);
        consultOrder.setDescription(desc);
        consultOrder.setDoctorId(doctorId);
        consultOrder.setHospitalId(hospitalId);
        consultOrder.setDeptId(deptId);
        consultOrder.setAmount(amount);
        consultOrder.setCreateTime(new Date());
        consultOrder.setUpdateTime(null);
        consultOrder.setAcceptTime(null);
        consultOrder.setSessionId(StringHelper.getUUIDWithoutHyphen());
        consultOrder.setDeleted(false);
        consultOrder.setPaymentStatus(PaymentStatusEnum.Pending.getValue());
        consultOrder.setConsultStatus(0);
        consultOrder.setPatientId(0);
        consultOrder.setUserPatientId(userPatientId);
        consultOrder.setExtStatus(extStatus);
        consultOrder.setConsultType(consultType);
        consultOrder.setIdNo(idNo);
        consultOrderRepository.save(consultOrder);

        Order order = new Order();
        order.setId(idGenerator.generateOrderId());
        order.setOrderNo(idGenerator.generateOrderNo(""));
        order.setOrderStatus(0);
        order.setUserId(userId);
        order.setPaymentStatus(PaymentStatusEnum.Pending.getValue());
        order.setOrderAmount(new BigDecimal(amount / 100d));
        order.setRemark("");
        order.setCreateTime(new Date());
        order.setOrderType(OrderTypeEnum.CONSULT.getValue());
        order.setBusinessId(consultOrder.getId());
        order.setDoctorId(doctorId);
        order.setPatientMobile(mobile);
        order.setDeleted(false);
        order.setTerminal(terminal);
        order.setPayCode("1005");
        order.setPayBody("医务通-" + OrderTypeEnum.CONSULT.getDisplayName());
        order.setPaymentCallbackMethod("/com.ywt.gapi.order.OrderService/wxPayPartnerCallback");
        orderRepository.save(order);

        //实名认证
        if (!StringHelper.isNullOrWhiteSpace(idNo) && !StringHelper.isNullOrWhiteSpace(patientName)) {
            String sql = "update user set id_certificate_type = 1, real_name = ?, id_certificate_no = ? where id = ? and (id_certificate_no = '' or id_certificate_no is null);";
            Object[] args = new Object[]{patientName, idNo, userId};
            int[] types = new int[]{Types.VARCHAR, Types.VARCHAR, Types.INTEGER};
            int count = jdbcTemplate.update(sql, args, types);
        }

        if (!StringHelper.isNullOrWhiteSpace(images)) {
//            String[] imageUrls = images.split(",");
            List<String> imageUrls = Arrays.asList(images.split(","));
            List<MedicalRecordsImage> imageList = new LinkedList<>();

            for (String url : imageUrls) {
                if (!StringHelper.isNullOrWhiteSpace(url)) {
                    MedicalRecordsImage image = new MedicalRecordsImage();
                    image.setId(idGenerator.genMedicalRecordsImageId());
                    image.setDoctorId(doctorId);
                    image.setImageUrl(url);
                    image.setDeleted(false);
                    image.setCreateTime(new Date());
                    image.setPatientId(0);
                    image.setMedicalRecordsId(0);
                    image.setOrderId(order.getId());
                    image.setUserId(userId);
                    image.setType(MedicalRecordsImageTypeEnum.Order.getValue());

                    imageList.add(image);
                }
            }

            if (imageList.size() > 0) {
                medicalRecordsImageRepository.saveAll(imageList);
            }

            List<MedicalRecordsImage> lst = new LinkedList<>();
            List<MedicalRecordsImage> medicalRecordsImages = medicalRecordsImageRepository.getListByRecordId(record.getId());
            List<String> existedImages = new LinkedList<>();    //已存在的病历图片链接

            if (medicalRecordsImages == null) {
                medicalRecordsImages = new LinkedList<>();
            }

            if (medicalRecordsImages.size() > 0) {
                existedImages = medicalRecordsImages.stream().map(MedicalRecordsImage::getImageUrl).collect(Collectors.toList());
            }

            for (MedicalRecordsImage image : medicalRecordsImages) {
                if (!imageUrls.contains(image.getImageUrl())) {
                    //本次删除的图片
                    image.setDeleted(true);
                    lst.add(image);
                }
            }

            for (String url : imageUrls) {
                //本次新增的图片链接
                if (!existedImages.contains(url)) {
                    MedicalRecordsImage image = new MedicalRecordsImage();
                    image.setId(idGenerator.genMedicalRecordsImageId());
                    image.setCreateTime(new Date());
                    image.setDeleted(false);
                    image.setDoctorId(doctorId);
                    image.setImageUrl(url);
                    image.setMedicalRecordsId(record.getId());
                    image.setPatientId(0);
                    image.setType(MedicalRecordsImageTypeEnum.Patient.getValue());

                    lst.add(image);
                }
            }

            medicalRecordsImageRepository.saveAll(lst);
        }

//        try{
//            messageServiceProvider.notifyAfterCreateConsultOrder(patientName, "", mobile);
//        } catch (Exception e){
//
//        }

        Map<String, Object> map = new HashMap<>();
        map.put("orderId", order.getId());
        map.put("orderType", order.getOrderType());
        map.put("sessionId", consultOrder.getSessionId());
        return serviceResult.succeed("创建订单成功", map);
    }

    public ServiceResult cancelConsultOrder(int orderId, int userId) {
        ServiceResult serviceResult = new ServiceResult();
        Order order = getOrderById(orderId);

        if (order == null || order.getDeleted()) {
            return serviceResult.failed("订单不存在");
        }

        if (order.getOrderType() != OrderTypeEnum.CONSULT.getValue() || order.getUserId() != userId) {
            return serviceResult.failed("非法请求");
        }

        ConsultOrder consultOrder = consultOrderRepository.findById(order.getBusinessId()).orElse(null);

        if (consultOrder == null || consultOrder.getDeleted()) {
            return serviceResult.failed("咨询订单不存在");
        }

        if (consultOrder.getConsultStatus() != ConsultStatusEnum.Paid.getValue()) {
            return serviceResult.failed("该订单不能取消");
        }

        Calendar ca1 = Calendar.getInstance();
        Calendar ca2 = Calendar.getInstance();

        ca1.setTime(consultOrder.getCreateTime());
        ca1.add(Calendar.DATE, 1);

        if (ca2.after(ca1)) {
            //医生24h内没有回复
            consultOrder.setConsultStatus(consultOrder.getConsultStatus() | ConsultStatusEnum.Cancel.getValue());
            consultOrder.setUpdateTime(new Date());
            consultOrderRepository.save(consultOrder);

            return serviceResult.succeed("处理成功");
        }

        return serviceResult.failed("该订单暂不能取消");
    }

    /**
     * 获取最后一期转诊订单
     *
     * @param doctorId
     * @param patientId
     * @return
     */
    public TransferTreatment getLastTransfer(int doctorId, int patientId) {
        return transferTreatmentRepository.getLastTransfer(doctorId, patientId);
    }

    /**
     * 获取最后一期主诊订单
     *
     * @param doctorId
     * @param patientId
     * @return
     */
    public AttendingTreatment getLastAttending(int doctorId, int patientId) {
        return attendingTreatmentRepository.getLastAttending(doctorId, patientId);
    }

    /**
     * 获取最后一期询诊订单
     *
     * @param doctorId
     * @param patientId
     * @return
     */
    public Treatment getLastTreatment(int doctorId, int patientId) {
        return treatmentRepository.getLastTreatment(doctorId, patientId);
    }

    /**
     * 获取最后一期随访订单
     *
     * @param doctorId
     * @param patientId
     * @return
     */
    public FollowUpOrder getLastFollowUpOrder(int doctorId, int patientId) {
        return followUpOrderRepository.getLastFollowUpOrder(doctorId, patientId);
    }

    /**
     * 创建随访订单
     *
     * @param hospitalId 医院Id
     * @param deptId     科室Id
     * @param doctorId   医生Id
     * @param patientId  患者Id
     * @return
     */
    public ServiceResult createFollowUpOrder(int hospitalId, int deptId, int doctorId, int patientId, int identity) {
        ServiceResult serviceResult = new ServiceResult();
        Patient patient = patientRepository.findById(patientId).orElse(null);

        if (patient == null || patient.getDeleted() || patient.getDoctorId() != doctorId) {
            return serviceResult.failed("患者不存在");
        }
        // 判断处理patient表的userID字段
        if (patient.getUserId() == 0) {
            User user = userRepository.findUserByMobile(patient.getMobile());
            if (Checker.isNone(user)) {
                return serviceResult.failed("患者未注册，暂时不能发起随访");
            }
            patient.setUserId(user.getId());
            patientRepository.save(patient);
        }

        FollowUpOrder followUpOrder = new FollowUpOrder();
        followUpOrder.setId(idGenerator.genFollowUpOrderId());
        followUpOrder.setUserId(patient.getUserId());
        followUpOrder.setPatientId(patient.getId());
        followUpOrder.setPatientName(patient.getRealName());
        followUpOrder.setPatientMobile(patient.getMobile());
        followUpOrder.setAge(patient.getAge());
        followUpOrder.setSex(patient.getSex());
        followUpOrder.setDoctorId(doctorId);
        followUpOrder.setHospitalId(hospitalId);
        followUpOrder.setDeptId(deptId);
        followUpOrder.setCreateTime(new Date());
        followUpOrder.setUpdateTime(null);
        followUpOrder.setSessionId(StringHelper.getUUIDWithoutHyphen());
        followUpOrder.setFollowUpStatus(FollowUpStatusEnum.During.getValue());
        followUpOrder.setDeleted(false);
        followUpOrder.setDiagnosis(patient.getDiagnosis());
        followUpOrder.setPatientIdNo(patient.getIdCardNo());
        followUpOrderRepository.save(followUpOrder);

        Order order = saveOrder(patient.getUserId(), 0, followUpOrder.getId(), doctorId,
                patient.getMobile(), OrderTypeEnum.FOLLOWUP.getValue());
        Map<String, Object> map = new HashMap<>();
        map.put("orderId", order.getId());
        map.put("orderType", order.getOrderType());
        map.put("sessionId", followUpOrder.getSessionId());
        map.put("patientName", followUpOrder.getPatientName());
        map.put("patientMobile", followUpOrder.getPatientMobile());

        try {
            //给患者发送短信或微信推送信息
            User user = userRepository.findById(followUpOrder.getDoctorId()).orElse(null);

            // 医生发给患者（IM消息）
            String doctorIdentity = DoctorIdentityEnum.valueOf(identity).getDisplayName();
            String content = String.format("您好，我是%s%s，现在对您进行随访", user.getRealname(), doctorIdentity);
            SessionMessage message = SessionMessage.newBuilder()
                    .setMessageType(1)
                    .setContent(content)
                    .setCustom(String.format("{\"biz_type\":6,\"order_id\":%d,\"auto\":1,\"sys\":1}", order.getId()))
                    .setFromUserId(followUpOrder.getDoctorId())
                    .setFromUserName(user.getRealname())
                    .setToUserId(followUpOrder.getUserId())
                    .setToUserName(followUpOrder.getPatientName())
                    .setTime(System.currentTimeMillis())
                    .setSessionId(followUpOrder.getSessionId())
                    .build();
            imServiceBlockingStub.sendSessionMessage(message);

            String first = String.format("%s医生向您发起了随访", user.getRealname());
            //互联网医院v1.0.4，南方医务通”原来预约挂号的微信模板消息保留，其他的去掉。 2018-11-14
//            String url = String.format("https://m.ywtinfo.com/nfywtwe/follow/chat/%d?doctorName=%s&doctorId=%d", order.getId(), user.getRealname(), followUpOrder.getDoctorId());
//            weChatServiceProvider.sendOfficialTplMsgFollowUp(followUpOrder.getUserId(), first, followUpOrder.getPatientName(), followUpOrder.getCreateTime(), "", url);

            //医务通互联网医院
            first = "您好，您的主诊医生诊后向您发起了诊后随访";
            String pagePath = String.format(Constants.TH_PATIENT_FOLLOW_CHAT_URL, order.getId());
            String miniProgram = BizUtil.getMiniProgramParam(Constants.TH_PATIENT_WXMP_APP_ID, pagePath);
            String keyword1 = user.getRealname();
            String keyword2 = DateUtil.convertToString(followUpOrder.getCreateTime(), "yyyy-MM-dd HH:mm");
            String keyword3 = followUpOrder.getPatientName();
            String remark = "点击查看！";
//            weChatMsgProvider.sendByTpl1036(followUpOrder.getUserId(), miniProgram, "", first, remark, keyword1, keyword2, keyword3);

//            String key = order.getId().toString();
//            String value = redisTemplate.opsForValue().get(key)+"";
//            Integer times = 0;
//            if(!Checker.isNone(value)){
//                times = Integer.parseInt(Checker.getStringValue(value));
//            }
//            if(Checker.isNone(value) || times <= 5) {
//                String url = "";
//                pagePath = String.format(Constants.TH_PATIENT_FOLLOW_CHAT_URL, order.getId());
//                miniProgram = BizUtil.getMiniProgramParam(Constants.TH_PATIENT_WXMP_APP_ID, pagePath);
//                String time3 = DateUtil.convertToString(followUpOrder.getCreateTime(), "yyyy-MM-dd HH:mm");
//                String const4 = "线上问诊-随访，医生有回复，请进入查看";
//                Map<String, Object> data = new HashMap<>();
//                data.put("const1", "线上问诊-随访");
//                data.put("thing2",  user.getRealname());
//                data.put("time3", time3);
//                data.put("const4", const4);
//                String tplCode = "TPL_012001";
//                weChatMsgProvider.sendTpl012001(followUpOrder.getUserId(), tplCode, url, miniProgram, data);
//                times = times + 1;
//                value = times.toString();
//                redisTemplate.opsForValue().set(key, expireTime, value);
//            }


            //南方医院太和分院
            weChatMsgProvider.sendByTpl8053(followUpOrder.getUserId(), miniProgram, "", first, remark, keyword1, keyword2, keyword3);

            //南方医务通
            Hospital hospital = hospitalRepository.findHospitalById(followUpOrder.getHospitalId());
            if (hospital != null && !StringHelper.isNullOrWhiteSpace(hospital.getName())) {
                keyword2 = hospital.getName();
            } else {
                keyword2 = "";
            }
            weChatMsgProvider.sendByTpl1019(followUpOrder.getUserId(), miniProgram, "", first, remark, keyword1, keyword2, keyword3);
            // 白云分院
            weChatMsgProvider.sendByTpl2012(followUpOrder.getUserId(), BizUtil.getMiniProgramParam(Constants.NFYYBYFY_WXMP_APP_ID, pagePath),
                    "", first, remark, String.format("%s医生", user.getRealname()), followUpOrder.getPatientName(), content,
                    DateUtil.convertToString(followUpOrder.getCreateTime()));
        } catch (Exception e) {

        }

        return serviceResult.succeed("创建订单成功", map);
    }

    private Order saveOrder(int userId, int amount, int businessId, int doctorId, String mobile, int orderType) {
        Order order = new Order();
        order.setId(idGenerator.generateOrderId());
        order.setOrderNo(idGenerator.generateOrderNo(""));
        order.setOrderStatus(0);
        order.setUserId(userId);
        order.setPaymentStatus(PaymentStatusEnum.Pending.getValue());
        order.setOrderAmount(new BigDecimal(amount / 100d));
        order.setRemark("");
        order.setCreateTime(new Date());
        order.setOrderType(orderType);
        order.setBusinessId(businessId);
        order.setDoctorId(doctorId);
        order.setPatientMobile(mobile);
        order.setDeleted(false);
        orderRepository.save(order);

        return order;
    }

    /**
     * 根据用户Id获取随访订单
     *
     * @param userId    用户Id
     * @param pageIndex 页码
     * @param pageSize  页大小
     * @return
     */
    public PagedList<FollowUpOrderView> getUserFollowUpOrderListByCondition(int userId, int pageIndex, int pageSize, int hospitalId) {
        String fields = "*";
        String orderBy = "create_time desc";
        String whereSql = " user_id = ? and deleted = 0";
        List<Object> params = new LinkedList<>();
        params.add(userId);
        if (hospitalId > 0) {
            whereSql += " and hospital_id = ? ";
            params.add(hospitalId);
        }

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, fields, whereSql, orderBy, FollowUpOrderView.class,
                params.toArray());
    }

    /**
     * 根据用户Id获取随访订单
     *
     * @param doctorId  医生Id
     * @param pageIndex 页码
     * @param pageSize  页大小
     * @return
     */
    public PagedList<FollowUpOrderView> getDoctorFollowUpOrderList(int doctorId, int pageIndex, int pageSize) {
        String fields = "*";
        String orderBy = "create_time desc";
        String whereSql = " doctor_id = ? and deleted = 0";
        Object[] params = new Object[]{doctorId};

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, fields, whereSql, orderBy, FollowUpOrderView.class, params);
    }

    public String getDateString(Date date, int period) {
        String transferDate = DateUtil.convertToString(date, "yyyy年MM月dd日");
        DatePeriodEnum datePeriodEnum = DatePeriodEnum.valueOf(period);

        if (datePeriodEnum != null) {
            transferDate += datePeriodEnum.getDisplayName();
        }

        return transferDate;
    }

    public ServiceResult settle(int orderId) {
        ServiceResult serviceResult = new ServiceResult();
        Order order = getOrderById(orderId);

        if (order == null || order.getDeleted()) {
            return serviceResult.failed("订单不存在");
        }

        if (order.getOrderType() != OrderTypeEnum.TREATMENT.getValue()) {
            return serviceResult.failed("订单类型不正确");
        }

        Treatment treatment = getTreatmentById(order.getBusinessId());

        if (treatment == null || treatment.isDeleted()) {
            return serviceResult.failed("远程会诊订单不存在");
        }

        if ((treatment.getTreatmentStatus() & TreatmentStatusEnum.Settlement.getValue()) == TreatmentStatusEnum.Settlement.getValue()) {
            return serviceResult.failed("订单已结算，请勿重复操作");
        }

        if ((treatment.getTreatmentStatus() & TreatmentStatusEnum.InformPatient.getValue()) != TreatmentStatusEnum.InformPatient.getValue()) {
            return serviceResult.failed("订单暂不能结算");
        }

        String sql = String.format("update treatment set treatment_status = treatment_status | %d where id = %d and (treatment_status & %d) != %d;",
                TreatmentStatusEnum.Settlement.getValue(),
                treatment.getId(),
                TreatmentStatusEnum.Settlement.getValue(),
                TreatmentStatusEnum.Settlement.getValue());
        int count = jdbcTemplate.update(sql);

        if (count > 0) {
            int total = Checker.getBigDecimalTo100TimeIntValue(treatment.getAmount());

            settle(total, treatment.getDoctorId(), treatment.getUnionDoctorId());

            order.setOrderStatus(OrderStatusEnum.Settlement.getValue());
            orderRepository.save(order);

            return serviceResult.succeed();
        }

        return serviceResult.failed("订单已结算，请勿重复操作");
    }


    /**
     * 远程会诊订单结算
     * 比例：专家/基层 = 4/1
     *
     * @param total
     * @param fromDoctorId
     * @param toDoctorId
     * @return
     */
    public ServiceResult settle(int total, int fromDoctorId, int toDoctorId) {
        ServiceResult serviceResult = new ServiceResult();

        int fromTotal = (int) (total * 0.2);
        int toTotal = total - fromTotal;

        settle(fromTotal, fromDoctorId, AccountDetailTypeEnum.Treatment);
        settle(toTotal, toDoctorId, AccountDetailTypeEnum.Treatment);

        return serviceResult.succeed();
    }

    private ServiceResult settle(int total, int doctorId, AccountDetailTypeEnum typeEnum) {
        ServiceResult serviceResult = new ServiceResult();
        Account account = accountRepository.getByUserId(doctorId);

        if (account == null) {
            //创建账户
            account = new Account();
            account.setId(idGenerator.genAccountId());
            account.setCreateTime(new Date());
            account.setStatus(AccountStatusEnum.Normal.getValue());
            account.setUserId(doctorId);
            account.setDeleted(false);
            account.setBalance(total);
        } else {
            account.setBalance(account.getBalance() + total);
        }

        //增加账户余额变动明细
        AccountDetail detail = new AccountDetail();
        detail.setId(idGenerator.genAccountDetailId());
        detail.setCreateTime(new Date());
        detail.setStatus(1);
        detail.setType(typeEnum.getValue());
        detail.setDeleted(false);
        detail.setBalance(account.getBalance());
        detail.setAmount(total);
        detail.setUserId(doctorId);
        detail.setAccountId(account.getId());
        detail.setTitle(typeEnum.getDisplayName());
        detail.setRemark(null);

        accountDetailRepository.save(detail);
        accountRepository.save(account);

        return serviceResult.succeed("处理成功");
    }

    /**
     * 结束随访订单
     *
     * @param orderId
     * @param doctorId
     * @return
     */
    public ServiceResult endFollowUpOrder(int orderId, int doctorId) {
        ServiceResult result = new ServiceResult();
        Order order = orderRepository.findById(orderId).orElse(null);

        if (order == null || order.getDeleted()) {
            return result.failed("该订单不存在");
        }

        FollowUpOrder followUpOrder = followUpOrderRepository.findById(order.getBusinessId()).orElse(null);

        Calendar ca1 = Calendar.getInstance();
        Calendar ca2 = Calendar.getInstance();

        ca1.setTime(followUpOrder.getCreateTime());
        ca1.add(Calendar.DATE, 1);

        if (ca2.after(ca1)) {
            //超过24h，随访自动结束
            return result.failed("随访已结束");
        }

        if (followUpOrder.getFollowUpStatus() != FollowUpStatusEnum.During.getValue()) {
            return result.failed("随访状态不正确");
        }

        if (followUpOrder.getDoctorId() != doctorId) {
            return result.failed("非法请求");
        }

        followUpOrder.setFollowUpStatus(FollowUpStatusEnum.End.getValue());
        followUpOrderRepository.save(followUpOrder);

        return result.succeed("已结束随访");
    }


    /**
     * 根据订单状态查找订单的数量（仅限于当前状态）(接诊中，48内处理)
     */
    public int getCountByDoctorId(int doctorId, int paymentStatus, int consultStatus, int doubleConsultStatus) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -2);
        String data = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
//        return consultOrderRepository.getCountByDoctorId(doctorId, paymentStatus, consultStatus, doubleConsultStatus, data, data);
        return consultOrderRepository.getConsultOrderCountByDoctorId(doctorId, paymentStatus, consultStatus, doubleConsultStatus, data);
    }

    /**
     * 根据订单状态和医生ID找到已预约的加诊订单数量（已支付，但是还没有过就诊时间）
     */
    public int getAdditionalRegistrationCountByDoctorId(int doctorId, int paymentStatus) {

        List<Object> paramList = new ArrayList<>();
        String whereSql = " 1=1 and doctor_id = ? and deleted = 0 and payment_status = ? and status = ? ";
        paramList.add(doctorId);
        paramList.add(paymentStatus);
        paramList.add(AdditionalRegistrationStatusEnum.Paid.getValue());    //  表示已付款

        String dateTime = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date());    // 表示查询的那一天
        String dayDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

        String morning = dayDate + PointInTimeEnum.Morning.getDisplayName();
        Date morningDate = DateUtil.stringToDate(morning, "yyyy-MM-dd HH:mm:ss");

        String afternoon = dayDate + PointInTimeEnum.Afternoon.getDisplayName();
        Date afternoonDate = DateUtil.stringToDate(afternoon, "yyyy-MM-dd HH:mm:ss");

        String night = dayDate + PointInTimeEnum.Night.getDisplayName();
        Date nightDate = DateUtil.stringToDate(night, "yyyy-MM-dd HH:mm:ss");

        Date date = new Date();

        // 我们需要找的是未结束的

        if (date.after(nightDate)) {  //如果当前时间大于当天晚上最大时间，则不取当天
            whereSql += "  and  schedule_date > ?    ";
            paramList.add(dateTime);
        } else if (date.after(afternoonDate)) {    //此时说明大于下午的时间，则晚上可以
            whereSql += "  and (schedule_date > ? or ( schedule_date = ? and  schedule_time = 3 ) )";
            paramList.add(dateTime);
            paramList.add(dateTime);
        } else if (date.after(morningDate)) {    //此时大于上午的时间，则下午、晚上可以
            whereSql += " and  (schedule_date > ? or ( schedule_date = ? and ( schedule_time = 2 or schedule_time = 3 ) ) )";
            paramList.add(dateTime);
            paramList.add(dateTime);
        } else if (date.before(morningDate)) {   //此时小于早上的时间，则当天都可以
            whereSql += "  and  schedule_date >= ?  ";
            paramList.add(dateTime);
        }

        return sqlHelperYwtCenter.getPagedList(1, 1000, "*", whereSql, " create_time desc", AdditionalRegistration.class, paramList.toArray()).getTotal();


    }

    /**
     * 得到接诊中订单的数量(待接诊也是在48小时之内)
     */
    public int getCountByDoctorIdWithAccept(int doctorId, int paymentStatus, int consultStatus, int doubleConsultStatus) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -2);
        String data = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
        return consultOrderRepository.getCountByDoctorId(doctorId, paymentStatus, consultStatus, doubleConsultStatus, data, data);
    }


    /**
     * 得到接诊中的订单
     */

    public PagedList<ConsultOrder> getConsultOrderListByDoctorIdWithAccept(int pageIndex, int pageSize, int doctorId, int paymentStatus, int consultStatus, int doubleConsultStatus) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -2);
        String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
        List<Object> paramList = new ArrayList<>();
        String whereSql = " doctor_id = ? and payment_status = ? and consult_status >= ? and consult_status < ? and create_time >= ? and ( accept_time >= ?  or accept_time is null ) and deleted = 0  ";
        paramList.add(doctorId);
        paramList.add(paymentStatus);
        paramList.add(consultStatus);
        paramList.add(doubleConsultStatus);
        paramList.add(date);
        paramList.add(date);
        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, " create_time desc", ConsultOrder.class, paramList.toArray());
    }

    /**
     * 得到接诊中的订单
     */

    public PagedList<ConsultOrder> getConsultOrderListByDoctorIdWithAccept(int pageIndex, int pageSize, int doctorId) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -2);
        String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
        List<Object> paramList = new ArrayList<>();
        String whereSql = " doctor_id = ? and payment_status = ? and( (consult_status >= ? and consult_status < ?) or (consult_status >= ? and consult_status < ?) )and create_time >= ? and ( accept_time >= ?  or accept_time is null ) and deleted = 0  ";
        paramList.add(doctorId);
        paramList.add(PaymentStatusEnum.Success.getValue());

        // Paid("已付款", 1),
        int paidValue = ConsultStatusEnum.Paid.getValue();
        paramList.add(paidValue);
        paramList.add(2 * paidValue);

        // Accept("已接诊", 1 << 2),
        int acceptValue = ConsultStatusEnum.Accept.getValue();
        paramList.add(acceptValue);
        paramList.add(2 * acceptValue);

        paramList.add(date);
        paramList.add(date);
        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, " create_time desc", ConsultOrder.class, paramList.toArray());
    }

    /**
     * 根据订单状态查找订单（仅限于当前状态）
     */
    public PagedList<AdditionalRegistration> getAdditionalRegistrationListByDoctorId(int pageIndex, int pageSize, int doctorId, int paymentStatus, int status) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " doctor_id = ? and payment_status = ? and status >= ? and status < ?  and deleted = 0  ";
        paramList.add(doctorId);
        paramList.add(paymentStatus);
        paramList.add(status);
        paramList.add(2 * status);

        String dateTime = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date());    // 表示查询的那一天

        String dayDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

        String morning = dayDate + PointInTimeEnum.Morning.getDisplayName();
        Date morningDate = DateUtil.stringToDate(morning, "yyyy-MM-dd HH:mm:ss");

        String afternoon = dayDate + PointInTimeEnum.Afternoon.getDisplayName();
        Date afternoonDate = DateUtil.stringToDate(afternoon, "yyyy-MM-dd HH:mm:ss");

        String night = dayDate + PointInTimeEnum.Night.getDisplayName();
        Date nightDate = DateUtil.stringToDate(night, "yyyy-MM-dd HH:mm:ss");

        Date date = new Date();
        if (date.after(nightDate)) {  //已经过了晚上时间了,则取后面
            whereSql += " and  schedule_date > ?   ";
            paramList.add(dateTime);
        } else if (date.after(afternoonDate)) {    //此时说明大于下午的时间，小于晚上的最大时间，则取晚上的
            whereSql += " and ( schedule_date > ? or ( schedule_date = ? and  schedule_time = 3 )) ";
            paramList.add(dateTime);
            paramList.add(dateTime);
        } else if (date.after(morningDate)) {    //此时大于上午的最大时间，小于下午的最大时间，则取下午和晚上的
            whereSql += " and ( schedule_date > ? or (  schedule_date = ? and ( schedule_time = 2 or schedule_time = 3 )) )";
            paramList.add(dateTime);
            paramList.add(dateTime);
        } else if (date.before(morningDate)) {   //此时小于上午的时间，则取当天和当天以后的
            whereSql += " and  schedule_date >= ?";
            paramList.add(dateTime);
        }

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, " create_time desc", AdditionalRegistration.class, paramList.toArray());
    }

    /**
     * 查找问诊记录(  )
     * create by daiyihua
     *
     * @param pageIndex
     * @param pageSize
     * @param doctorId
     * @return
     */
    public PagedList<ConsultOrder> getConsultOrderListByDoctorIdWithRecord(int pageIndex, int pageSize, int doctorId) {
        //  停诊：1<<1 ; 患者取消： 1 << 2；结束：1<<3;

        List<Object> paramList = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -2);
        String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
        String whereSql = " doctor_id = ? and ( " +
                "(consult_status >= 2 and consult_status < 4 ) or ( consult_status >= 8 and consult_status < 16  ) or ( consult_status >= 16  ) " +
                "  or (create_time < ? )  or (consult_status & 8 = 8) ) and ( payment_status = ? ) and deleted = 0  ";
        paramList.add(doctorId);
//        paramList.add(ConsultStatusEnum.Refunded.getValue());
        paramList.add(date);
        paramList.add(PaymentStatusEnum.Success.getValue());
        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, " create_time desc", ConsultOrder.class, paramList.toArray());
    }

    /**
     * 查找已预约里面的记录
     * create by daiyihua
     *
     * @param pageIndex
     * @param pageSize
     * @param doctorId
     * @return
     */
    public PagedList<AdditionalRegistration> getAdditionalRegistrationListByDoctorIdWithStatus(int pageIndex, int pageSize, int doctorId, int status) {
        //传过来的status值有：4-患者取消；8-就诊结束；2-医生停诊

        List<Object> paramList = new ArrayList<>();
        String whereSql = " 1=1 and doctor_id = ? and deleted = 0 and payment_status = ? ";
        paramList.add(doctorId);
        paramList.add(PaymentStatusEnum.Success.getValue());
        if (status == 4) {   //患者取消
            whereSql += " and  status >= 4 and status < 8  ";
        } else if (status == 8) {   //已结束
            whereSql += " and ( status >= 8 ";
            String dateTime = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date());    // 表示查询的那一天
            String dayDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

            String morning = dayDate + PointInTimeEnum.Morning.getDisplayName();
            Date morningDate = DateUtil.stringToDate(morning, "yyyy-MM-dd HH:mm:ss");

            String afternoon = dayDate + PointInTimeEnum.Afternoon.getDisplayName();
            Date afternoonDate = DateUtil.stringToDate(afternoon, "yyyy-MM-dd HH:mm:ss");

            String night = dayDate + PointInTimeEnum.Night.getDisplayName();
            Date nightDate = DateUtil.stringToDate(night, "yyyy-MM-dd HH:mm:ss");

            Date date = new Date();
            if (date.after(nightDate)) {  //已经过了晚上时间了,说明已经结束了
                whereSql += " or (status = 1 and  schedule_date <= ? ) ) ";
                paramList.add(dateTime);
            } else if (date.after(afternoonDate)) {    //此时说明大于下午的时间，小于晚上的最大时间
                whereSql += " or (status = 1  and ( schedule_date < ? or ( schedule_date = ? and ( schedule_time = 1  or schedule_time = 2 ))) ) )";
                paramList.add(dateTime);
                paramList.add(dateTime);
            } else if (date.after(morningDate)) {    //此时大于上午的最大时间，小于下午的最大时间，表示上午时间为已结束
                whereSql += " or (status = 1  and ( schedule_date < ? or (  schedule_date = ? and schedule_time = 1 ))))";
                paramList.add(dateTime);
                paramList.add(dateTime);
            } else if (date.before(morningDate)) {   //此时小于上午的时间，则不取当天
                whereSql += " or (status = 1 and  schedule_date < ?) )";
                paramList.add(dateTime);
            }

        } else if (status == 2) {   //医生停诊
            whereSql += " and  status >= 2 and status < 4  ";
        } else {
            //这里主要是和带就诊区分开来,停诊则不用功算时间
            whereSql += " and ( status > 1   ";
            String dateTime = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date());    // 表示查询的那一天
            String dayDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

            String morning = dayDate + PointInTimeEnum.Morning.getDisplayName();
            Date morningDate = DateUtil.stringToDate(morning, "yyyy-MM-dd HH:mm:ss");

            String afternoon = dayDate + PointInTimeEnum.Afternoon.getDisplayName();
            Date afternoonDate = DateUtil.stringToDate(afternoon, "yyyy-MM-dd HH:mm:ss");

            String night = dayDate + PointInTimeEnum.Night.getDisplayName();
            Date nightDate = DateUtil.stringToDate(night, "yyyy-MM-dd HH:mm:ss");

            Date date = new Date();
            if (date.after(nightDate)) {  //已经过了晚上时间了,说明已经结束了
                whereSql += " or ( status = 1  and  schedule_date <= ?  )  )";
                paramList.add(dateTime);
            } else if (date.after(afternoonDate)) {    //此时说明大于下午的时间，小于晚上的最大时间
                whereSql += " or ( status = 1  and ( schedule_date < ? or ( schedule_date = ? and ( schedule_time = 1  or schedule_time = 2 ) ) )) )";
                paramList.add(dateTime);
                paramList.add(dateTime);
            } else if (date.after(morningDate)) {    //此时大于上午的最大时间，小于下午的最大时间，表示上午时间为已结束
                whereSql += " or ( status = 1  and ( schedule_date < ? or (  schedule_date = ? and schedule_time = 1 ) ) ) )";
                paramList.add(dateTime);
                paramList.add(dateTime);
            } else if (date.before(morningDate)) {   //此时小于上午的时间，则不取当天
                whereSql += "or ( status = 1  and  schedule_date < ? ) )";
                paramList.add(dateTime);
            }

        }

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, " create_time desc", AdditionalRegistration.class, paramList.toArray());
    }

    public FollowUpConfig saveFollowUpConfig(FollowUpConfig config) {
        config.setId(idGenerator.genFollowUpConfigId());
        followUpConfigRepository.save(config);
        return config;
    }

    /**
     * 得到随访中的订单(24小时以内为随访中的订单)
     * create by daiyihua
     *
     * @param doctorId
     * @return
     */
    public List<FollowUpOrder> getUnderwayFollowUpORderList(int doctorId) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        String date = DateUtil.convertToString(calendar.getTime(), "yyyy-MM-dd HH:mm:ss");
        return followUpOrderRepository.getUnderwayFollowUpORderList(doctorId, date);
    }

    /**
     * 得到已结束的订单（超过24小时自动结束）
     * create by daiyihua
     *
     * @param doctorId
     * @return
     */
    public List<FollowUpOrder> getFinishFollowUpORderList(int doctorId) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        String date = DateUtil.convertToString(calendar.getTime(), "yyyy-MM-dd HH:mm:ss");
        return followUpOrderRepository.getFinishFollowUpORderList(doctorId, date);
    }

    /**
     * 根据type类型得到订单记录
     * create by daiyihua
     *
     * @param pageIndex
     * @param pageSize
     * @param doctorId
     * @param type
     * @return
     */
    public PagedList<FollowUpOrder> getDoctorFollowUpOrderWithStatus(int pageIndex, int pageSize, int doctorId, int type) {
        //type 需要查找的类型，1-随访中，2-随访记录（已结束）

        List<Object> paramList = new ArrayList<>();
        String whereSql = " 1=1 ";
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        String date = DateUtil.convertToString(calendar.getTime(), "yyyy-MM-dd HH:mm:ss");

        if (type == 1) {

            calendar.add(Calendar.DAY_OF_YEAR, -1);      //得到随访中的订单 (24小时以内为随访中的订单)
            whereSql += " and doctor_id = ? and create_time >= ? and follow_up_status = 1 and deleted = 0   ";
            paramList.add(doctorId);
            paramList.add(date);
        } else if (type == 2) {

            calendar.add(Calendar.DAY_OF_YEAR, -1);      //得到已结束的订单（超过24小时自动结束）  1-随访中，2-已结束，4-已评价  ，采用的是位运算
            whereSql += " and  doctor_id = ? and (follow_up_status & 2 = 2 or create_time < ?) and deleted = 0  ";
            paramList.add(doctorId);
            paramList.add(date);
        }

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, " create_time desc", FollowUpOrder.class, paramList.toArray());
    }

    public ServiceResult createFollowUpConfig(int doctorId, int userId, int type, int preId, int qid, int delay,
                                              String unit, String mobile, String name, String diagnose, int sex, int age) {
        ServiceResult result = new ServiceResult();

        if (preId < 1) {
            return result.failed("invalid preId");
        }

        Calendar calendar = Calendar.getInstance();
        Date currentDate = calendar.getTime();
        MsgTplTypeEnum msgTplTypeEnum = MsgTplTypeEnum.valueOf(type);

        if (msgTplTypeEnum == null) {
            return result.failed("invalid type");
        }

        if (msgTplTypeEnum != MsgTplTypeEnum.NO_NEED) {
            if (delay < 1 || delay > 50) {
                return result.failed("invalid delay");
            }

            if (type == MsgTplTypeEnum.QUESTIONNAIRE.getValue() && qid < 1) {
                return result.failed("invalid qid");
            }

            switch (unit) {
                case "天":
                    calendar.add(Calendar.DATE, delay);
                    break;
                case "周":
                    calendar.add(Calendar.DATE, delay * 7);
                    break;
                case "月":
                    calendar.add(Calendar.MONTH, delay);
                    break;
                default:
                    return result.failed("invalid unit");
            }
        }

        MsgTpl msgTpl = msgTplRepository.getMsgTplByType(type);

        if (msgTpl == null) {
            return result.failed("模板不存在");
        }

        String content = msgTpl.getContent();

        if (msgTpl.getFormat()) {
            User user = userRepository.findById(doctorId).orElse(null);
            if (user != null && !StringHelper.isNullOrEmpty(user.getRealname())) {
                content = String.format(msgTpl.getContent(), user.getRealname());
            }
        }

        FollowUpConfig followUpConfig = new FollowUpConfig();
        followUpConfig.setId(idGenerator.genFollowUpConfigId());
        followUpConfig.setContent(content);
        followUpConfig.setDelay(delay);
        followUpConfig.setDoctorId(doctorId);
        followUpConfig.setUserId(userId);
        followUpConfig.setCreateTime(currentDate);
        followUpConfig.setDeleted(false);
        followUpConfig.setQuestionnaireId(qid);
        followUpConfig.setStatus(0);
        followUpConfig.setType(type);
        followUpConfig.setUnit(unit);
        followUpConfig.setTriggerTime(calendar.getTime());
        followUpConfig.setUpdateTime(null);
        followUpConfig.setPrescriptionId(preId);
        followUpConfig.setUserId(userId);
        followUpConfig.setMobile(mobile);
        followUpConfig.setName(name);
        followUpConfig.setDiagnose(diagnose);
        followUpConfig.setAge(age);
        followUpConfig.setSex(sex);

        followUpConfigRepository.save(followUpConfig);

        return result.succeed();
    }

    /**
     * 创建加诊预约订单
     *
     * @return
     */
    public ServiceResult createAdditionalRegistration(int recordId, int userId, int scheduleId) {
        ServiceResult result = new ServiceResult();

        MedicalRecords records = medicalRecordsRepository.findById(recordId).orElse(null);
        if (Checker.isNone(records)) {
            return result.failed("参数有误");
        }
        if (records.getUserId() != userId) {
            return result.failed("参数有误");
        }

        DoctorSchedule doctorSchedule = doctorScheduleRepository.findById(scheduleId).orElse(null);
        if (doctorSchedule == null) {
            return result.failed("创建失败：没找到相关用户信息");
        }

        //医生
        Doctor doctor = doctorRepository.findById(doctorSchedule.getDoctorId()).orElse(null);
        if (doctor == null) {
            return result.failed("创建失败：没找到相关用户信息");
        }
        ScheduleConfig config = scheduleConfigRepository.findById(doctorSchedule.getConfigId()).orElse(null);
        if (config == null) {
            return result.failed("创建失败：没找到相关用户信息");
        }

        //这里需要判断是否属于第二次预约
        int count = additionalRegistrationRepository.checkRepetition(records.getPatientName(), records.getMobile(), scheduleId);
        if (count > 0) {
            return result.failed("不能重复预约");
        }

        //type:  类型（7-创建加诊订单）
        // 远程会诊价格
        Double amount = config.getAmount() / 100d;

        int addId = idGenerator.genAdditionalRegistrationId();
        AdditionalRegistration ar = new AdditionalRegistration();
        ar.setId(addId);
        //这里是用户表id
        ar.setUserId(userId);
        ar.setPaymentStatus(PaymentStatusEnum.Pending.getValue());
        ar.setUpdateTime(new Date());
        ar.setCreateTime(new Date());
        ar.setDeleted(false);
        ar.setStatus(AdditionalRegistrationStatusEnum.UNKNOWN.getValue());
        ar.setAmount(config.getAmount());
        ar.setMobile(records.getMobile());
        ar.setName(records.getPatientName());
        ar.setSex(records.getSex());
        ar.setAge(records.getAge());
        ar.setPatientId(Checker.getIntegerValue(records.getPatientId()));
        ar.setScheduleAddress(config.getProvince() + config.getCity() + config.getArea() + config.getAddress());
        ar.setDoctorId(doctorSchedule.getDoctorId());
        int hospitalId = 0;
        String[] hos = doctor.getHospitalIds().split(",");
        for (String h : hos) {
            if (!Checker.isNone(h)) {
                hospitalId = Integer.parseInt(h);
                break;
            }
        }
        int deptId = 0;
        String[] des = doctor.getDeptIds().split(",");
        for (String d : des) {
            if (!Checker.isNone(d)) {
                deptId = Integer.parseInt(d);
                break;
            }
        }
        ar.setHospitalId(hospitalId);
        ar.setDeptId(deptId);
        ar.setScheduleId(scheduleId);
        ar.setScheduleDate(doctorSchedule.getClinicTime());
        if (doctorSchedule.getMorning()) {
            ar.setScheduleTime(1);
        } else if (doctorSchedule.getAfternoon()) {
            ar.setScheduleTime(2);
        } else if (doctorSchedule.getNight()) {
            ar.setScheduleTime(3);
        }
        additionalRegistrationRepository.save(ar);

        int orderId = idGenerator.generateOrderId();
        String orderNo = idGenerator.generateOrderNo("");

        BigDecimal decimal = BigDecimal.valueOf(config.getAmount() / 100.0);
        Order order = new Order();
        order.setId(orderId);
        order.setOrderNo(orderNo);
        order.setOrderStatus(OrderStatusEnum.Pending_Payment.getValue());
        order.setUserId(records.getUserId());
        order.setPatientMobile(records.getMobile());
        order.setOrderAmount(decimal);
        order.setPaymentStatus(PaymentStatusEnum.Pending.getValue());
        order.setRemark("");
        order.setCreateTime(new Date());
        order.setDeleted(false);
        order.setOrderType(OrderTypeEnum.ADDITIONAL_REGISTRATION.getValue());
        order.setBusinessId(addId);
        order.setDoctorId(doctorSchedule.getDoctorId());
        order.setTitle("");

        orderRepository.save(order);

        Map<String, Object> map = new HashMap<>();
        map.put("orderId", orderId);
        result.setData(map);


        return result.succeed("处理成功");
    }

    /**
     * 根据ID得到待随访数量
     *
     * @param doctorId
     * @return
     */
    public int getAwaitFollowUpCountByDoctorId(int doctorId) {
        return followUpOrderRepository.getAwaitFollowUpCountByDoctorId(doctorId);
    }

    public AdditionalRegistration getAdditionalRegistration(int id) {
        return additionalRegistrationRepository.findById(id).orElse(null);
    }


    /**
     * 创建预约挂号订单
     *
     * @param hospitalId       医院ID
     * @param deptCode         科室Code
     * @param deptName         科室名称
     * @param doctorCode       医生Code
     * @param doctorName       医生名称
     * @param registeredFee    挂号费
     * @param medicalFee       诊查费
     * @param registeredDate   预约日期
     * @param period           预约时间段
     * @param startTime        预约开始时间：HH:MI
     * @param endTime          预约结束时间：HH:MI
     * @param userId           用户ID
     * @param medicalCardId    诊疗卡ID
     * @param scheduleItemCode 门诊排班项记录标识
     * @param paymentChannel   支付渠道
     * @param source           订单来源
     * @return
     */
    public ServiceResult createTaiheRegisteredOrder(
            int hospitalId, String deptCode, String deptName, String doctorCode,
            String doctorName, int registeredFee, int medicalFee, long registeredDate,
            int period, String startTime, String endTime, int userId, int medicalCardId,
            String scheduleItemCode, int paymentChannel, int source) {
        ServiceResult serviceResult = new ServiceResult();
        MedicalCard medicalCard = medicalCardRepository.findById(medicalCardId).orElse(null);

        if (medicalCard == null || medicalCard.getStatus() == MedicalCardStatusEnum.DELETED.getValue()) {
            return serviceResult.failed("诊疗卡不存在");
        }

        User user = userRepository.findById(userId).orElse(null);

        if (user == null || user.getIsDeleted()) {
            return serviceResult.failed(("用户不存在"));
        }

        int paymentStatus = PaymentStatusEnum.Pending.getValue();

        if (paymentChannel == PaymentChannelEnum.Cash.getValue() ||
                paymentChannel == PaymentChannelEnum.FREE.getValue()) {
            //现场支付、无须支付
            paymentStatus = PaymentStatusEnum.Success.getValue();
        }

        GetDoctorListResponse res = taiheProvider.getDoctorList("", "", doctorCode, hospitalId);

        if ((res == null) || (res.getCode() != ResultCode.SUCCEED_VALUE) || (res.getDoctorsList().size() == 0)) {
            return serviceResult.failed("医生不存在");
        }

        com.ywt.gapi.third.taihe.Doctor doctor = res.getDoctors(0);

        RegisteredOrder registeredOrder = new RegisteredOrder();
        registeredOrder.setId(idGenerator.genRegisteredOrderId());
        registeredOrder.setUserId(userId);
        registeredOrder.setHospitalId(hospitalId);
        registeredOrder.setDeptId(0);
        registeredOrder.setDoctorId(0);
        registeredOrder.setDoctorName(doctorName);
        registeredOrder.setDoctorTitle(Checker.getStringValue(doctor.getDoctorTitle()));
        registeredOrder.setTotal(registeredFee + medicalFee);
        registeredOrder.setRegisteredDate(new Date(registeredDate));
        registeredOrder.setRegisteredPeriod(period);
        registeredOrder.setStartTime(startTime);
        registeredOrder.setEndTime(endTime);
        registeredOrder.setHisPatientId(medicalCard.getHisPatientId());
        registeredOrder.setMedicalCardId(medicalCardId);
        registeredOrder.setPatientSex(medicalCard.getSex());
        registeredOrder.setPatientName(medicalCard.getPatientName());
        registeredOrder.setPaymentChannel(paymentChannel);
        registeredOrder.setDeleted(false);
        registeredOrder.setUpdateTime(new Date());
        registeredOrder.setCreateTime(new Date());
        registeredOrder.setScheduleItemCode(scheduleItemCode);
        registeredOrder.setDoctorCode(doctorCode);
        registeredOrder.setDoctorName(doctorName);
        registeredOrder.setDeptCode(deptCode);
        registeredOrder.setDeptName(deptName);
        registeredOrder.setRegisteredFee(registeredFee);
        registeredOrder.setMedicalFee(medicalFee);
        registeredOrder.setPaymentStatus(paymentStatus);
        registeredOrder.setRegisteredStatus(0);
        registeredOrder.setSource(source);
        registeredOrder.setRemark(BizUtil.getHospitalNameByIdSimply(hospitalId));

        registeredOrderRepository.save(registeredOrder);

        int orderType = OrderTypeEnum.REGISTERED.getValue();
        int orderId = idGenerator.generateOrderId();
        String orderNo = idGenerator.generateOrderNo("");

        Order order = new Order();
        order.setId(orderId);
        order.setOrderNo(orderNo);
        order.setOrderStatus(OrderStatusEnum.Pending_Payment.getValue());
        order.setUserId(registeredOrder.getUserId());
        order.setPatientMobile(user.getMobile());
        order.setOrderAmount(new BigDecimal(registeredOrder.getTotal() / 100d));
        order.setPaymentStatus(paymentStatus);
        order.setRemark("");
        order.setCreateTime(new Date());
        order.setDeleted(false);
        order.setOrderType(orderType);
        order.setBusinessId(registeredOrder.getId());
        order.setDoctorId(0);
        order.setTitle(OrderTypeEnum.REGISTERED.getDisplayName());

        orderRepository.save(order);
        registeredOrder.setOrderId(orderId);
        registeredOrder.setOrderNo(orderNo);

        //调用HIS
        ServiceResult createOrderResult = taiheProvider.createOrder(scheduleItemCode, registeredOrder.getHisPatientId(),
                medicalCard.getCardNo(), registeredOrder.getStartTime(), registeredOrder.getEndTime(), hospitalId);

        if (!createOrderResult.success()) {
            return serviceResult.failed(createOrderResult.getMsg());
        }

        Map<String, Object> map = createOrderResult.getData();
        registeredOrder.setHisSeqCode(Checker.isNone(map.get("seqCode")) ? "" : map.get("seqCode").toString());
        registeredOrder.setHisRegFee(Checker.isNone(map.get("regFee")) ? "" : map.get("regFee").toString());
        registeredOrder.setHisAdmitRange(Checker.isNone(map.get("admitRange")) ? "" : map.get("admitRange").toString());
        registeredOrder.setHisAdmitAddress(Checker.isNone(map.get("admitAddress")) ? "" : map.get("admitAddress").toString());
        registeredOrder.setHisOrderContent(Checker.isNone(map.get("orderContent")) ? "" : map.get("orderContent").toString());
        registeredOrder.setHisOrderCode(Checker.isNone(map.get("orderCode")) ? "" : map.get("orderCode").toString());
        registeredOrder.setHisTransactionId("");
        registeredOrder.setRegisteredStatus(RegisteredStatusEnum.Booked.getValue());

        registeredOrderRepository.save(registeredOrder);
        taiheProvider.payFree(registeredOrder.getHisOrderCode(), registeredOrder.getHisPatientId(), hospitalId);

        wxProvider.notifyRegisteredTaihe(
                registeredOrder.getUserId(), registeredOrder.getPatientName(), registeredOrder.getHisPatientId(),
                registeredOrder.getDoctorName(), registeredOrder.getRegisteredDate(), registeredOrder.getDeptName(),
                registeredOrder.getStartTime(), registeredOrder.getEndTime(), hospitalId, registeredOrder.getRegisteredPeriod());

        int status = 0;
        String msg = "已为您保留预约号，请在就诊当日到医院人工缴费窗口取号，如未就诊将计爽约一次";

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("orderId", orderId);
        dataMap.put("orderType", orderType);
        dataMap.put("status", status);
        dataMap.put("hisSeqCode", Checker.parseInt(registeredOrder.getHisSeqCode()));
        dataMap.put("idNo", Checker.getStringValue(medicalCard.getIdNo()));
        dataMap.put("mobile", Checker.getStringValue(medicalCard.getMobile()));
        dataMap.put("name", Checker.getStringValue(medicalCard.getPatientName()));

        serviceResult.setData(dataMap);
        return serviceResult.succeed(msg);
    }

    /**
     * 发送取消预约通知
     */
    private void sendCancelRegMsg(RegisteredOrder registeredOrder, int hospitalId) {
        switch (hospitalId) {
            case Constants.TAIHE_HOSPITAL_ID:
                wxProvider.notifyCancelTaihe(
                        registeredOrder.getUserId(), BizUtil.getHospitalNameByIdSimply(hospitalId), registeredOrder.getDeptName(),
                        registeredOrder.getPatientName(), registeredOrder.getDoctorName(), new Date());
                break;
            case Constants.NFYYBYFY_HOSPITAL_ID:
                wxProvider.notifyCancel4NFYYBYFY(registeredOrder.getUserId(), BizUtil.getHospitalNameByIdSimply(hospitalId),
                        registeredOrder.getPatientName(), registeredOrder.getDoctorName(),
                        String.format("%s %s-%s", DateUtil.convertToString(registeredOrder.getRegisteredDate(), "MM月dd日"),
                                Checker.getStringValue(registeredOrder.getStartTime()),
                                Checker.getStringValue(registeredOrder.getEndTime())));
                break;
            default:
                break;
        }
    }


    /**
     * 取消预约挂号订单
     *
     * @param orderId 订单Id
     * @param userId  用户Id
     * @return
     */
    public ServiceResult cancelTaiheRegisteredOrder(int orderId, int userId) {
        ServiceResult serviceResult = new ServiceResult();
        Order order = getOrderById(orderId);

        if (order == null || order.getDeleted()) {
            return serviceResult.failed("订单不存在");
        }

        if (order.getOrderType() != OrderTypeEnum.REGISTERED.getValue() || order.getUserId() != userId) {
            return serviceResult.failed("非法请求");
        }

        RegisteredOrder registeredOrder = registeredOrderRepository.findById(order.getBusinessId()).orElse(null);

        if (registeredOrder == null || registeredOrder.getDeleted()) {
            return serviceResult.failed("挂号订单不存在");
        }

        String wxTransactionId = Checker.getStringValue(registeredOrder.getWxTransactionId());


        if (StringHelper.isNullOrWhiteSpace(registeredOrder.getHisOrderCode())) {
            return serviceResult.failed("订单未预约成功");
        }

        ServiceResult cancelOrderResult = new ServiceResult();
        int hospitalId = Checker.getIntegerValue(registeredOrder.getHospitalId());
        if (hospitalId == Constants.TAIHE_HOSPITAL_ID || hospitalId == Constants.NFYYBYFY_HOSPITAL_ID) {
            //太和医院/白云区医院取消
            cancelOrderResult = taiheProvider.cancelOrder(registeredOrder.getHisOrderCode(),
                    registeredOrder.getHisClinicCode(), hospitalId, wxTransactionId);

            if (cancelOrderResult.success()) {
                registeredOrder.setRegisteredStatus(registeredOrder.getRegisteredStatus() | RegisteredStatusEnum.Back.getValue());
                registeredOrderRepository.save(registeredOrder);

                //TODO: 微信退费处理 修改type值

                Refunded refunded = new Refunded();
                refunded.setId(idGenerator.genRefundedId());
                refunded.setOrderId(orderId);
                refunded.setOrderCode(registeredOrder.getHisOrderCode());
                refunded.setUserId(registeredOrder.getUserId());
                refunded.setClinicCode(registeredOrder.getHisClinicCode());
                refunded.setResult(1);
                refunded.setRefundedRemark(cancelOrderResult.getMsg());
                refunded.setRefundedTransactionId("");
                refunded.setReturnFee(registeredOrder.getTotal());
                refunded.setCreateTime(new Date());
                refunded.setType(1);

                refundedRepository.save(refunded);

                //通知用户
                sendCancelRegMsg(registeredOrder, hospitalId);

                Map<String, Object> map = new HashMap<>();
                map.put("status", 2);

                return serviceResult.succeed("", map);
            }

            return serviceResult.failed(cancelOrderResult.getMsg());
        } else if (registeredOrder.getHospitalId() == 1) {
            if (registeredOrder.getRegisteredType() != null &&
                    registeredOrder.getRegisteredType() == RegisteredTypeEnum.ADDITIONAL.getValue()) {
                //南方医院加号取消
                cancelOrderResult = nfyyServiceProvider.cancelOrder(
                        registeredOrder.getHisOrderCode(), RegisteredTypeEnum.ADDITIONAL.getValue());

                if (cancelOrderResult.success()) {


                }
            } else {
                //南方医院普通预约取消
            }
        }

        if (StringHelper.isNullOrWhiteSpace(registeredOrder.getHisOrderCode())) {
            //用户未确认，订单没有支付

            int result = 0;
            Refunded refunded = new Refunded();
            refunded.setId(idGenerator.genRefundedId());
            refunded.setOrderId(orderId);
            refunded.setOrderCode(registeredOrder.getHisOrderCode());
            refunded.setUserId(registeredOrder.getUserId());
            refunded.setClinicCode(registeredOrder.getHisClinicCode());
            refunded.setCancelRemark(cancelOrderResult.getMsg());
            refunded.setType(1);
            refunded.setCreateTime(new Date());

            if (cancelOrderResult.success()) {
                result = 0;
                refunded.setResult(result);

                registeredOrder.setRegisteredStatus(registeredOrder.getRegisteredStatus() | RegisteredStatusEnum.Cancel.getValue());
                registeredOrderRepository.save(registeredOrder);
            } else {
                result = 1;
                refunded.setResult(result);
            }

            refundedRepository.save(refunded);

//            状态（1-订单未支付 2-订单已支付）
            Map<String, Object> map = new HashMap<>();
            map.put("status", 1);
            return result == 0 ? serviceResult.succeed(cancelOrderResult.getMsg(), map) :
                    serviceResult.failed(cancelOrderResult.getMsg());
        } else {
            String regDateStr = DateUtil.convertToString(registeredOrder.getRegisteredDate(), "yyyy-MM-dd");
            if (registeredOrder.getStartTime() != null) {
                regDateStr = regDateStr + " " + registeredOrder.getStartTime() + ":00";
            } else {
                regDateStr = regDateStr + " " + "00:00:00";
            }
            if (DateUtil.hourBetween(regDateStr) < 24 && DateUtil.hourBetween(regDateStr) > 0) {
                serviceResult.failed("已过平台退号时间，请至医院人工窗口或自助机退号。");
            }

            //进行退号处理
            ServiceResult cancelRegResult = taiheProvider.cancelOrder(registeredOrder.getHisOrderCode(),
                    registeredOrder.getHisClinicCode(), registeredOrder.getHospitalId(), wxTransactionId);

            int result = 0;
            int returnFee = 0;
            String transactionId = "";

            Refunded refunded = new Refunded();

            if (cancelRegResult.success()) {
                result = 0;
                registeredOrder.setRegisteredStatus(registeredOrder.getRegisteredStatus() | RegisteredStatusEnum.Back.getValue());
                registeredOrderRepository.save(registeredOrder);

                //通知用户
                sendCancelRegMsg(registeredOrder, hospitalId);
            } else {
                result = 1;
            }

            refunded.setId(idGenerator.genRefundedId());
            refunded.setOrderId(orderId);
            refunded.setOrderCode(registeredOrder.getHisOrderCode());
            refunded.setUserId(registeredOrder.getUserId());
            refunded.setClinicCode(registeredOrder.getHisClinicCode());
            refunded.setResult(result);
            refunded.setRefundedRemark(cancelRegResult.getMsg());
            refunded.setRefundedTransactionId(transactionId);
            refunded.setReturnFee(returnFee * 100);
            refunded.setCreateTime(new Date());
            refunded.setType(2);

            refundedRepository.save(refunded);

            //            状态（1-订单未支付 2-订单已支付）
            Map<String, Object> map = new HashMap<>();
            map.put("status", 2);
            return result == 0 ? serviceResult.succeed(cancelRegResult.getMsg(), map) :
                    serviceResult.failed(cancelRegResult.getMsg());
        }
    }

    /**
     * 太和医院，在线取号
     *
     * @param orderId 订单Id
     * @param userId  用户Id
     * @return
     */
    public ServiceResult takeTaiheRegisteredOrder(int orderId, int userId) {
        ServiceResult serviceResult = new ServiceResult();
        Order order = getOrderById(orderId);

        if (order == null || order.getDeleted()) {
            return serviceResult.failed("订单不存在");
        }

        if (order.getOrderType() != OrderTypeEnum.REGISTERED.getValue() || order.getUserId() != userId) {
            return serviceResult.failed("非法请求");
        }

        RegisteredOrder registeredOrder = registeredOrderRepository.findById(order.getBusinessId()).orElse(null);

        if (registeredOrder == null || registeredOrder.getDeleted()) {
            return serviceResult.failed("挂号订单不存在");
        }

        if (StringHelper.isNullOrWhiteSpace(registeredOrder.getHisOrderCode())) {
            return serviceResult.failed("订单未预约成功");
        }

        //进行取号处理
        ServiceResult takeRegResult = taiheProvider.take(registeredOrder.getHisOrderCode(),
                registeredOrder.getHisPatientId(), registeredOrder.getHospitalId());

        int result = 0;
        String registrationId = "";

        if (takeRegResult.success()) {
            result = 0;
            registrationId = Checker.getStringValue(takeRegResult.getData().get("registrationId").toString());      //就诊流水号，对应registeredOrder表的HisClinicCode字段

            registeredOrder.setRegisteredStatus(registeredOrder.getRegisteredStatus() | RegisteredStatusEnum.Took.getValue());
            registeredOrder.setHisClinicCode(registrationId);
            registeredOrderRepository.save(registeredOrder);

            //获取排队信息
            ServiceResult queueInfoResult = taiheProvider.getQueueInfo(registrationId, registeredOrder.getHospitalId());

            if (queueInfoResult.success()) {
                Map<String, Object> data = queueInfoResult.getData();
                int waitingNumber = (int) data.get("waitingNumber");
                wxProvider.notifyTookTaihe(registeredOrder.getUserId(), waitingNumber, new Date(), registrationId);
            }


        } else {
            result = 1;
        }

        //            状态（1-订单未支付 2-订单已支付）
        Map<String, Object> map = new HashMap<>();
        map.put("registrationId", registrationId);
        return result == 0 ? serviceResult.succeed(takeRegResult.getMsg(), map) :
                serviceResult.failed(takeRegResult.getMsg());
    }

    /**
     * 根据用户ID得到该用户下所有的诊疗卡的所有当然候诊订单
     *
     * @param userId
     * @return
     */
    public List<RegisteredOrder> getQueueOrderList(int userId) {
        String date = DateUtil.convertToString(new Date(), "yyyy-M-d");
        return registeredOrderRepository.getTaiheQueueOrderListByUserId(userId, date);

    }


    /**
     * 获取预约挂号订单状态
     *
     * @param registeredOrder
     * @return
     */
    public Map<String, Integer> getRegisteredStatusName(RegisteredOrder registeredOrder) {
        Map<String, Integer> map = new HashMap<>();
        int registeredStatus = registeredOrder.getRegisteredStatus();
        if ((registeredStatus & RegisteredStatusEnum.Back.getValue()) == RegisteredStatusEnum.Back.getValue()) {
            map.put("已退号", 5);
            return map;
        }
        if ((registeredStatus & RegisteredStatusEnum.Expired.getValue()) == RegisteredStatusEnum.Expired.getValue()) {
            map.put("已过期", 4);
            return map;
        }

        if ((registeredStatus & RegisteredStatusEnum.Cancel.getValue()) == RegisteredStatusEnum.Cancel.getValue()) {
            map.put("已取消", 2);
            return map;
        }

        if ((registeredStatus & RegisteredStatusEnum.Took.getValue()) == RegisteredStatusEnum.Took.getValue()) {
            map.put("已取号", 3);
            return map;
        }

        if ((registeredStatus & RegisteredStatusEnum.Booked.getValue()) == RegisteredStatusEnum.Booked.getValue()) {
            map.put("已预约", 1);
            return map;
        }

        return map;
    }

    /**
     * 根据订单号，得到支付成功的订单支付记录
     *
     * @param orderNo
     * @return
     */
    public OrderPayment getOrderPaymentByOrderNo(String orderNo) {
        return orderPaymentRepository.getOrderPaymentByOrderNo(orderNo);
    }


    /**
     * 根据条件得到订单ID
     *
     * @param userId          用户ID
     * @param userId          用户手机号
     * @param type            1-进行中，2-已完成
     * @param prescriptionIds 处方IDs（经过type参数筛选后的值）
     * @param pageIndex       当前页数
     * @param pageSize        每页大小
     * @return
     */
    @Deprecated // 对getListByUserId方法进行备份
    public PagedList<Order> getListByUserIdBackUp(int userId, String mobile, int type, String prescriptionIds, int pageIndex, int pageSize) {
        String orderBy = "id desc";
        List<Object> params = new LinkedList<>();
        // todo 除了问诊，其它订单的类型都需要根据userId和手机号进行匹配
        String sql = " (user_id = ? or patient_mobile = ?) ";
        params.add(userId);
        params.add(mobile.trim());

        /**
         * 已完成、已退款、已取消 的状态算是"已完成"，对应type=2
         * */

        // 得到远程会诊中正在进行的订单
        String str11 = " (select ot.id from orders ot where ot.order_type = 1 and ot.user_id = ? and ot.order_status = 10 and ot.payment_status <> 2  )  ";
        // 得到远程会诊中结束的订单
        String str12 = " (select ot.id from orders ot where ot.order_type = 1 and ot.user_id = ? and !(ot.order_status = 10 and ot.payment_status <> 2)  )  ";

        // 得到双向转诊中正在进行中的订单 (//转出医生24h内没有收到回复 算是已结束, 无法安排床位 或者 用户已确认，也算是已结束)
        String str21 = " (select ot.id from orders ot,transfer_treatment tt where ot.order_type = 2 and ot.user_id = ? and ot.`business_id` = tt.id and tt.is_deleted <> 1 and ((tt.transfer_status >1 and tt.transfer_status < 16) or (tt.transfer_status is null and TIMEDIFF(now(),tt.create_time) <= '24:00:00.000' ))) ";

        // 得到双向转诊中已结束的订单
        String str22 = " (select ot.id from orders ot,transfer_treatment tt where ot.order_type = 2 and ot.user_id = ? and ot.`business_id` = tt.id and tt.is_deleted <> 1 and (tt.transfer_status = 1 or tt.transfer_status >= 16 or (tt.transfer_status is null and TIMEDIFF(now(),tt.create_time) > '24:00:00.000'))) ";

        // 得到外请会诊中进行中的订单（//医生24h内没有收到回复，算是已结束，拒绝 或者 已支付，相当于用户已确认，标记订单结束  ）
        String str3 = " (select ot.id from orders ot,attending_treatment tt where ot.order_type = 3 and ot.user_id = ? and ot.`business_id` = tt.id and ((tt.attending_status > 1 and tt.attending_status < 8 ) or (tt.attending_status is null and TIMEDIFF(now(),tt.create_time) <= '24:00:00.000' ) )) ";

        // 得到预约挂号中未结束的订单
        String str4 = " (select ot.id from orders ot,registered_order tt where ot.order_type = 4 and ot.user_id = ? and ot.`business_id` = tt.id and ( (tt.registered_status = 1 and TIMEDIFF( now(),ADDTIME(tt.registered_date,tt.end_time)) < '00:00:00.000')))";

        // 得到咨询中未结束的订单
        String str51 = " (select ot.id from orders ot,consult_order tt where ot.order_type = 5 and ot.user_id = ? and ot.`business_id` = tt.id and !((tt.consult_status > 16) or (tt.consult_status = 3) or (tt.consult_status = 1 and tt.accept_time is null and TIMEDIFF(now(),tt.create_time) > '48:00:00.000' ) or (tt.consult_status & 4 = 4 and tt.consult_status < 8 and TIMEDIFF(now(),tt.accept_time) > '48:00:00.000' ))) ";
        // 得到咨询中已结束的订单（1.医生手动结束；2.医生接诊后不结束，48小时后系统自动结束；3.医生不接诊，患者也不取消，48小时后系统自动结束, 4-退诊）
        String str52 = " (select ot.id from orders ot,consult_order tt where ot.order_type = 5 and ot.user_id = ? and ot.`business_id` = tt.id and ((tt.consult_status > 16) or (tt.consult_status = 3) or (tt.consult_status = 1 and tt.accept_time is null and TIMEDIFF(now(),tt.create_time) > '48:00:00.000' ) or (tt.consult_status & 4 = 4 and tt.consult_status < 8 and TIMEDIFF(now(),tt.accept_time) > '48:00:00.000' ))) ";

        // 得到随访中未结束的订单
        String str61 = " (select ot.id from orders ot,`follow_up_order` tt where ot.order_type = 6 and ot.user_id = ? and ot.`business_id` = tt.id and (tt.follow_up_status = 1 and TIMEDIFF(now(),tt.create_time) < '24:00:00.000' )) ";
        // 得到随访中已结束的订单(随访开始后24小时自动结束，或者医生手动点击“结束会话”，该记录自动移动到“已完成”)
        String str62 = " (select ot.id from orders ot,`follow_up_order` tt where ot.order_type = 6 and ot.user_id = ? and ot.`business_id` = tt.id and (tt.follow_up_status != 1 or TIMEDIFF(now(),tt.create_time) >= '24:00:00.000')) ";

        // 得到加诊预约中未结束的订单 （）
        String str7 = " (select ot.id from orders ot,additional_registration tt where ot.order_type = 7 and ot.user_id = ? and ot.`business_id` = tt.id and ((tt.payment_status != 2) or (tt.status = 0 or tt.status = 1))  and ( TIMEDIFF( now(),tt.schedule_date) < '24:00:00.000' ))";

        // TODO 处方以处方表的数据为准，列表也是，处方的单独去查找处方数据库，所以下面的暂时弃用
        // 得到门诊缴费订单中未结束的订单 (处方)
        String str81 = " (select ot.id from orders ot,outpatient_order tt where ot.order_type = 8 and ot.user_id = ? and ot.`business_id` = tt.id and tt.outpatient_status = 0  and tt.deleted = 0 and tt.id in (select  max(a.id) from outpatient_order a group by `his_order_no`)) ";
        // 得到门诊缴费订单中结束的订单 (处方)
        String str82 = " (select ot.id from orders ot,outpatient_order tt where ot.order_type = 8 and ot.user_id = ? and ot.`business_id` = tt.id and tt.outpatient_status > 0 and tt.deleted = 0 and tt.id in (select  max(a.id) from outpatient_order a group by `his_order_no`)) ";

        // 远程会诊报告(已完成)(参考：TreatmentReportStatusEnum)
        String str102 = " (select ot.id from orders ot,treatment_report tt where ot.order_type = 10 and ot.user_id = ? and ot.`business_id` = tt.id and tt.`status` = 1 ) ";

        // 处方订单（已经经过type筛选）
        String prescriptionStr = "(select ot.id from orders ot where ot.order_type = 11 and ot.`business_id` in (" + prescriptionIds + ") ) ";
        if (type == 1) {
            sql += " and ( ";
            sql += " id in " + str11;
            params.add(userId);
            sql += " or id in " + str21;
            params.add(userId);
            sql += " or id in " + str51;
            params.add(userId);
            sql += " or id in " + str61;
            params.add(userId);
            if (!Checker.isNone(prescriptionIds)) {
                sql += " or id in " + prescriptionStr;
            }
            sql += " ) ";
        } else if (type == 2) {
            sql += " and ( ";
            sql += " id in " + str12;
            params.add(userId);
            sql += " or id in " + str22;
            params.add(userId);
            sql += " or id in " + str52;
            params.add(userId);
            sql += " or id in " + str62;
            params.add(userId);
            sql += " or id in " + str102;
            params.add(userId);
            if (!Checker.isNone(prescriptionIds)) {
                sql += " or id in " + prescriptionStr;
            }
            sql += " ) ";
        } else {
            return new PagedList<Order>(pageIndex, pageSize, 0, new ArrayList<>());
        }
        sql += " and deleted = 0 ";
        return sqlHelperYwtCenter.getPagedList(
                pageIndex, pageSize, "*", sql, orderBy, Order.class, params.toArray());
    }


    /**
     * 根据条件得到订单ID
     *
     * @param userId          用户ID
     * @param userId          用户手机号
     * @param type            1-进行中，2-已完成
     * @param prescriptionIds 处方IDs（经过type参数筛选后的值）
     * @param pageIndex       当前页数
     * @param pageSize        每页大小
     * @return
     */
    public PagedList<Order> getListByUserId(int userId, String mobile, int type, String prescriptionIds, int pageIndex, int pageSize) {
        String orderBy = "id desc";
        List<Object> params = new LinkedList<>();
        String sql = "";
        // todo 除了问诊，其它订单的类型都需要根据userId和手机号进行匹配
        if (!Checker.isNone(mobile)) {
            sql = " (user_id = ? or patient_mobile = ?) ";
            params.add(userId);
            params.add(mobile.trim());
        } else {
            sql = " user_id = ?  ";
            params.add(userId);
        }

        /**
         * 已完成、已退款、已取消 的状态算是"已完成"，对应type=2
         * */

        // 得到远程会诊中正在进行的订单
        String str11 = " (select ot.id from orders ot where ot.order_type = 1 and ot.user_id = ? and ot.order_status = 10 and ot.payment_status <> 2  )  ";
        // 得到远程会诊中结束的订单
        String str12 = " (select ot.id from orders ot where ot.order_type = 1 and ot.user_id = ? and !(ot.order_status = 10 and ot.payment_status <> 2)  )  ";

        // 得到双向转诊中正在进行中的订单 (//转出医生24h内没有收到回复 算是已结束, 无法安排床位 或者 用户已确认，也算是已结束)
        String str21 = " (select ot.id from orders ot,transfer_treatment tt where ot.order_type = 2 and ot.user_id = ? and ot.`business_id` = tt.id and tt.is_deleted <> 1 and ((tt.transfer_status >1 and tt.transfer_status < 16) or (tt.transfer_status is null and TIMEDIFF(now(),tt.create_time) <= '24:00:00.000' ))) ";

        // 得到双向转诊中已结束的订单
        String str22 = " (select ot.id from orders ot,transfer_treatment tt where ot.order_type = 2 and ot.user_id = ? and ot.`business_id` = tt.id and tt.is_deleted <> 1 and (tt.transfer_status = 1 or tt.transfer_status >= 16 or (tt.transfer_status is null and TIMEDIFF(now(),tt.create_time) > '24:00:00.000'))) ";

        // 得到外请会诊中进行中的订单（//医生24h内没有收到回复，算是已结束，拒绝 或者 已支付，相当于用户已确认，标记订单结束  ）
        String str3 = " (select ot.id from orders ot,attending_treatment tt where ot.order_type = 3 and ot.user_id = ? and ot.`business_id` = tt.id and ((tt.attending_status > 1 and tt.attending_status < 8 ) or (tt.attending_status is null and TIMEDIFF(now(),tt.create_time) <= '24:00:00.000' ) )) ";

        // 得到预约挂号中未结束的订单
        String str4 = " (select ot.id from orders ot,registered_order tt where ot.order_type = 4 and ot.user_id = ? and ot.`business_id` = tt.id and ( (tt.registered_status = 1 and TIMEDIFF( now(),ADDTIME(tt.registered_date,tt.end_time)) < '00:00:00.000')))";

        // 得到咨询中未结束的订单
        String str51 = " (select ot.id from orders ot,consult_order tt where ot.order_type = 5 and ot.user_id = ? and ot.`business_id` = tt.id and !((tt.consult_status > 16) or (tt.consult_status = 3) or (tt.consult_status & 8 = 8) or (tt.consult_status = 1 and tt.accept_time is null and TIMEDIFF(now(),tt.create_time) > '48:00:00.000' ) or (tt.consult_status & 4 = 4 and tt.consult_status < 8 and TIMEDIFF(now(),tt.accept_time) > '48:00:00.000' ))) ";
        // 得到咨询中已结束的订单（1.医生手动结束；2-退诊; 3-取消; 4-医生接诊后不结束; 48小时后系统自动结束; 5-医生不接诊，患者也不取消，48小时后系统自动结束;）
        String str52 = " (select ot.id from orders ot,consult_order tt where ot.order_type = 5 and ot.user_id = ? and ot.`business_id` = tt.id and ((tt.consult_status > 16) or (tt.consult_status = 3) or (tt.consult_status & 8 = 8) or (tt.consult_status = 1 and tt.accept_time is null and TIMEDIFF(now(),tt.create_time) > '48:00:00.000' ) or (tt.consult_status & 4 = 4 and tt.consult_status < 8 and TIMEDIFF(now(),tt.accept_time) > '48:00:00.000' ))) ";

        // 得到随访中未结束的订单
        String str61 = " (select ot.id from orders ot,`follow_up_order` tt where ot.order_type = 6 and ot.user_id = ? and ot.`business_id` = tt.id and (tt.follow_up_status = 1 and TIMEDIFF(now(),tt.create_time) < '24:00:00.000' )) ";
        // 得到随访中已结束的订单(随访开始后24小时自动结束，或者医生手动点击“结束会话”，该记录自动移动到“已完成”)
        String str62 = " (select ot.id from orders ot,`follow_up_order` tt where ot.order_type = 6 and ot.user_id = ? and ot.`business_id` = tt.id and (tt.follow_up_status != 1 or TIMEDIFF(now(),tt.create_time) >= '24:00:00.000')) ";

        // 得到加诊预约中未结束的订单 （）
        String str7 = " (select ot.id from orders ot,additional_registration tt where ot.order_type = 7 and ot.user_id = ? and ot.`business_id` = tt.id and ((tt.payment_status != 2) or (tt.status = 0 or tt.status = 1))  and ( TIMEDIFF( now(),tt.schedule_date) < '24:00:00.000' ))";

        // TODO 处方以处方表的数据为准，列表也是，处方的单独去查找处方数据库，所以下面的暂时弃用
        // 得到门诊缴费订单中未结束的订单 (处方)
        String str81 = " (select ot.id from orders ot,outpatient_order tt where ot.order_type = 8 and ot.user_id = ? and ot.`business_id` = tt.id and tt.outpatient_status = 0  and tt.deleted = 0 and tt.id in (select  max(a.id) from outpatient_order a group by `his_order_no`)) ";
        // 得到门诊缴费订单中结束的订单 (处方)
        String str82 = " (select ot.id from orders ot,outpatient_order tt where ot.order_type = 8 and ot.user_id = ? and ot.`business_id` = tt.id and tt.outpatient_status > 0 and tt.deleted = 0 and tt.id in (select  max(a.id) from outpatient_order a group by `his_order_no`)) ";

        // 远程会诊报告(已完成)(参考：TreatmentReportStatusEnum)
        String str102 = " (select ot.id from orders ot,treatment_report tt where ot.order_type = 10 and ot.user_id = ? and ot.`business_id` = tt.id and tt.`status` = 1 ) ";

        // 处方订单（已经经过type筛选）
        String prescriptionStr = "(select ot.id from orders ot where ot.order_type = 11 and ot.`business_id` in (" + prescriptionIds + ") ) ";
        if (type == 1) {
            sql += " and ( ";
            sql += " id in " + str11;
            params.add(userId);
            sql += " or id in " + str21;
            params.add(userId);
            sql += " or id in " + str51;
            params.add(userId);
            sql += " or id in " + str61;
            params.add(userId);
            if (!Checker.isNone(prescriptionIds)) {
                sql += " or id in " + prescriptionStr;
            }
            sql += " ) ";
        } else if (type == 2) {
            sql += " and ( ";
            sql += " id in " + str12;
            params.add(userId);
            sql += " or id in " + str22;
            params.add(userId);
            sql += " or id in " + str52;
            params.add(userId);
            sql += " or id in " + str62;
            params.add(userId);
            sql += " or id in " + str102;
            params.add(userId);
            if (!Checker.isNone(prescriptionIds)) {
                sql += " or id in " + prescriptionStr;
            }
            sql += " ) ";
        } else {
            return new PagedList<Order>(pageIndex, pageSize, 0, new ArrayList<>());
        }
        sql += " and deleted = 0 ";
        return sqlHelperYwtCenter.getPagedList(
                pageIndex, pageSize, "*", sql, orderBy, Order.class, params.toArray());
    }

    /**
     * 根据ID得到记录
     *
     * @param id
     * @return
     */
    public OutpatientOrder getOutpatientOrderById(int id) {
        return outpatientOrderRepository.findById(id).orElse(null);
    }

    /**
     * 创建远程会诊报告订单
     *
     * @param report
     * @param patient
     * @return
     */
    public Order createTreatmentReportOrder(TreatmentReport report, Patient patient) {
        int orderId = idGenerator.generateOrderId();
        Order order = new Order();
        order.setId(orderId);
        order.setOrderNo(idGenerator.generateOrderNo(""));
        order.setUserId(patient.getUserId());
        order.setPatientMobile(patient.getMobile());
        order.setCreateTime(new Date());
        order.setOrderAmount(BigDecimal.ZERO);
        order.setOrderStatus(OrderStatusEnum.Over.getValue());
        order.setPaymentStatus(PaymentStatusEnum.Pending.getValue());
        order.setRemark("远程会诊报告");
        order.setDeleted(false);
        order.setOrderType(OrderTypeEnum.TREATMENT_REPORT.getValue());
        order.setBusinessId(report.getId());
        order.setDoctorId(report.getFromDoctorId());
        order.setTitle("");

        orderRepository.save(order);
        return order;
    }

    /**
     * 根据ID得到记录
     *
     * @param id
     * @return
     */
    public TreatmentReport getTreatmentReportById(int id) {
        return treatmentReportRepository.findById(id).orElse(null);
    }


    /**
     * 根据hisOrderNo得到最近的一条订单
     *
     * @param hisOrderNo
     * @return
     */
    public Order getOrderByHisOrderNo(String hisOrderNo) {
        return orderRepository.getOneByHisOrderNo(hisOrderNo);
    }


    /**
     * 保存处方需要支付的费用
     *
     * @param orderId       订单Id
     * @param reimbursement 医保报销金额
     * @param total         药品总金额
     * @param individual    个人支付总金额
     * @return
     */
    public ServiceResult savePrescriptionNeedFee(int orderId, int individual, int reimbursement, int total, int userId) {
        ServiceResult serviceResult = new ServiceResult();
        Order order = getOrderById(orderId);

        if (order == null || order.getDeleted()) {
            return serviceResult.failed("订单不存在");
        }

        if (order.getOrderType() != OrderTypeEnum.PRESCRIPTION.getValue() || order.getUserId() != userId) {
            return serviceResult.failed("非法请求");
        }
        /* todo 暂时不需要考虑医保，只需要考虑个人支付金额，而个人支付金额需要存到处方库里面去
        OutpatientOrder outpatientOrder = outpatientOrderRepository.findOne(order.getBusinessId());

        if (outpatientOrder == null || outpatientOrder.getDeleted()) {
            return serviceResult.failed("该处方订单不存在");
        }

        //进行数据处理
        outpatientOrder.setIndividual(individual);
        outpatientOrder.setTotal(total);
        outpatientOrder.setReimbursement(reimbursement);
        outpatientOrderRepository.save(outpatientOrder);
        return serviceResult.succeed("处理成功");
        */
        return drugProvider.savePrescriptionFee(individual, order.getBusinessId(), order.getUserId());


    }

    /**
     * 根据处方ID得到订单ID
     *
     * @param prescriptionId
     * @return
     */
    public int getOrderByPrescriptionId(int prescriptionId) {
        Order order = orderRepository.getOrder(prescriptionId, OrderTypeEnum.PRESCRIPTION.getValue());
        return !Checker.isNone(order) ? order.getId() : 0;
    }

    public TreatmentOrderView getTreatmentOrderViewByTreatmentId(int treatmentId) {
        return treatmentOrderViewRepository.findById(treatmentId).orElse(null);
    }

    public TransferOrderView getTransferOrderViewByTransferId(int transferId) {
        return transferOrderViewRepository.findById(transferId).orElse(null);
    }

    public AttendingOrderView getAttendingOrderViewByAttendingId(int attendingId) {
        return attendingOrderViewRepository.findById(attendingId).orElse(null);
    }


    public String getAttendingStatusName(Date attendingCreateTime, int attendingStatus) {

        Calendar ca2 = Calendar.getInstance();

        if (attendingStatus == 0) {
            Calendar ca1 = Calendar.getInstance();
            ca1.setTime(attendingCreateTime);
            ca1.add(Calendar.DATE, 1);

            if (ca2.after(ca1)) {
                //医生24h内没有收到回复
                return "已结束";
            }
        } else if ((attendingStatus & AttendingStatusEnum.Refuse.getValue()) == AttendingStatusEnum.Refuse.getValue()) {
            //主诊医生拒绝订单
            return "已结束";
        } else if ((attendingStatus & AttendingStatusEnum.AlreadyPay.getValue()) == AttendingStatusEnum.AlreadyPay.getValue()) {
            //已支付，相当于用户已确认，标记订单结束
            return "已结束";
        } else if ((attendingStatus & AttendingStatusEnum.InformPatient.getValue()) == AttendingStatusEnum.InformPatient.getValue()) {
            //已通知用户，用户未确认（或支付），标记订单为待确认状态
            return "待确认";
        }

        return "";
    }


    public List<Order> getOrderListByPrescriptionInfoIds(String prescriptionInfoIds) {
        int count = prescriptionInfoIds.split(",").length;

        StringBuilder sqlBuilder = new StringBuilder("");
        sqlBuilder.append("select * from orders where order_type = 11 and deleted = 0 and business_id in (")
                .append(prescriptionInfoIds)
                .append(") order by id desc limit ")
                .append(count)
                .append(";");
        return jdbcTemplate.query(sqlBuilder.toString(), new BeanPropertyRowMapper<>(Order.class));
    }

    public ServiceResult addAdditionalRecord(int acceptDoctorId, String acceptTime, String returnTime, int doctorId, int orderId) {
        ServiceResult serviceResult = new ServiceResult();
        try {
            Order order = getOrderById(orderId);
            if (order == null || order.getDeleted() || order.getOrderType() != OrderTypeEnum.TRANSFER.getValue()) {
                return serviceResult.failed("订单不存在");
            }
            TransferTreatment transferTreatment = getTransferTreatmentById(order.getBusinessId());
            if (transferTreatment == null) {
                return serviceResult.failed("转诊订单不存在");
            }

            if (doctorId != transferTreatment.getToDoctorId()) {
                return serviceResult.failed("抱歉，上级医生才能增加补录信息");
            }
            DoctorInfo doctorInfo = doctorService.getDoctorInfoById(acceptDoctorId);
            transferTreatment.setAdditionalAcceptDoctorId(acceptDoctorId);
            transferTreatment.setAdditionalAcceptDoctorName(doctorInfo == null ? "" : Checker.getStringValue(doctorInfo.getName()));
            transferTreatment.setAdditionalAcceptTime(DateUtil.parseDate(acceptTime, "yyyy-MM-dd HH:mm"));
            transferTreatment.setAdditionalReturnTime(DateUtil.parseDate(returnTime, "yyyy-MM-dd HH:mm"));
            transferTreatmentRepository.save(transferTreatment);
            return serviceResult.succeed();
        } catch (Exception e) {
            logger.error("OrderService#addAdditionalRecord(acceptDoctorId={} , acceptTime={} , returnTime={} , " +
                            "doctorId={} , orderId={} ):\n {}", acceptDoctorId, acceptTime, returnTime, doctorId, orderId,
                    e.getMessage(), e);
            return serviceResult.failed(e.getMessage());
        }
    }

    public ServiceResult getAdditionalRecord(int orderId) {
        ServiceResult serviceResult = new ServiceResult();
        try {
            Order order = getOrderById(orderId);
            if (order == null || order.getDeleted() || order.getOrderType() != OrderTypeEnum.TRANSFER.getValue()) {
                return serviceResult.failed("订单不存在");
            }
            TransferTreatment transferTreatment = getTransferTreatmentById(order.getBusinessId());
            if (transferTreatment == null) {
                return serviceResult.failed("转诊订单不存在");
            }
            Map<String, Object> map = new HashMap<>();
            int acceptDoctorId = Checker.getIntegerValue(transferTreatment.getAdditionalAcceptDoctorId());
            map.put("acceptDoctorId", acceptDoctorId);
            Date acceptTime = transferTreatment.getAdditionalAcceptTime();
            Date returnTime = transferTreatment.getAdditionalReturnTime();
            map.put("acceptTime", acceptTime == null ? "" : DateUtil.convertToString(acceptTime, "yyyy-MM-dd HH:mm"));
            map.put("returnTime", returnTime == null ? "" : DateUtil.convertToString(returnTime, "yyyy-MM-dd HH:mm"));
            map.put("acceptDoctorName", Checker.getStringValue(transferTreatment.getAdditionalAcceptDoctorName()));
            DoctorInfo doctorInfo = doctorService.getDoctorInfoById(acceptDoctorId);
            map.put("acceptDoctorDept", doctorInfo == null ? "" : Checker.getStringValue(doctorInfo.getDeptName()));
            map.put("acceptDoctorHospital", doctorInfo == null ? "" : Checker.getStringValue(doctorInfo.getHospitalName()));
            map.put("acceptDoctorTitle", doctorInfo == null ? "" : Checker.getStringValue(doctorInfo.getTitle()));
            return serviceResult.succeed(map);
        } catch (Exception e) {
            logger.error("OrderService#getAdditionalRecord(orderId={} ):\n {}", orderId, e.getMessage(), e);
            return serviceResult.error(e.getMessage());
        }
    }

    private void trySendingVoiceMsg(String phone) {
        // 总值医生的手机号
        String targetPhone = configServiceProvider.getVoiceSmsPhone();
        if (Checker.isNone(targetPhone)) {
            logger.info("OrderService#sendVoiceMsg(): 发送语音电话失败，电话号码为空");
            return;
        }
        if (!Checker.getStringValue(phone).equals(targetPhone)) {
            logger.info("OrderService#sendVoiceMsg(phone={}): 非总值电话 {}，不发送电话语音", phone, targetPhone);
            return;
        }
        String tplId = configServiceProvider.getVoiceSmsTplId();
        if (Checker.isNone(tplId)) {
            logger.info("OrderService#sendVoiceMsg(): 发送语音电话失败，模板为空");
            return;
        }
        try {
            SendVoiceSmsRequest request = SendVoiceSmsRequest.newBuilder()
                    .setPhone(targetPhone)
                    .setTemplateId(tplId)
                    .build();
            SendVoiceSmsResponse response = voiceSmsServiceBlockingStub.sendVoiceSms(request);
            logger.info("OrderService#sendVoiceMsg: 发送语音电话，phone {} tpl {} code {} msg {}", targetPhone, tplId,
                    response.getCode(), response.getMsg());
        } catch (Exception e) {
            logger.error("OrderService#sendVoiceMsg():发送语音电话出错\n {}", e.getMessage(), e);
        }
    }

    /**
     * 修改orders表的pay_code字段，如果白云、太和外转处方和数据库配置的不一样，那么就以数据库配置的为准对orders表进行修改
     *
     * @param request
     * @return
     */
    public UpdatePayCodeResponse updatePayCode(UpdatePayCodeRequest request) {
        UpdatePayCodeResponse.Builder builder = UpdatePayCodeResponse.newBuilder();
        builder.setCode(ResultCode.SUCCEED_VALUE);
        builder.setInfo("处理成功");
        try {
            int orderId = Checker.getIntegerValue(request.getOrderId());
            String orderNo = Checker.getStringValue(request.getOrderNo());
            Order order = null;
            if (orderId > 0) {
                order = orderRepository.getOrderById(orderId);
            } else if (!Checker.isNone(orderNo)) {
                order = orderRepository.getOrderByOrderNo(orderNo);
            }
            if (!Checker.isNone(order)) {
                // 目前只有外转处方需要用到修改pay_code
                if (order.getOrderType() == OrderTypeEnum.PRESCRIPTION.getValue()) {
                    // 判断 orders 表的pay_code 是否和 ywt_center库config表type为18的记录
                    String configPayCode = configServiceProvider.getOpenHisPushConfigPayCode();
                    if (!order.getPayCode().equals(configPayCode)) {
                        // 判断是否是外转处方
                        boolean isByAndThPrescription = drugProvider.checkIsByAndThPrescription(order.getBusinessId());
                        if (isByAndThPrescription) {
                            order.setPayCode(configPayCode);
                            orderRepository.save(order);
                        }
                    }
                }
            }
        } catch (Exception e) {
            builder.setCode(ResultCode.APP_ERROR_VALUE).setInfo(e.getMessage());
            logger.error("OrderService#updatePayCode(): {}", e.getMessage(), e);
        }
        return builder.build();
    }

    public GetCommonOrderBillResponse getCommonOrderBill(GetCommonOrderBillRequest request) {

        GetCommonOrderBillResponse.Builder respBuilder = GetCommonOrderBillResponse.newBuilder();
        try {
            String billDate = Checker.getStringValue(request.getBillDate());
            int type = Checker.getIntegerValue(request.getType());
            int hospitalId = Checker.getIntegerValue(request.getHospitalId());
            if (Checker.isNone(billDate) || billDate.trim().length() != 8) {
                throw new YwtCommonException(YwtCommonRespCode.P_ERR, "账单日期参数不正确");
            }
            String data = "";
            // type(参考ywt_center.config id 为22的记录)：服务类型，1-互联网就诊，2-问诊订单，3-随访订单，4-会诊订单，5-转诊订单，6-外诊订单
            switch (type) {
                case 1:
                    data = offlineConsultationService.getOrderBill(billDate, hospitalId);
                    break;
                case 2:
                    data = consultingService.getOrderBill(billDate, hospitalId);
                    break;
                case 3:
                    data = getFollowUpOrderBill(billDate, hospitalId);
                    break;
                case 4:
                    data = getTreatmentOrderBill(billDate, hospitalId);
                    break;
                case 5:
                    data = getTransferTreatmentOrderBill(billDate, hospitalId);
                    break;
                case 6:
                    data = getAttendingTreatmentOrderBill(billDate, hospitalId);
                    break;
                default:
                    break;
            }
            respBuilder.setCode(0).setData(data);
        } catch (YwtCommonException e) {
            respBuilder.setCode(ResultCode.APP_ERROR_VALUE).setInfo(e.getMessage());
        } catch (Exception e) {
            logger.error("getCommonOrderBill(): {}", e.getMessage(), e);
            respBuilder.setCode(ResultCode.APP_ERROR_VALUE).setInfo(e.getMessage());
        }
        return respBuilder.build();
    }


    private String getFollowUpOrderBill(String billDate, int hospitalId) {
        String csvData = "";
        try {
            // 没有发生业务金额，所以数据均为空
            String[] fileHeader = new String[]{
                    "业务编码ID", "订单号", "支付流水号", "业务类型", "金额", "支付渠道标识", "支付渠道说明", "下单时间", "支付时间", "退款金额", "退款时间", "退款流水号", "医院"
            };
            StringBuffer stringBuffer = new StringBuffer();
            CSVPrinter csvPrinter = new CSVPrinter(stringBuffer, CSVFormat.DEFAULT.withHeader(fileHeader));
            csvPrinter.flush();
            csvData = stringBuffer.toString();
        } catch (Exception e) {
            logger.error("OrderService#getFollowUpOrderBill(): {}", e.getMessage(), e);
        }
        return csvData;
    }

    private String getTreatmentOrderBill(String billDate, int hospitalId) {
        String csvData = "";
        try {
            // 该业务表里面没有订单支付时间，而且目前表的数据都是测试数据，所以暂时通过这种形式展示出来
            String[] fileHeader = new String[]{
                    "业务编码ID", "订单号", "支付流水号", "业务类型", "金额", "支付渠道标识", "支付渠道说明", "下单时间", "支付时间", "退款金额", "退款时间", "退款流水号", "医院"
            };
            StringBuffer stringBuffer = new StringBuffer();
            CSVPrinter csvPrinter = new CSVPrinter(stringBuffer, CSVFormat.DEFAULT.withHeader(fileHeader));
            csvPrinter.flush();
            csvData = stringBuffer.toString();
        } catch (Exception e) {
            logger.error("OrderService#getTreatmentOrderBill(): {}", e.getMessage(), e);
        }
        return csvData;
    }

    private String getTransferTreatmentOrderBill(String billDate, int hospitalId) {
        String csvData = "";
        try {
            // 没有发生业务金额，所有数据均为空
            String[] fileHeader = new String[]{
                    "业务编码ID", "订单号", "支付流水号", "业务类型", "金额", "支付渠道标识", "支付渠道说明", "下单时间", "支付时间", "退款金额", "退款时间", "退款流水号", "医院"
            };
            StringBuffer stringBuffer = new StringBuffer();
            CSVPrinter csvPrinter = new CSVPrinter(stringBuffer, CSVFormat.DEFAULT.withHeader(fileHeader));
            csvPrinter.flush();
            csvData = stringBuffer.toString();
        } catch (Exception e) {
            logger.error("OrderService#getTransferTreatmentOrderBill(): {}", e.getMessage(), e);
        }
        return csvData;
    }

    private String getAttendingTreatmentOrderBill(String billDate, int hospitalId) {
        String csvData = "";
        try {
            // 没有发生业务金额，所有数据均为空
            String[] fileHeader = new String[]{
                    "业务编码ID", "订单号", "支付流水号", "业务类型", "金额", "支付渠道标识", "支付渠道说明", "下单时间", "支付时间", "退款金额", "退款时间", "退款流水号", "医院"
            };
            StringBuffer stringBuffer = new StringBuffer();
            CSVPrinter csvPrinter = new CSVPrinter(stringBuffer, CSVFormat.DEFAULT.withHeader(fileHeader));
            csvPrinter.flush();
            csvData = stringBuffer.toString();
        } catch (Exception e) {
            logger.error("OrderService#getAttendingTreatmentOrderBill(): {}", e.getMessage(), e);
        }
        return csvData;
    }
}
