package com.ywt.outpatient.controllers;

import com.ywt.biz.common.constant.YwtCommonRespCode;
import com.ywt.biz.common.enums.SexEnum;
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.StringHelper;
import com.ywt.biz.common.util.serializers.JsonSerializer;
import com.ywt.gapi.Result;
import com.ywt.gapi.ResultCode;
import com.ywt.gapi.doctor.*;
import com.ywt.gapi.drug.*;
import com.ywt.gapi.drug.PrescriptionInfo;
import com.ywt.gapi.order.*;
import com.ywt.gapi.order.GetOutpatientDetailRequest;
import com.ywt.gapi.order.GetOutpatientDetailResponse;
import com.ywt.gapi.order.OutpatientOrder;
import com.ywt.gapi.sf.*;
import com.ywt.gapi.system.Address;
import com.ywt.gapi.system.GetAddressRequest;
import com.ywt.gapi.system.GetAddressResponse;
import com.ywt.gapi.system.SystemService;
import com.ywt.gapi.taihe.outpaitent.*;
import com.ywt.gapi.taihe.outpaitent.GetOutpatientListRequest;
import com.ywt.gapi.taihe.outpaitent.GetOutpatientListResponse;
import com.ywt.gapi.third.taihe.*;
import com.ywt.gapi.user.*;
import com.ywt.outpatient.controllers.taihe.DHOutpatientController;
import com.ywt.outpatient.core.BaseResponse;
import com.ywt.outpatient.core.utils.BizUtil;
import com.ywt.outpatient.core.utils.IdCardUtil;
import com.ywt.outpatient.core.Constant;
import com.ywt.outpatient.domain.models.enums.PresCancelStatusEnum;
import com.ywt.outpatient.service.common.TaiheProvider;
import com.ywt.outpatient.service.rpc.common.ServiceResult;
import com.ywt.outpatient.service.web.UserSrv;
import com.ywt.outpatient.service.common.FileProvider;
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.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController("/outpatient")
@RequestMapping({"/outpatient"})
public class OutpatientController {

    private static Logger logger = LoggerFactory.getLogger(OutpatientController.class);

    @DubboReference
    private OrderService orderServiceBlockingStub;

    @DubboReference
    private UserService userServiceBlockingStub;

    @Autowired
    private TaiheProvider taiheProvider;

    @Autowired
    private UserSrv userSrv;

    @Autowired
    private FileProvider fileProvider;

    @DubboReference
    private DrugService drugServiceBlockingStub;

    @DubboReference
    private DoctorService doctorServiceBlockingStub;

    @DubboReference
    private SystemService systemServiceBlockingStub;

    @DubboReference
    private TaiheService taiheServiceBlockingStub;

    @DubboReference
    private TaiheOutpatientService taiheOutpatientServiceBlockingStub;

    @DubboReference
    private SFService sfServiceBlockingStub;

    @DubboReference
    private SFInternalService sfInternalServiceBlockingStub;

    @Value("#{new Boolean('${ywt.env.test:false}')}")
    private boolean isTest;

    /**
     * 门诊缴费（处方）单详情
     * <p>
     * body: orderId 订单Id
     * body: preBizNo 处方编号，对应处方表preBizNo字段
     *
     * @return
     */
    @RequestMapping(value = {"/getOutpatientDetail"}, method = RequestMethod.POST)
    public @ResponseBody
    BaseResponse getOutpatientDetail(@RequestBody Map<String, Object> data) {
        BaseResponse response = new BaseResponse();

        try {
            int orderId = (int) data.getOrDefault("orderId", "0");
            String preBizNo = (String) data.getOrDefault("preBizNo", "");

            if (Checker.isNone(preBizNo)) {
                return response.failed(BaseResponse.PARAMETER_ERROR, "invalid preBizNo");
            }
            Map<String, Object> map = new HashMap<>();
            /* TODO 暂时不考虑处方接入his，所以此代码先注释
            if (orderId > 0) {
                GetOutpatientDetailRequest reqt = GetOutpatientDetailRequest.newBuilder()
                        .setOrderId(orderId)
                        .build();
                GetOutpatientDetailResponse rest = orderServiceBlockingStub.getOutpatientDetail(reqt);
                Result result = rest.getResult();
                if (result.getCode() == ResultCode.SUCCEED) {
                    OutpatientOrder order = rest.getOrder();
                    map.put("orderId", order.getOrderId());
                    map.put("orderNo", order.getOrderNo());
                    map.put("createTime", DateUtil.convertTimestampToDateString(order.getCreateTime(), "yyyy年MM月dd日 HH:mm"));
                    map.put("hospitalId", order.getHospitalId());
                    map.put("hospitalName", order.getHospitalName());
                    map.put("deptCode", order.getDeptCode());
                    map.put("deptName", order.getDeptName());
                    map.put("doctorCode", order.getDoctorCode());
                    map.put("doctorName", order.getDoctorName());
                    map.put("total", order.getTotal() / 100d);
                    map.put("reimbursement", order.getReimbursement() / 100d);
                    map.put("individual", order.getIndividual() / 100d);
                    map.put("amount", order.getIndividual());
                    map.put("userId", order.getUserId());
                    map.put("hisPatientId", order.getHisPatientId());
                    map.put("payName", order.getPayName());
                    // map.put("patientName", order.getPatientName());
                    // map.put("patientAge", order.getPatientAge());
                    // map.put("patientSex", SexEnum.getSexDisplayName(order.getPatientSex()));
                    // map.put("paymentStatus", order.getPaymentStatus());
                    // map.put("outpatientStatus", order.getOutpatientStatus());
                }
            }
            */
            GetPrescriptionRequest req = GetPrescriptionRequest.newBuilder().setBizNo(preBizNo).build();
            GetPrescriptionResponse res = drugServiceBlockingStub.getPrescription(req);

            if (res.getCode() == ResultCode.SUCCEED_VALUE) {
                PrescriptionInfo info = res.getPrescriptionInfo();
                //处方表ID
                map.put("preId", info.getPrescriptionId());
                map.put("patientName", info.getPatientName());
                String ageStr = Checker.getStringValue(info.getPatientAge());
                if (!Checker.isNone(ageStr) && !ageStr.contains("岁")) {
                    ageStr = ageStr + "岁";
                }
                map.put("patientSex", info.getPatientSex());
                map.put("patientAge", ageStr);
                map.put("patientMobile", info.getPatientMobile());
                map.put("diagnose", info.getDiagnose());
                map.put("allergicHistory", info.getAllergicHistory());
                map.put("description", info.getDescription());
                // 药品总金额
                map.put("total", String.format("%.2f元", info.getTotalPrice() / 100d));
                // 个人支付总金额（药品总金额 - 医保 + 运费）
                // map.put("individual", String.format("%.2f元", info.getIndividual() / 100d));
                map.put("amount", info.getTotalPrice());
                // 医保
                // map.put("reimbursement", 0);
                // map.put("reimbursementStr", "0.00元");
                // int doctorId = info.getDoctorId();
                // map.put("doctorId", doctorId);
                // map.put("userId", info.getUserId());

                /*
                try {
                    GetDoctorRequest request = GetDoctorRequest.newBuilder().setDoctorId(doctorId).build();
                    GetDoctorResponse resp = doctorServiceBlockingStub.getDoctor(request);
                    Result result = resp.getResult();
                    if (result.getCode() == ResultCode.SUCCEED) {
                        com.ywt.gapi.user.DoctorInfo doctorInfo = resp.getDoctorInfo();
                        map.put("hospitalId", doctorInfo.getHospitalIds());
                        map.put("hospitalName", doctorInfo.getHospital());
                        map.put("deptId", doctorInfo.getDeptIds());
                        map.put("deptName", doctorInfo.getDept());
                        map.put("doctorName", doctorInfo.getName());
                    }
                } catch (Exception e) {
                    logger.error("根据医生ID获取医生信息接口出错,doctorId:" + doctorId, e.getMessage(), e);
                }
                */

                // map.put("doctorSignId", info.getDoctorSignId());

                // 取药方式，0-待选择取药方式，1-快递 2-自取
                map.put("deliveryMethod", info.getDeliveryMethod());
                // 处方订单状态
                int status = info.getStatus();
                map.put("status", status);

                String statusStr = info.getStatusStr();

                // 拓展状态，位运算，1-是否报到，2-是否发药，4-是否打印发票
                int extStatus = info.getExtStatus();
                map.put("registerStatus", (extStatus & 1) == 1 ? 1 : 0);
                map.put("dispensingStatus", (extStatus & 2) == 2 ? 1 : 0);
                // 是否需要打印发票，0-不需要，1-需要
                map.put("needPrintStatus", info.getNeedPrintStatus());
                map.put("needPrintStatusStr", info.getNeedPrintStatus() == 1 ? "需要" : "不需要");

                // todo 如果是自取，那报到之后给下面的提示
                if (status == 2 && info.getDeliveryMethod() == 2 && extStatus == 1) {
                    statusStr = "配药中，您的取药窗口是1号窗！";
                }
                map.put("statusStr", statusStr);
                //运费
                int freight = Checker.getIntegerValue(info.getFreight());
                map.put("freight", freight);
                map.put("freightStr", String.format("%.2f", freight / 100d));
                // 预计送达时间 （调顺丰接口计算出来的）
                String predictArriveTime = "";
                if (info.getDeliveryMethod() == 1) {
                    // TODO 调顺丰接口计算预计送达时间
                    predictArriveTime = "";
                }
                map.put("predictArriveTime", predictArriveTime);
                // 完成时间
                String finishTime = info.getFinshTime() == 0 ? "" : DateUtil.convertTimestampToDateString(info.getFinshTime(), "yyyy年M月d日");
                map.put("finishTime", finishTime);
                // 药店名称
                map.put("pharmacyName", info.getPharmacyName());
                // 药店的地址
                map.put("pharmacyAddress", info.getPharmacyAddress());
                // 取药二维码  ywtac://patient_checkin/${处方号}
                map.put("qrCodeUrl", String.format(Constant.TAKE_MEDICINE_CODE_URL, info.getPrescriptionId() + ""));
                // 配送号
                map.put("arriveNo", info.getSendNo());

                int addressId = info.getAddressId();
                String address = "";    //收货地址
                String contact = "";    //收货联系人
                String mobile = "";      //收货手机号
                if (addressId > 0) {
                    GetAddressRequest getAddressRequest = GetAddressRequest.newBuilder().setAddressId(addressId).build();
                    GetAddressResponse getAddressResponse = systemServiceBlockingStub.getAddress(getAddressRequest);
                    Result reslt = getAddressResponse.getResult();
                    if (reslt.getCode() == ResultCode.SUCCEED) {
                        Address ads = getAddressResponse.getAddress();
                        if (!Checker.isNone(ads)) {
                            address = ads.getProvince() + ads.getCity() + ads.getArea() + ads.getAddress();
                            contact = ads.getContact();
                            mobile = ads.getMobile();
                        }
                    }
                }
                map.put("address", address);
                map.put("contact", contact);
                map.put("mobile", mobile);
                //获取医生签名
                String signUrl = "";
                GetDoctorSignRequest getDoctorSignRequest = GetDoctorSignRequest.newBuilder().setId(info.getDoctorSignId()).build();
                GetDoctorSignResponse getDoctorSignResponse = doctorServiceBlockingStub.getDoctorSign(getDoctorSignRequest);
                Result results = getDoctorSignResponse.getResult();

                if (results.getCode() == ResultCode.SUCCEED) {
                    DoctorSign doctorSign = getDoctorSignResponse.getSign();
                    signUrl = doctorSign.getSignUrl();
                }
                map.put("doctorSignUrl", signUrl);
                List<Object> objLst = new ArrayList<>();
                Map<String, List<Map<String, Object>>> drugMap = new HashMap<>();
                // 这里需要按group字段分组（group 的值不会为0）
                if (info.getDrugsList() != null) {
                    for (PrescriptionInfo.PrescriptionDrugInfo drug : info.getDrugsList()) {

                        int group = drug.getGroup();
                        Map<String, Object> item = new HashMap<>();
                        item.put("drugName", drug.getDrugName());   //药品名称
                        item.put("spec", drug.getDrugSpec());       //药品规格
                        item.put("quantity", drug.getQuantity());   //药品数量
                        item.put("unit", drug.getUnits());          //整包装单位
                        item.put("frequency", drug.getFrequency()); //频次
                        item.put("eachDose", drug.getOneDosage());  //单次服用剂量
                        item.put("eachDoseUnit", drug.getOneDosageUnit());//单次服用剂量单位
                        String usage = !Checker.isNone(drug.getUsage()) ? drug.getUsage() : drug.getUsageCode();
                        item.put("usage", usage);         //用法,数据库里面UsageCode字段存值，UsageDetail字段的值都为空
                        item.put("course", drug.getCourse());       //疗程，单位：天
                        item.put("total", String.format("%.2f元", drug.getTotal() / 100d));//总价
                        item.put("group", group);                   //组数
                        item.put("combination", drug.getCombination());//是否为同组药(1-是，0-否)
                        item.put("remark", drug.getRemark());       //备注

                        if (group != 0) {
                            String groupStr = group + "";
                            if (drugMap.containsKey(groupStr)) {
                                List<Map<String, Object>> drugList = drugMap.get(groupStr);
                                drugList.add(item);
                            } else {
                                List<Map<String, Object>> drugList = new LinkedList<>();
                                drugList.add(item);
                                drugMap.put(groupStr, drugList);
                            }
                        }
                    }

                    Iterator<Map.Entry<String, List<Map<String, Object>>>> entries = drugMap.entrySet().iterator();
                    while (entries.hasNext()) {
                        Map.Entry<String, List<Map<String, Object>>> entry = entries.next();
                        String key = entry.getKey();
                        List<Map<String, Object>> lst = entry.getValue();
                        Map objMap = new HashMap();
                        objMap.put("group", key);
                        objMap.put("drugList", lst);

                        objLst.add(objMap);
                    }
                }
                map.put("drugLists", objLst);
                return response.succeed("处理成功", map);
            }
            return response.failed(BaseResponse.APP_ERROR, "系统错误");
        } catch (Exception e) {
            logger.error("getOutpatientDetail(): {}", e.getMessage(), e);
            return response.failed(BaseResponse.APP_EXCEPTION, e.getMessage());
        }
    }

    /**
     * 获取太和门诊缴费列表
     *
     * @param reqBody
     * @return
     */
    @RequestMapping({"/taihe/list"})
    public @ResponseBody
    BaseResponse getTaiheList(@RequestBody Map<String, Object> reqBody) {
        BaseResponse response = new BaseResponse();
        Integer pageIndex = (Integer) reqBody.getOrDefault("pageIndex", 0);
        Integer pageSize = (Integer) reqBody.getOrDefault("pageSize", 0);

        if (pageIndex < 1) {
            pageIndex = 1;
        }
        if (pageSize < 1 || pageSize > 100) {
            pageSize = 20;
        }

        try {
            GetOutpatientListRequest req = GetOutpatientListRequest.newBuilder()
                    .setPageIndex(pageIndex)
                    .setPageSize(pageSize)
                    .setUserId(userSrv.getCurrentUserIdWrapped())
                    .build();
            GetOutpatientListResponse res = taiheOutpatientServiceBlockingStub.getOutpatientList(req);

            if (res.getCode() == ResultCode.SUCCEED_VALUE) {
                List<Map<String, Object>> lst = new LinkedList<>();
                Map<String, Object> map;

                for (com.ywt.gapi.taihe.outpaitent.OutpatientOrder order : res.getOrderList()) {
                    map = new HashMap<>();
                    map.put("orderId", order.getOrderId());
                    map.put("orderNo", order.getOrderNo());
                    map.put("createTime", DateUtil.convertTimestampToDateString(order.getCreateTime(), "yyyy年MM月dd日 HH:mm"));
                    map.put("hospitalId", order.getHospitalId());
                    map.put("hospitalName", order.getHospitalName());
                    map.put("deptCode", order.getDeptCode());
                    map.put("deptName", order.getDeptName());
                    map.put("doctorCode", order.getDoctorCode());
                    map.put("doctorName", order.getDoctorName());
                    map.put("total", order.getTotal() / 100d);
                    map.put("reimbursement", order.getReimbursement() / 100d);
                    map.put("individual", order.getIndividual() / 100d);
                    map.put("paymentStatus", order.getPaymentStatus());
                    map.put("outpatientStatus", order.getOutpatientStatus());
                    map.put("userId", order.getUserId());
                    map.put("hisPatientId", order.getHisPatientId());
                    map.put("payName", order.getPayName());
                    map.put("outpatientStatusName", order.getStatusName());
                    lst.add(map);
                }

                Map<String, Object> data = new HashMap<>();
                data.put("list", lst);
                data.put("count", res.getCount());
                data.put("totalPage", res.getTotalPage());
                return response.succeed(data);
            }
            return response.failedWithAppError(res.getMsg());
        } catch (Exception e) {
            logger.error("getTaiheList({}): {}", reqBody, e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 太和门诊缴费单详情
     *
     * @param reqBody
     * @return
     */
    @RequestMapping({"/taihe/detail"})
    public @ResponseBody
    BaseResponse getTaiheOutpatientDetail(@RequestBody Map<String, Object> reqBody) {
        BaseResponse response = new BaseResponse();
        Integer orderId = (Integer) reqBody.getOrDefault("orderId", 0);//订单Id

        if (orderId < 1) {
            return response.failedWithParameterError("invalid orderId");
        }

        try {
            com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailRequest req =
                    com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailRequest.newBuilder()
                            .setOrderId(orderId)
                            .build();
            com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailResponse res = taiheOutpatientServiceBlockingStub.getOutpatientDetail(req);

            if (res.getCode() == ResultCode.SUCCEED_VALUE) {
                com.ywt.gapi.taihe.outpaitent.OutpatientOrder order = res.getOrder();
                Map<String, Object> map = new HashMap<>();
                map.put("orderId", order.getOrderId());
                map.put("orderNo", order.getOrderNo());
                map.put("createTime", DateUtil.convertTimestampToDateString(order.getCreateTime(), "yyyy年MM月dd日 HH:mm"));
                map.put("hospitalId", order.getHospitalId());
                map.put("hospitalName", order.getHospitalName());
                map.put("deptCode", order.getDeptCode());
                map.put("deptName", order.getDeptName());
                map.put("doctorCode", order.getDoctorCode());
                map.put("doctorName", order.getDoctorName());
                map.put("total", order.getTotal() / 100d);
                map.put("reimbursement", order.getReimbursement() / 100d);
                map.put("individual", order.getIndividual() / 100d);
                map.put("amount", order.getIndividual());
                map.put("paymentStatus", order.getPaymentStatus());
                map.put("outpatientStatus", order.getOutpatientStatus());
                map.put("userId", order.getUserId());
                map.put("hisPatientId", order.getHisPatientId());
                map.put("payName", order.getPayName());
                map.put("patientName", order.getPatientName());
                map.put("patientAge", order.getPatientAge());
                map.put("patientSex", SexEnum.getSexDisplayName(order.getPatientSex()));
                map.put("express", 1);//express   1-可以快递   0-不可以
                return response.succeed(map);
            }

            return response.failedWithAppError(res.getMsg());
        } catch (Exception e) {
            logger.error("getTaiheOutpatientDetail({}): {}", reqBody, e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 太和医保试算接口
     * <p>
     * body: orderId       订单Id
     * body: insuranceType 医保类型
     *
     * @return
     */
    @RequestMapping(value = {"/taihe/insurance/cal"}, method = RequestMethod.POST)
    public @ResponseBody
    BaseResponse calInsurance(@RequestBody Map<String, Object> reqBody) {
        BaseResponse response = new BaseResponse();
        try {
            int orderId = (int) reqBody.getOrDefault("orderId", 0);
            int insuranceType = (int) reqBody.getOrDefault("insuranceType", 0);
            return calInsuranceCommon(orderId, insuranceType);
        } catch (Exception e) {
            logger.error("calInsurance({}): {}", reqBody, e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 医保试算公共类
     *
     * @param orderId
     * @param insuranceType
     * @return
     */
    public BaseResponse calInsuranceCommon(int orderId, int insuranceType) {
        BaseResponse response = new BaseResponse();

        if (orderId < 1) {
            return response.failedWithParameterError("invalid orderId");
        }

        String insureKey;
        String insureBizType;
        String insureTreatmentType;

        switch (insuranceType) {
            case 1:
                //职工医保
                insureKey = "101";
                insureBizType = "11";
                insureTreatmentType = "110";
                break;
            case 2:
                //生育医保(一般产检)
                insureKey = "102";
                insureBizType = "51";
                insureTreatmentType = "551";
                break;
            case 3:
                //居民医保
                insureKey = "101";
                insureBizType = "11";
                insureTreatmentType = "110";
                break;
            case 4:
                //门诊慢性病医保(糖尿病)
                insureKey = "103";
                insureBizType = "13";
                insureTreatmentType = "131";
                break;
            case 5:
                //慢性病医保(高血压)
                insureKey = "103";
                insureBizType = "13";
                insureTreatmentType = "132";
                break;
            default:
                return response.failedWithParameterError("invalid insuranceType");
        }

        try {
            GetOutpatientDetailRequest getDetailReq = GetOutpatientDetailRequest.newBuilder()
                    .setOrderId(orderId)
                    .build();
            GetOutpatientDetailResponse getDetailRes = orderServiceBlockingStub.getOutpatientDetail(getDetailReq);
            Result getDetailResult = getDetailRes.getResult();

            if (getDetailResult.getCode() != ResultCode.SUCCEED) {
                return response.failedWithAppError(getDetailResult.getInfo());
            }

            OutpatientOrder outpatientOrder = getDetailRes.getOrder();
            // 医保试算
            CalInsuranceResponse res = taiheProvider.calInsurance(outpatientOrder.getHisPatientId(),
                    DateUtil.convertTimestampToDateString(outpatientOrder.getPrescriptionDate()),
                    outpatientOrder.getHisOrderNo(),
                    insureKey,
                    insureBizType,
                    insureTreatmentType,
                    BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped()));

            if (!Checker.isNone(res) && res.getCode() == ResultCode.SUCCEED_VALUE) {
                Map<String, Object> map = new HashMap<>();
                map.put("total", res.getTotal() / 100d);
                map.put("reimbursement", res.getReimbursement() / 100d);
                map.put("individual", res.getIndividual() / 100d);
                map.put("amount", res.getIndividual());
                return response.succeed(map);
            }

            return response.failedWithAppError(res.getMsg());
        } catch (Exception e) {
            logger.error("calInsurance({}, {}): {}", orderId, insuranceType, e.getMessage(), e);
            return response.failed(BaseResponse.APP_EXCEPTION, e.getMessage());
        }
    }

    /**
     * 查询治疗指引（太和）
     *
     * @param reqBody
     * @return
     */
    @RequestMapping({"/taihe/guide"})
    public @ResponseBody
    BaseResponse getTaiheGuide(@RequestBody Map<String, Object> reqBody) {
        BaseResponse response = new BaseResponse();
        Integer orderId = (Integer) reqBody.getOrDefault("orderId", 0);//订单Id

        if (orderId < 1) {
            return response.failedWithParameterError("invalid orderId");
        }

        try {
            GetOutpatientDetailRequest req = GetOutpatientDetailRequest.newBuilder()
                    .setOrderId(orderId)
                    .build();
            GetOutpatientDetailResponse res = orderServiceBlockingStub.getOutpatientDetail(req);
            Result result = res.getResult();

            if (result.getCode() != ResultCode.SUCCEED) {
                return response.failedWithAppError(result.getInfo());
            }

            GetTreatmentGuideRequest guideRequest = GetTreatmentGuideRequest.newBuilder()
                    .setHisOrderNo(res.getOrder().getHisOrderNo())
                    .setHospitalId(BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped()))
                    .build();
            GetTreatmentGuideResponse guideResponse = taiheServiceBlockingStub.getTreatmentGuide(guideRequest);

            if (guideResponse.getCode() != ResultCode.SUCCEED_VALUE) {
                return response.failedWithAppError(guideResponse.getMsg());
            }

            GetTreatmentGuideResponse.DrugApply drugApply = guideResponse.getDrugApply();
            List<GetTreatmentGuideResponse.InspectionApply> inspectionApplyList = guideResponse.getInspectionApplyList();
            List<GetTreatmentGuideResponse.InspectionApply> laboratoryApplyList = guideResponse.getLaboratoryApplyList();

            Map<String, Object> drugMap = new HashMap<>();
            List<Map<String, Object>> inspectionList = new LinkedList<>();
            List<Map<String, Object>> laboratoryList = new LinkedList<>();

            if (drugApply != null) {
                List<Map<String, Object>> drugList = new LinkedList<>();

                if (drugApply.getDrugItemList() != null && drugApply.getDrugItemList().size() > 0) {
                    for (GetTreatmentGuideResponse.DrugItem drugItem : drugApply.getDrugItemList()) {
                        Map<String, Object> itemMap = new HashMap<>();
                        itemMap.put("name", drugItem.getName());
                        itemMap.put("desc", drugItem.getDesc());
                        drugList.add(itemMap);
                    }
                }

                drugMap.put("doctorName", drugApply.getDoctorName());
                drugMap.put("statusName", drugApply.getStatusName());
                drugMap.put("title", drugApply.getTitle());
                drugMap.put("patientName", drugApply.getPatientName());
                drugMap.put("serialNo", drugApply.getSerialNo());
                drugMap.put("applyDate", drugApply.getApplyDate());
                drugMap.put("guide", drugApply.getAddr());
                drugMap.put("list", drugList);
            }

            if (inspectionApplyList != null && inspectionApplyList.size() > 0) {
                for (GetTreatmentGuideResponse.InspectionApply apply : inspectionApplyList) {
                    Map<String, Object> itemMap = new HashMap<>();
                    itemMap.put("doctorName", apply.getDoctorName());
                    itemMap.put("statusName", apply.getStatusName());
                    itemMap.put("itemName", apply.getItemName());
                    itemMap.put("title", apply.getTitle());
                    itemMap.put("patientName", apply.getPatientName());
                    itemMap.put("serialNo", apply.getSerialNo());
                    itemMap.put("applyDate", apply.getApplyDate());
                    itemMap.put("desc", apply.getDesc());
                    itemMap.put("guide", apply.getGuide());

                    inspectionList.add(itemMap);
                }
            }

            if (laboratoryApplyList != null && laboratoryApplyList.size() > 0) {
                for (GetTreatmentGuideResponse.InspectionApply apply : laboratoryApplyList) {
                    Map<String, Object> itemMap = new HashMap<>();
                    itemMap.put("doctorName", apply.getDoctorName());
                    itemMap.put("statusName", apply.getStatusName());
                    itemMap.put("itemName", apply.getItemName());
                    itemMap.put("title", apply.getTitle());
                    itemMap.put("patientName", apply.getPatientName());
                    itemMap.put("serialNo", apply.getSerialNo());
                    itemMap.put("applyDate", apply.getApplyDate());
                    itemMap.put("desc", apply.getDesc());
                    itemMap.put("guide", apply.getGuide());

                    laboratoryList.add(itemMap);
                }
            }

            Map<String, Object> data = new HashMap<>();
            data.put("drug", drugMap);
            data.put("inspectionList", inspectionList);
            data.put("laboratoryList", laboratoryList);

            return response.succeed(data);
        } catch (Exception e) {
            logger.error("getTaiheGuide({}): {}", reqBody, e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 处方提交配送方式
     * <p>
     * <p>
     * body: orderId        订单ID
     * body: method         配送方式（1-快递到家，2-自取）
     * body: addressId      自行取药的药房地址ID
     * body: concat         收货联系人
     * body: mobile         收货人电话号码
     * body: province       省名称
     * body: city           市名称
     * body: area           区名称
     * body: address        详细地址
     * body: freight    	运费
     * body: reimbursement  医保报销金额
     * body: total    	    药品总金额
     * body: individual    	个人支付总金额
     * body: insuranceType   医保类型
     * body: needPrintStatus    是否需要打印发票，0-不需要，1-需要
     *
     * @return {@link BaseResponse}
     */
    @RequestMapping(value = {"/taihe/order/save"}, method = RequestMethod.POST)
    @ResponseBody
    public BaseResponse saveTaiheOrderInfo(@RequestBody Map<String, Object> reqBody) {
        BaseResponse response = new BaseResponse();
        try {
            Integer orderId = (Integer) reqBody.getOrDefault("orderId", 0);
            Integer method = (Integer) reqBody.getOrDefault("method", 0);
            String contact = (String) reqBody.getOrDefault("contact", "");
            String mobile = (String) reqBody.getOrDefault("mobile", "");
            String province = (String) reqBody.getOrDefault("province", "");
            String city = (String) reqBody.getOrDefault("city", "");
            String area = (String) reqBody.getOrDefault("area", "");
            String address = (String) reqBody.getOrDefault("address", "");
            Integer freight = (Integer) reqBody.getOrDefault("freight", 0);
            Integer reimbursement = (Integer) reqBody.getOrDefault("reimbursement", 0);
            Integer total = (Integer) reqBody.getOrDefault("total", 0);
            Integer payTotal = (Integer) reqBody.getOrDefault("payTotal", 0);
            Integer individual = (Integer) reqBody.getOrDefault("individual", 0);
            Integer insuranceType = (Integer) reqBody.getOrDefault("insuranceType", 0);
            Integer needPrintStatus = (Integer) reqBody.getOrDefault("needPrintStatus", 0);
            // 时效标准(快递的预计送达时间)
            String timeStandard = (String) reqBody.getOrDefault("timeStandard", "");

            if (method == 0) {
                return response.failedWithParameterError("请选择取药方式");
            }

            if (payTotal != individual + freight) {
                return response.failedWithParameterError("金额有误");
            }

            String insureKey = "";
            String insureBizType = "";
            String insureTreatmentType = "";

            com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailRequest getDetailReq =
                    com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailRequest.newBuilder()
                            .setOrderId(orderId)
                            .build();
            com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailResponse getDetailRes =
                    taiheOutpatientServiceBlockingStub.getOutpatientDetail(getDetailReq);

            if (getDetailRes.getCode() != ResultCode.SUCCEED_VALUE) {
                return response.failedWithAppError(getDetailRes.getMsg());
            }

            com.ywt.gapi.taihe.outpaitent.OutpatientOrder outpatientOrder = getDetailRes.getOrder();

            if (outpatientOrder.getTotal() != total) {
                return response.failedWithAppError("订单金额不一致");
            }

            if (insuranceType != null && insuranceType > 0) {
                //医保报销
                ServiceResult serviceResult = verifyInsuranceType(insuranceType);
                if (!serviceResult.success()) {
                    return response.failedWithParameterError(serviceResult.getMsg());
                }
                Map<String, Object> data = serviceResult.getData();
                insureKey = data.get("insureKey").toString();
                insureBizType = data.get("insureBizType").toString();
                insureTreatmentType = data.get("insureTreatmentType").toString();

                CalInsuranceResponse calInsuranceResponse = taiheProvider.calInsurance(
                        outpatientOrder.getHisPatientId(),
                        DateUtil.convertTimestampToDateString(outpatientOrder.getPrescriptionDate()),
                        outpatientOrder.getHisOrderNo(),
                        insureKey,
                        insureBizType,
                        insureTreatmentType,
                        BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped()));
                if (calInsuranceResponse == null || calInsuranceResponse.getCode() != ResultCode.SUCCEED_VALUE) {
                    return response.failedWithAppError("医保试算失败");
                }
                if (reimbursement != calInsuranceResponse.getReimbursement()) {
                    return response.failedWithAppError("医保报销金额不正确");
                }
                if (individual != calInsuranceResponse.getIndividual()) {
                    return response.failedWithAppError("医保个人支付部分金额不正确");
                }
            }
            if (method == 1) {
                //快递到家
                if (StringHelper.isNullOrWhiteSpace(contact)) {
                    return response.failedWithParameterError("收货人不能为空");
                }
                if (StringHelper.isNullOrWhiteSpace(mobile)) {
                    return response.failedWithParameterError("收货联系电话有误");
                }
                if (StringHelper.isNullOrWhiteSpace(province)) {
                    return response.failedWithParameterError("省名称不能为空");
                }
                if (StringHelper.isNullOrWhiteSpace(city)) {
                    return response.failedWithParameterError("市名称不能为空");
                }
                if (StringHelper.isNullOrWhiteSpace(area)) {
                    return response.failedWithParameterError("区名称不能为空");
                }
                if (StringHelper.isNullOrWhiteSpace(address)) {
                    return response.failedWithParameterError("详细地址不能为空");
                }

                String consignTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                //对应城市-城市(郊区)时效标准，这时候会认为srcCode是大陆地区城市代码,destCode是大陆地区城市代码
                int queryType = 7;
                //根据顺丰文档医药专递使用T4
                String productType = "T4";
                // TODO: 2018/10/9 产品暂定重量固定为1.0KG，后续应该根据presNo找出处方单信息计算重量
                double weight = 1.0D;
                // TODO: 2018/10/10 根据presNo找出药房地址,确定srcCode
                String srcCode = "020";
                //获取目的地城市代码
                GetCityCodeRequest request = GetCityCodeRequest.newBuilder().setProvinceName(province).setCityName(city).build();
                GetCityCodeResponse getCityCodeResponse = sfInternalServiceBlockingStub.getCityCode(request);

                if (getCityCodeResponse.getCode() != BaseResponse.SUCCEED) {
                    return response.failed(BaseResponse.APP_ERROR, getCityCodeResponse.getMsg());
                }

                String destCode = getCityCodeResponse.getCityCode();
                CalcTimePromiseAndFreightRequest calcTimePromiseAndFreightReq = CalcTimePromiseAndFreightRequest.newBuilder()
                        .setQueryType(queryType)
                        .setSrcCode(srcCode)
                        .setDestCode(destCode)
                        .setConsignTime(consignTime)
                        .setWeight(weight)
                        .setProductType(productType)
                        .build();
                CalcTimePromiseAndFreightResponse calcTimePromiseAndFreightRes = sfServiceBlockingStub.calcTimePromiseAndFreight(
                        calcTimePromiseAndFreightReq);

                if (calcTimePromiseAndFreightRes.getCode() != BaseResponse.SUCCEED) {
                    return response.failedWithAppError(calcTimePromiseAndFreightRes.getMsg());
                }

                double calFreight = isTest ? 0.01 : calcTimePromiseAndFreightRes.getFreight();
                if (freight != calFreight) {
                    return response.failedWithAppError("快递费用不正确");
                }

                String calTimeStandard = calcTimePromiseAndFreightRes.getTimeStandard();
            }


            UpdateOutpatientRequest updateOutpatientRequest = UpdateOutpatientRequest.newBuilder()
                    .setOrderId(orderId)
                    .setIndividual(individual)
                    .setReimbursement(reimbursement)
                    .setInsureBizType(insureBizType)
                    .setInsureKey(insureKey)
                    .setInsureTreatmentType(insureTreatmentType)
                    .setDeliveryMethod(method)
                    .setPostage(freight)
                    .build();
            UpdateOutpatientResponse updateOutpatientResponse = taiheOutpatientServiceBlockingStub.updateOutpatient(updateOutpatientRequest);

            if (updateOutpatientResponse.getCode() == ResultCode.SUCCEED_VALUE) {
                Map<String, Object> data = new HashMap<>();
                data.put("payTotal", payTotal);
                return response.succeed(data);
            }
            return response.failedWithAppError(updateOutpatientResponse.getMsg());
        } catch (Exception e) {
            logger.error("saveTaiheOrderInfo({}): {}", reqBody, e.getMessage(), e);
            return response.error();
        }
    }


    /**
     * 针对回写 HIS 的处方做兼容处理
     *
     * @param orderId  订单 id
     * @param orderSum 订单总金额，不包括运费
     * @param freight  运费
     * @return individual 个人需支付部分 = total（订单总额） + freight（快递费）
     * @throws YwtCommonException 业务错误
     */
    private int writeBack2HisCompat(int orderId, int orderSum, int freight) throws YwtCommonException {
        logger.info("PrescriptionController#writeBack2HisCompat(orderId={} , orderSum={} , freight={} ):回写 HIS 重新计费", orderId, orderSum, freight);
        GetPrescriptionRequest getPrescriptionRequest = GetPrescriptionRequest.newBuilder()
                .setOrderId(orderId)
                .build();
        GetPrescriptionResponse getPrescriptionResponse = drugServiceBlockingStub.getPrescription(getPrescriptionRequest);
        if (getPrescriptionResponse.getCode() != ResultCode.SUCCEED_VALUE)
            throw new YwtCommonException(YwtCommonRespCode.P_ERR, String.format("无法获取处方信息，orderId: %d：%s", orderId, getPrescriptionResponse.getInfo()));
        PrescriptionInfo prescriptionInfo = getPrescriptionResponse.getPrescriptionInfo();
        if (prescriptionInfo == null) {
            throw new YwtCommonException(YwtCommonRespCode.P_ERR, String.format("处方信息为空，orderId: %d", orderId));
        }
        String hisOeoriOrderId = prescriptionInfo.getHisOeoriOrderId();
        //HIS 医嘱订单 id 为空，非回写处方，直接用原金额支付
        if (StringHelper.isNullOrEmpty(hisOeoriOrderId)) return orderSum + freight;

        // 如果是回写 HIS 的处方，需要先做预结算，以预结算后的金额为准支付
        // 根据 hisPatientId 拉取门诊待缴费列表
        String hisPatientId = prescriptionInfo.getHisPatientId();
        String hisClinicCode = prescriptionInfo.getHisClinicCode();
        if (StringHelper.isNullOrEmpty(hisPatientId))
            throw new YwtCommonException(YwtCommonRespCode.P_ERR, "HIS 患者 id 为空");
        if (StringHelper.isNullOrEmpty(hisClinicCode))
            throw new YwtCommonException(YwtCommonRespCode.P_ERR, "HIS 就诊流水号 为空");
        com.ywt.gapi.third.taihe.GetOutpatientListRequest request = com.ywt.gapi.third.taihe.GetOutpatientListRequest.newBuilder()
                .setPatientId(hisPatientId)
                .setType(DHOutpatientController.TYPE_UNPAID)
                .setHospitalId(BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped()))
                .build();
        com.ywt.gapi.third.taihe.GetOutpatientListResponse result = taiheServiceBlockingStub.getOutpatientList(request);
        if (result.getCode() != ResultCode.SUCCEED_VALUE) {
            throw new YwtCommonException(YwtCommonRespCode.P_ERR, String.format("获取待缴费列表返回：%s", result.getMsg()));
        }
        // his 订单 id
        String hisOrderNum = "";
        List<PaymentItem> paymentItems = result.getPaymentList();
        int totalFee = orderSum;
        PaymentItem item = paymentItems.stream()
                .filter(paymentItem -> hisClinicCode.equals(paymentItem.getClinicCode()))
                .findFirst()
                .orElse(null);
        if (item != null) {
            hisOrderNum = Checker.getStringValue(item.getHisOrdNum());
            // 预结算订单金额以 HIS 待缴费列表返回的为准
            totalFee = Checker.getIntegerValue(item.getTotalFee());
        } else {
            logger.error("没有返回付费信息");
        }
        if (StringHelper.isNullOrEmpty(hisOrderNum))
            throw new YwtCommonException(YwtCommonRespCode.P_ERR, "获取不到 HIS 订单号");
        // 预结算
        PrePayConfirmRequest req = PrePayConfirmRequest.newBuilder()
                .setPatientId(hisPatientId)
                .setClinicCode(hisClinicCode)
                .setHisOrdNum(hisOrderNum)
                .setOrderSum(totalFee)
                .setHisUserID("0")// 处方回写,门诊结算和缴费用新的账号,独立用户结算
                .setHospitalId(BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped()))
                .build();
        PrePayConfirmResponse response = taiheServiceBlockingStub.prePayConfirm(req);
        if (response.getCode() != ResultCode.SUCCEED_VALUE)
            throw new YwtCommonException(YwtCommonRespCode.P_ERR, String.format("预结算返回：%s", response.getMsg()));
        if (Checker.isNone(response.getListList()))
            throw new YwtCommonException(YwtCommonRespCode.P_ERR, "预结算返回数据为空");
        PrePayConfirm p = response.getListList().get(0);
        // 预结算后的待支付金额
        int payAmount = Checker.getIntegerValue(p.getInvoiceAmt());
        String invoiceNo = p.getInvoiceNo();// 发票号
        if (orderSum != payAmount) {
            logger.info("预结算后待支付金额有变化，原支付金额 {}，预结算后支付金额 {}， 订单 id {}", orderSum, payAmount, orderId);
            // 修改订单金额 orders#order_amount
            // 修改订单金额由 drugServiceBlockingStub.saveOrderDeliveryInfo 处理
//            UpdateOrderAmtRequest updateOrderAmtRequest = UpdateOrderAmtRequest.newBuilder()
//                    .setOrderId(orderId)
//                    .setPayAmt(payAmount + freight)
//                    .build();
//            UpdateOrderAmtResponse updateOrderAmtResponse = orderServiceBlockingStub.updateOrderAmt(updateOrderAmtRequest);
//            if (updateOrderAmtResponse.getCode() != ResultCode.SUCCEED_VALUE) {
//                logger.error("PrescriptionController#writeBack2HisCompat(): 修改订单金额失败 {}", updateOrderAmtResponse.getInfo());
//            }
        }
        UpdateHisPresInfoRequest updateHisPresInfoRequest = UpdateHisPresInfoRequest.newBuilder()
                .setHisOrdNum(hisOrderNum)
                .setInvoiceNo(invoiceNo)
                .setPreId(prescriptionInfo.getPrescriptionId())
                .setHisPayAmt(payAmount)
                .build();
        Result updateResult = drugServiceBlockingStub.updateHisPresInfo(updateHisPresInfoRequest);
        if (updateResult.getCode() != ResultCode.SUCCEED) {
            logger.error("PrescriptionController#writeBack2HisCompat(): updateHisPresInfo failed! {}", updateResult.getInfo());
        }
        return payAmount + freight;
    }

    /**
     * 处方提交配送方式
     * <p>
     * <p>
     * body: orderId        订单ID
     * body: method         配送方式（1-快递到家，2-自取）
     * body: addressId      自行取药的药房地址ID
     * body: concat         收货联系人
     * body: mobile         收货人电话号码
     * body: province       省名称
     * body: city           市名称
     * body: area           区名称
     * body: address        详细地址
     * body: freight    	运费
     * body: reimbursement  医保报销金额
     * body: total    	    药品总金额
     * body: individual    	个人支付总金额
     * body: insuranceType   医保类型
     * body: needPrintStatus    是否需要打印发票，0-不需要，1-需要
     *
     * @return {@link BaseResponse}
     */
    @RequestMapping(value = {"/saveDeliveryMethod"}, method = RequestMethod.POST)
    @ResponseBody
    public BaseResponse saveDeliveryMethod(@RequestBody Map<String, Object> data) {
        BaseResponse baseResponse = new BaseResponse();
        try {
            int orderId = (int) data.getOrDefault("orderId", 0);
            int method = (int) data.getOrDefault("method", 0);
            String concat = (String) data.getOrDefault("concat", "");
            String mobile = (String) data.getOrDefault("mobile", "");
            String province = (String) data.getOrDefault("province", "");
            String city = (String) data.getOrDefault("city", "");
            String area = (String) data.getOrDefault("area", "");
            String address = (String) data.getOrDefault("address", "");
            int freight = (int) data.getOrDefault("freight", 0);
            int reimbursement = (int) data.getOrDefault("reimbursement", 0);
            int total = (int) data.getOrDefault("total", 0);
            int individual = (int) data.getOrDefault("individual", 0);
            int insuranceType = (int) data.getOrDefault("insuranceType", 0);
            int needPrintStatus = (int) data.getOrDefault("needPrintStatus", 0);
            int pharmacyId = (int) data.getOrDefault("pharmacyId", 0);
            String name = (String) data.getOrDefault("name", "");
            String idCardNo = (String) data.getOrDefault("idCardNo", "");
            // 时效标准(快递的预计送达时间)
            String timeStandard = (String) data.getOrDefault("timeStandard", "");
            int patientId = (int) data.getOrDefault("patientId", 0);

            //（临时注释）  2018-12-27  开始校验身份证
            if (StringHelper.isNullOrWhiteSpace(name)) {
                return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "姓名不能为空");
            }
            if (StringHelper.isNullOrWhiteSpace(idCardNo)) {
                return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "身份证号码不能为空");
            }
            if (!IdCardUtil.verify(idCardNo)) {
                return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "身份证号不正确");
            }

            int err = 0;
            String msg = "";
            int value = 0;

            if (method == 0) {
                return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "请选择取药方式");
            }
            // 不管是自取还是快递，发药的药房地址ID值一定不能为0
            if (pharmacyId == 0) {
                return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "pharmacyId参数错误");
            }
            // 自取
            if (method == 2) {
                // TODO 进行医保校验
                /*
                BaseResponse baseRes = calInsuranceCommon(orderId, insuranceType);
                if (baseRes.getCode() != BaseResponse.SUCCEED) {
                    return baseRes;
                }
                */

                // TODO 金额校验
                if (individual != (total - reimbursement)) {
                    return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "金额有误");
                }

            } else {
                // 如果是快递，那么此时addressId的值一定要为0才行
                if (Checker.isNone(concat.trim())) {
                    return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "收货人不能为空");
                }
                if (Checker.isNone(mobile.trim())) {
                    return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "收货联系电话有误");
                }
                if (Checker.isNone(province.trim())) {
                    return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "省名称不能为空");
                }
                if (Checker.isNone(city.trim())) {
                    return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "市名称不能为空");
                }
                if (Checker.isNone(area.trim())) {
                    return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "区名称不能为空");
                }
                if (Checker.isNone(address.trim())) {
                    return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "详细地址不能为空");
                }

                // TODO 这里进行运费的校验

                // TODO 金额校验
                if (individual != (total - reimbursement + freight)) {
                    return baseResponse.failed(BaseResponse.PARAMETER_ERROR, "金额有误");
                }

            }
            // 回写的处方要校验是否已作废，作废中或已作废返回失败
            GetPrescriptionRequest getPrescriptionRequest = GetPrescriptionRequest.newBuilder()
                    .setOrderId(orderId)
                    .setIgnoreDeleted(true)
                    .build();
            GetPrescriptionResponse getPrescriptionResponse = drugServiceBlockingStub.getPrescription(getPrescriptionRequest);
            if (getPrescriptionResponse.getCode() == ResultCode.SUCCEED_VALUE) {
                PrescriptionInfo prescriptionInfo = getPrescriptionResponse.getPrescriptionInfo();
                if (prescriptionInfo != null) {
                    String hisOeoriOrderId = Checker.getStringValue(prescriptionInfo.getHisOeoriOrderId());
                    int cancelStatus = Checker.getIntegerValue(prescriptionInfo.getCancelStatus());
                    if (!StringHelper.isNullOrEmpty(hisOeoriOrderId) && (cancelStatus == PresCancelStatusEnum.PROCESSING.getValue()
                            || cancelStatus == PresCancelStatusEnum.CANCELED.getValue())) {
                        return baseResponse.failedWithAppError("该处方作废中或已作废，请返回刷新");
                    }
                }
            }

            // 针对 HIS 回写处方兼容，调用 HIS 接口重新计价
            individual = writeBack2HisCompat(orderId, total, freight);
            logger.info("Pay individual: {}", individual);

            SavePrescriptionAddressRequest reqt = SavePrescriptionAddressRequest.newBuilder()
                    .setOrderId(orderId)
                    .setProvince(province)
                    .setCity(city)
                    .setArea(area)
                    .setAddress(address.trim())
                    .setContact(concat.trim())
                    .setMobile(mobile)
                    .setFreight(freight)
                    .setIndividual(individual)
                    .setNeedPrintStatus(needPrintStatus)
                    .setDeliveryMethod(method)
                    .setPharmacyId(pharmacyId)
                    .setTimeStandard(timeStandard)
                    .build();
            Result result = orderServiceBlockingStub.savePrescriptionAddress(reqt);

            if (result.getCode() == ResultCode.SUCCEED) {
                //保存患者身份证号、姓名信息（临时注释）
                if (!StringHelper.isNullOrWhiteSpace(idCardNo) &&
                        IdCardUtil.verify(idCardNo) &&
                        !StringHelper.isNullOrWhiteSpace(name)) {
                    int preId = Checker.parseInt(result.getValue());
                    UpdatePrescriptionPatientInfoRequest updatePrescriptionPatientInfoRequest =
                            UpdatePrescriptionPatientInfoRequest.newBuilder()
                                    .setAge(IdCardUtil.getCurrentAge(idCardNo) + "岁")
                                    .setIdCardNo(idCardNo)
                                    .setName(name)
                                    .setSex(IdCardUtil.getSex(idCardNo))
                                    .setPreId(preId)
                                    .build();
                    UpdatePrescriptionPatientInfoResponse updatePrescriptionPatientInfoResponse =
                            drugServiceBlockingStub.updatePrescriptionPatientInfo(updatePrescriptionPatientInfoRequest);
                    // 更新患者信息
                    UpdatePatientInfoRequest updatePatientInfoRequest = UpdatePatientInfoRequest.newBuilder()
                            .setIdCardNo(idCardNo)
                            .setName(name)
                            .setSex(IdCardUtil.getSexInt(idCardNo))
                            .setPatientId(patientId)
                            .build();
                    Result rst = doctorServiceBlockingStub.updatePatientInfo(updatePatientInfoRequest);
                    if (rst.getCode() != ResultCode.SUCCEED) {
                        logger.warn("Update patient info failed: {}", Checker.getStringValue(rst.getInfo()));
                    }
                }

                err = 0;
                BigDecimal bd = new BigDecimal(result.getInfo());
                BigDecimal bd2 = new BigDecimal("100");
                bd = bd.multiply(bd2);
                value = bd.intValue();
            } else {
                err = 1;
                msg = result.getInfo();
            }

            if (err == 0) {
                Map map = new HashMap();
                map.put("individual", value);
                return baseResponse.succeed(map);
            } else {
                return baseResponse.failed(BaseResponse.PARAMETER_ERROR, msg);
            }
/*
            try {
                int userId = userSrv.getCurrentUserId();
                SavePrescriptionNeedFeeRequest request = SavePrescriptionNeedFeeRequest.newBuilder()
                        .setOrderId(orderId)
                        .setIndividual(individual)
                        .setReimbursement(reimbursement)
                        .setTotal(total)
                        .setUserId(userId)
                        .build();
                Result result = orderServiceBlockingStub.savePrescriptionNeedFee(request);
                if (result.getCode() != ResultCode.SUCCEED) {
                    err = 1;
                    msg = result.getInfo();
                }
            } catch (Exception e) {
                logger.error("/saveDeliveryMethod调用rpc里面的savePrescriptionNeedFee", e.getMessage(), e);
            }
*/

        } catch (Exception e) {
            logger.error("/saveDeliveryMethod：", JsonSerializer.toJson(data), e.getMessage(), e);
            return baseResponse.failed(BaseResponse.APP_EXCEPTION, e.getMessage());
        }
    }

    private ServiceResult verifyInsuranceType(int insuranceType) {
        ServiceResult serviceResult = new ServiceResult();
        String insureKey;
        String insureBizType;
        String insureTreatmentType;

        switch (insuranceType) {
            case 1:
                //职工医保
                insureKey = "101";
                insureBizType = "11";
                insureTreatmentType = "110";
                break;
            case 2:
                //生育医保(一般产检)
                insureKey = "102";
                insureBizType = "51";
                insureTreatmentType = "551";
                break;
            case 3:
                //居民医保
                insureKey = "101";
                insureBizType = "11";
                insureTreatmentType = "110";
                break;
            case 4:
                //门诊慢性病医保(糖尿病)
                insureKey = "103";
                insureBizType = "13";
                insureTreatmentType = "131";
                break;
            case 5:
                //慢性病医保(高血压)
                insureKey = "103";
                insureBizType = "13";
                insureTreatmentType = "132";
                break;
            default:
                return serviceResult.failed("invalid insuranceType");
        }

        Map<String, Object> data = new HashMap<>();
        data.put("insureKey", insureKey);
        data.put("insureBizType", insureBizType);
        data.put("insureTreatmentType", insureTreatmentType);
        return serviceResult.succeed(data);
    }

}
