package com.ywt.alipaympapi.service.impl;

import com.alipay.api.domain.AlipayTradeCreateModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.response.AlipayTradeCreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.ywt.alipaympapi.core.utils.*;
import com.ywt.alipaympapi.face.IPayFace;
import com.ywt.alipaympapi.models.Constants;
import com.ywt.alipaympapi.models.enums.PaymentStatusEnum;
import com.ywt.alipaympapi.models.enums.SexEnum;
import com.ywt.core.exception.AppMessageException;
import com.ywt.gapi.Result;
import com.ywt.gapi.ResultCode;
import com.ywt.gapi.drug.GetOneKeyRegListRequest;
import com.ywt.gapi.drug.GetOneKeyRegListResponse;
import com.ywt.gapi.order.*;
import com.ywt.gapi.order.OutpatientOrder;
import com.ywt.gapi.ordercenter.*;
import com.ywt.gapi.system.GetConfigByTypeRequest;
import com.ywt.gapi.system.GetConfigByTypeResponse;
import com.ywt.gapi.taihe.outpaitent.*;
import com.ywt.gapi.taihe.outpaitent.BaseResult;
import com.ywt.gapi.third.taihe.*;
import com.ywt.gapi.third.taihe.GetOutpatientListRequest;
import com.ywt.gapi.third.taihe.GetOutpatientListResponse;
import com.ywt.gapi.wx_ins_pay.MarkOpOrderDeletedRequest;
import com.ywt.gapi.wx_ins_pay.MarkOpOrderDeletedResponse;
import com.ywt.gapi.wx_ins_pay.WxInsPayServiceGrpc;
import com.ywt.model.PageVO;
import com.ywt.model.Pagination;
import com.ywt.request.pay.*;
import com.ywt.response.inpatient.DepositTradeResponseData;
import com.ywt.response.pay.*;
import com.ywt.alipaympapi.service.IsvPayService;
import com.ywt.response.report.QueryReportListResponseData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class IsvPayServiceImpl implements IsvPayService {
    @Resource
    private IPayFace payFace;

    public static final int TYPE_UNPAID_WX = 1;
    private static final int TYPE_PAID_WX = 2;

    public static final int TYPE_UNPAID_ZFB = 0;
    private static final int TYPE_PAID_ZFB = 1;

    private static final int TYPE_PAID = 2;
    // No pagination for now
    private static final int PAGE_INDEX = 1;
    private static final int PAGE_SIZE = 99999;


    @Autowired
    private TaiheServiceGrpc.TaiheServiceBlockingStub taiheServiceBlockingStub;

    @Autowired
    private TaiheOutpatientServiceGrpc.TaiheOutpatientServiceBlockingStub taiheOutpatientServiceBlockingStub;

    @Autowired
    private com.ywt.gapi.drug.DrugServiceGrpc.DrugServiceBlockingStub drugServiceBlockingStub;

    @Autowired
    private OrderServiceGrpc.OrderServiceBlockingStub orderServiceBlockingStub;
    @Autowired
    private OrderCenterServiceGrpc.OrderCenterServiceBlockingStub orderCenterServiceBlockingStub;

    @Autowired
    private WxInsPayServiceGrpc.WxInsPayServiceBlockingStub wxInsPayServiceBlockingStub;


    // 商家订单号获取
    @Override
    public TradeNoResponseData queryTradeNo(OutTradeNoRequest request) throws Exception {
        int orderId = Integer.parseInt(request.getOrderId());
        if (orderId <= 0) {
            throw new AppMessageException("该订单不存在");
        }
        int userId = Integer.parseInt(request.getUserId());
        int amount = BizUtil.yuan2Cent(request.getAmount());

        CreateAlipayOrderResponse response = orderCenterServiceBlockingStub.createAlipayOrder(CreateAlipayOrderRequest.newBuilder()
                .setBody("预约挂号")
                .setAlipayUid(request.getAlipayUid())
                .setOrderId(orderId)
                .setOrderNo("")
                .setAmount(amount)
                .setUserId(userId)
                .setTerminal(ContextHelper.getCurrentTerminalWrapped())
                .build());
        if (response.getCode() != ResultCode.SUCCEED_VALUE)
            throw new AppMessageException("支付宝下单：" + response.getInfo());
        TradeNoResponseData data = new TradeNoResponseData();
        data.setOrderId(orderId);
        data.setOutTradeNo(response.getOrderNo());
        data.setTradeNo(response.getTradeNo());
        return data;
    }

    @Override
    public TradeResultResponseData informTradeResult(TradeResultRequest request) {
        TradeResultResponseData data = new TradeResultResponseData();

        AlipayTradeQueryModel alipayTradeQueryModel = new AlipayTradeQueryModel();
        alipayTradeQueryModel.setTradeNo(request.getTradeNo());
        AlipayTradeQueryResponse response = payFace.tradeQuery(request.getAppId(), alipayTradeQueryModel);
        if ("TRADE_SUCCESS".equals(response.getTradeStatus())) {
            data.setStatus("TRADE_SUCCESS");
        }

        return data;
    }

    @Override
    public PayDetailResponseData queryPayDetail(PayDetailRequest request) throws Exception {
        int userId = ContextHelper.getCurrentUserIdWrapped();
        int hospitalId = BizUtil.getCurrentHospitalId();
        if (Checker.isNone(request.getStatus())) {
            throw new RuntimeException("订单状态不能为空");
        }
        if (request.getStatus() == TYPE_UNPAID_ZFB) {
            PayDetailResponseData da = new PayDetailResponseData();
            da.setDeptName(Checker.getStringValue(request.getDeptName()));
            if (!Checker.isNone(request.getAge()) && request.getAge() > 0) {
                da.setAge(request.getAge());
            }
            da.setSex(Checker.getStringValue(request.getSex()));
            da.setStatus(request.getStatus());
            da.setDoctorName(Checker.getStringValue(request.getDoctorName()));
            da.setDoctorCode(Checker.getStringValue(request.getDoctorCode()));
            da.setHisClinicCode(Checker.getStringValue(request.getHisClinicCode()));
            da.setPrescribeDate(Checker.getStringValue(request.getPrescribeDate()));
            da.setTotal(request.getTotal());
            da.setUserName(Checker.getStringValue(request.getName()));
            da.setName(Checker.getStringValue(request.getName()));
            da.setHisOrderNo(Checker.getStringValue(request.getHisOrderNo()));
            da.setAmount(Checker.getStringValue(request.getAmount()));
            da.setCreateTime(Checker.getStringValue(request.getPrescribeDate()));
            da.setHisPatientId(request.getHisPatientId());
            if (!Checker.isNone(request.getOrderItems())) {
                da.setOrderItems((request.getOrderItems()));
            }
            return da;
        }
        if (Checker.isNone(request.getInvoiceNo()) && Checker.isNone(request.getOutTradeNo())) {
            throw new RuntimeException("订单发票号不存在");
        }
        List<OrderItem> list = new LinkedList<>();
        PayDetailResponseData da = new PayDetailResponseData();
        String hisPatientId = Checker.getStringValue(request.getHisPatientId());
        switch (hospitalId) {
            default:
            case Constants.HOSPITAL_ID_NFYYBYFY:
                // 白云从 HIS 接口获取门诊缴费详情
                String invoiceNo = Checker.getStringValue(request.getInvoiceNo());
                CheckUtil.ensureNotEmpty(invoiceNo, "发票号不能为空");
                CheckUtil.ensureNotEmpty(hisPatientId, "HIS 病人 id 不能为空");
                // 根据 his_patient_id 获取诊疗卡信息
                String pName = "";
                int pAge = 0;
                String pGender = "";
                String cardNum = "";
                GetMedicalCardInfoByPatientIdRequest gResp = GetMedicalCardInfoByPatientIdRequest.newBuilder()
                        .setHisPatientId(hisPatientId)
                        .setHospitalId(hospitalId)
                        .setUserId(userId)
                        .build();
                GetMedicalCardInfoByPatientIdResponse gmcResp = taiheOutpatientServiceBlockingStub.getMedicalCardInfoByPatientId(gResp);
                if (gmcResp.getCode() == ResultCode.SUCCEED_VALUE) {
                    pName = gmcResp.getPatientName();
                    pAge = getPatientAgeSafely(gmcResp.getIdNo(), gmcResp.getBirthday());
                    pGender = IdCardUtil.getSex(gmcResp.getIdNo());
                    cardNum = Checker.getStringValue(gmcResp.getCardNo());

                }
                GetPaymentDetailResponse response2 = taiheServiceBlockingStub.getPaymentDetail(GetPaymentDetailRequest.newBuilder()
                        .setHospitalId(hospitalId)
                        .setInvoiceNo(invoiceNo)
                        .setHisPatientId(hisPatientId)
                        .setType("2")
                        .build());
                if (response2.getCode() != ResultCode.SUCCEED_VALUE)
                    throw new RuntimeException(response2.getMsg());
                if (!Checker.isNone(response2.getDetailList())) {
                    list = response2.getDetailList().stream()
                            .map(i -> {
                                OrderItem it = new OrderItem();
                                it.setItemName(i.getItemName());
                                it.setAmount(String.format("%.2f", i.getItemPrice() / 100d));
                                it.setItemNum(String.valueOf(i.getItemNumber()));
                                return it;
                            })
                            .collect(Collectors.toList());
                }
                da.setAge(Checker.getIntegerValue(pAge));
                da.setUserName(Checker.getStringValue(pName));
                da.setSex(pGender);
                da.setPayDate(request.getDate());
                da.setOrderItems(list);
                da.setCardNum(cardNum);
                da.setOrderId("");
                da.setTotal(request.getTotal());
                da.setStatus(request.getStatus());
                da.setAmount(request.getAmount());
                da.setHisPatientId(request.getHisPatientId());
                da.setDoctorName(Checker.getStringValue(request.getDoctorName()));
                da.setDeptName(Checker.getStringValue(request.getDeptName()));
                da.setPayDate(Checker.getStringValue(request.getPayTime()));
                da.setPrescribeDate(Checker.getStringValue(request.getPrescribeDate()));
                break;
            case Constants.TAIHE_HOSPITAL_ID:
                // 太和从数据库读取数据
                String hisOrderNo = request.getHisOrderNo();
                CheckUtil.ensureNotEmpty(hisOrderNo, "hisOrderNo 不能为空");
                GetOutpatientOrderDetailRequest req = GetOutpatientOrderDetailRequest.newBuilder()
                        .setHospitalId(BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped()))
                        .setHisOrderNo(hisOrderNo)
                        .build();
                GetOutpatientOrderDetailResponse response = taiheOutpatientServiceBlockingStub.getOutpatientOrderDetail(req);
                if (response.getCode() != ResultCode.SUCCEED_VALUE)
                    throw new AppMessageException(response.getMsg());
                if (!Checker.isNone(response.getDetailList())) {
                    list = response.getDetailList().stream()
                            .map(i -> {
                                OrderItem it = new OrderItem();
                                it.setItemName(i.getItemName());
                                it.setAmount(String.format("%.2f", i.getItemPrice() / 100d));
                                it.setItemNum(String.valueOf(i.getItemNumber()));
                                return it;
                            })
                            .collect(Collectors.toList());
                }
                da.setOrderItems(list);
                da.setAge(Checker.getIntegerValue(response.getPatientAge()));
                da.setUserName(Checker.getStringValue(response.getPatientName()));
                da.setSex(SexEnum.getSexDisplayName(Checker.getIntegerValue(response.getPatientSex())));
                da.setPayDate(request.getDate());
                da.setOrderItems(list);
//                da.setCardNum(cardNum);
                da.setOrderId("");
                da.setTotal(request.getTotal());
                da.setStatus(request.getStatus());
                da.setAmount(request.getAmount());
                da.setHisPatientId(request.getHisPatientId());
                da.setDoctorName(Checker.getStringValue(request.getDoctorName()));
                da.setDeptName(Checker.getStringValue(request.getDeptName()));
                da.setPayDate(Checker.getStringValue(request.getPayTime()));
                da.setPrescribeDate(Checker.getStringValue(request.getPrescribeDate()));
                break;
        }
        return da;
    }

    @Override
    public PageVO<PayHistoryResponseData> queryPayHistory(PayHistoryRequest request) throws Exception {
        List<PayHistoryResponseData> list = new ArrayList<>();
        int pageIndex = request.getPageIndex();
        int pageSize = request.getPageSize();
        int total = 0;
        if (Checker.isNone(request.getStatus())) {
            throw new AppMessageException("订单状态不能为空");
        }
        int status = Integer.parseInt(Checker.getStringValue(request.getStatus()));
        if (Checker.isNone(request.getHisPatientId())) {
            throw new AppMessageException("hisPatientI不能为空");
        }
        String hisPatientId = Checker.getStringValue(request.getHisPatientId());
        int userId = ContextHelper.getCurrentUserIdWrapped();
        String pName = "";
        int pAge = 0;
        String pGender = "";
        int hospitalId = BizUtil.getCurrentHospitalId();
        GetMedicalCardInfoByPatientIdRequest gResp = GetMedicalCardInfoByPatientIdRequest.newBuilder()
                .setHisPatientId(hisPatientId)
                .setHospitalId(hospitalId)
                .setUserId(userId)
                .build();
        GetMedicalCardInfoByPatientIdResponse resp = taiheOutpatientServiceBlockingStub.getMedicalCardInfoByPatientId(gResp);
        if (resp.getCode() == ResultCode.SUCCEED_VALUE) {
            pName = resp.getPatientName();
            pAge = getPatientAgeSafely(resp.getIdNo(), resp.getBirthday());
            pGender = IdCardUtil.getSex(resp.getIdNo());
        }
        switch (status) {
            case TYPE_UNPAID_ZFB:
                // 待缴费列表从 HIS 获取数据
                GetOutpatientListRequest req = GetOutpatientListRequest.newBuilder()
                        .setPatientId(hisPatientId)
                        .setType(TYPE_UNPAID_WX)
                        .setHospitalId(hospitalId)
                        .build();
                GetOutpatientListResponse result = taiheServiceBlockingStub.getOutpatientList(req);

                if (result.getCode() != ResultCode.SUCCEED_VALUE) {
                    throw new RuntimeException(result.getMsg());
                }
                List<Map<String, Object>> lst = new LinkedList<>();
                Map<String, Object> map;

                List<PaymentItem> paymentItems = result.getPaymentList();
                if (!Checker.isNone(paymentItems)) {
                    // 过滤处方门诊缴费单
                    GetOneKeyRegListRequest getOneKeyRegListRequest = GetOneKeyRegListRequest.newBuilder()
                            .setUserId(userId)
                            .build();
                    GetOneKeyRegListResponse getOneKeyRegListResponse = drugServiceBlockingStub.getOneKeyRegList(getOneKeyRegListRequest);
                    List<String> clinicCodes = getOneKeyRegListResponse.getCode() == ResultCode.SUCCEED_VALUE ? getOneKeyRegListResponse.getClinicCodeList() : new LinkedList<>();
                    List<PaymentItem> payItems = paymentItems;
                    if (!clinicCodes.isEmpty()) {
                        payItems = paymentItems.stream()
                                .filter(paymentItem -> !clinicCodes.contains(paymentItem.getClinicCode()))
                                .collect(Collectors.toList());
                    }
                    total = payItems.size();
                    for (PaymentItem payItem : payItems) {
                        PayHistoryResponseData data = new PayHistoryResponseData();
                        data.setStatus(status);
                        data.setTitle("");
                        data.setHisOrderNo(payItem.getHisOrdNum());
                        data.setOrderId(payItem.getOrderId());
                        data.setDeptName(payItem.getDeptName());
                        data.setPrescribeDate(payItem.getPrescriptionDate());
                        data.setName(resp.getPatientName());
                        data.setTotal(payItem.getTotalFee());
                        data.setAmount(String.format("%.2f", payItem.getTotalFee() / 100d));
                        data.setTradeNo(""); //Todo
                        data.setOutTradeNo("");//Todo
                        data.setIdNum("");//Todo
                        data.setInvoiceNo(Checker.getStringValue(payItem.getInvoiceNo()));
                        data.setHisPatientId(hisPatientId);
                        data.setAge(Checker.getIntegerValue(pAge));
                        data.setSex(pGender);
                        data.setDoctorName(payItem.getDoctorName());
                        data.setDoctorCode(payItem.getDoctorCode());
                        data.setHisClinicCode(payItem.getClinicCode());
                        List<PayDetailItem> detailItems = payItem.getItemListList();
                        List<OrderItem> ls = new ArrayList<>();
//                        String detailName = "";
                        for (PayDetailItem detailItem : detailItems) {
                            OrderItem it = new OrderItem();
                            it.setAmount(String.format("%.2f", detailItem.getItemTotalFee() / 100d));
                            it.setItemName(detailItem.getItemName());
                            it.setItemNum(detailItem.getItemNumber());
                            ls.add(it);
                        }
////                        detailName.substring(1);
//                        data.setDetailName(detailName);
                        data.setOrderItems(ls);
                        data.setType(0);
                        list.add(data);
//                        map.put("hisClinicCode", payItem.getClinicCode());
//                        map.put("hisOrderNo", payItem.getHisOrdNum());
//                        map.put("patientName", pName);
//                        map.put("orderInsType", payItem.getOrderInsType());
//                        map.put("patientAge", pAge);
//                        map.put("patientSex", pGender);
//                        map.put("doctorCode", payItem.getDoctorCode());

//                        map.put("detailItems", items);
//                        lst.add(map);
                        // 保存门诊缴费明细到数据库
                        SaveOutpatientOrderDetailsRequest sReq = SaveOutpatientOrderDetailsRequest.newBuilder()
                                .setHisOrderNo(payItem.getHisOrdNum())
                                .addAllDetail(payItem.getItemListList().stream()
                                        .map(i -> OutpatientOrderDetail.newBuilder()
                                                .setItemName(i.getItemName())
                                                .setItemPrice(i.getItemPrice())
                                                .setItemCode(i.getItemCode())
                                                .setItemNumber(i.getItemNumber())
                                                .setItemSpec(i.getItemSpec())
                                                .setItemUnit(i.getItemUnit())
                                                .setItemTotalFee(i.getItemTotalFee())
                                                .build()).collect(Collectors.toList()))
                                .build();
                        BaseResult baseResult = taiheOutpatientServiceBlockingStub.saveOutpatientOrderDetails(sReq);
                        if (baseResult.getCode() != ResultCode.SUCCEED_VALUE) {
                            throw new RuntimeException("保存门诊缴费明细失败");
//                            logger.error("保存门诊缴费明细失败，hisOrderNo : {}", payItem.getHisOrdNum());
                        }
                    }
                }
                break;
            case TYPE_PAID_ZFB:
                switch (hospitalId) {
                    default:
                    case Constants.HOSPITAL_ID_NFYYBYFY:
                        // v1.3.7 白云改为从 HIS 接口读取数据
                        String startDate = request.getStartTime();
                        String endDate = request.getEndTime();
                        Date start = DateUtil.parseDate(startDate, DateUtil.DADE_FROMAT_YMD);
                        Date end = DateUtil.parseDate(endDate, DateUtil.DADE_FROMAT_YMD);
                        if (Checker.isNone(start) || Checker.isNone(end)) {
                            Pagination pagination = new Pagination(pageIndex, pageSize, total);
                            PageVO<PayHistoryResponseData> res = new PageVO<>(pagination, list);
                            return res;
                        }
//                        CheckUtil.ensureNotNull(start, "请选择时间");
//                        CheckUtil.ensureNotNull(end, "请选择时间");
                        long day = 0;
                        day = DateUtil.getDaySub(request.getEndTime(), request.getStartTime());
                        if (day < -15) {
//                            throw new AppMessageException("请选择15天以内");
                            Pagination pagination = new Pagination(pageIndex, pageSize, total);
                            PageVO<PayHistoryResponseData> res = new PageVO<>(pagination, list);
                            return res;
                        }
                        GetOutpatientListRequest req3 = GetOutpatientListRequest.newBuilder()
                                .setPatientId(hisPatientId)
                                .setType(TYPE_PAID_WX)
                                .setHospitalId(hospitalId)
                                .setStartDate(startDate)
                                .setEndDate(endDate)
                                .build();
                        GetOutpatientListResponse res3 = taiheServiceBlockingStub.getOutpatientList(req3);
                        if (res3.getCode() != ResultCode.SUCCEED_VALUE) {
//                            throw new RuntimeException(res3.getMsg());
                            Pagination pagination = new Pagination(pageIndex, pageSize, total);
                            PageVO<PayHistoryResponseData> res = new PageVO<>(pagination, list);
                            return res;

                        }
                        total = res3.getPaymentList().size();
                        for (PaymentItem payItem : res3.getPaymentList()) {
                            PayHistoryResponseData data = new PayHistoryResponseData();
                            data.setStatus(status);
                            data.setTitle("");
                            data.setDeptName(payItem.getDeptName());
                            data.setPrescribeDate(payItem.getPrescriptionDate());
                            data.setName(resp.getPatientName());
                            data.setAmount(String.format("%.2f", payItem.getTotalFee() / 100d));
                            data.setTradeNo(""); //Todo
                            data.setOutTradeNo("");//Todo
                            data.setIdNum("");//Todo
                            data.setInvoiceNo(payItem.getInvoiceNo());
                            data.setHisPatientId(hisPatientId);
                            data.setPayTime(payItem.getPrescriptionDate());
                            data.setTotal(Checker.getIntegerValue(payItem.getTotalFee()));
                            data.setDoctorName(Checker.getStringValue(payItem.getDoctorName()));
                            data.setDoctorCode(Checker.getStringValue(payItem.getDoctorCode()));
                            data.setHisClinicCode(Checker.getStringValue(payItem.getClinicCode()));
                            data.setAge(Checker.getIntegerValue(pAge));
                            data.setType(0);
                            list.add(data);
                        }
                        break;
                    case Constants.TAIHE_HOSPITAL_ID:
                        // 太和已缴费列表读取数据库
                        GetOutpatientOrderListRequest req2 = GetOutpatientOrderListRequest.newBuilder()
                                .setType(TYPE_PAID)
                                .setHisPatientId(hisPatientId)
                                .setPageIndex(PAGE_INDEX)
                                .setPageSize(PAGE_SIZE)
                                .setUserId(userId)
                                .setHospitalId(hospitalId)
                                .build();
                        GetOutpatientOrderListResponse res = orderServiceBlockingStub.getOutpatientOrderList(req2);
                        Result result2 = res.getResult();
                        if (result2.getCode() != ResultCode.SUCCEED) throw new AppMessageException(result2.getInfo());
                        for (OutpatientOrder order : res.getOrderList()) {
                            PayHistoryResponseData data = new PayHistoryResponseData();
                            data.setStatus(status);
                            data.setTitle("");
                            data.setDeptName(order.getDeptName());
                            data.setPrescribeDate(DateUtil.convertTimestampToDateString(order.getPrescriptionDate()));
                            data.setName(resp.getPatientName());
                            data.setAmount(String.format("%.2f", order.getTotal() / 100d));
                            data.setTradeNo(""); //Todo
                            data.setOutTradeNo("");//Todo
                            data.setIdNum("");//Todo
                            data.setInvoiceNo(order.getInvoiceNo());
                            data.setHisPatientId(hisPatientId);
//                            data.setPayTime(payItem.getPrescriptionDate());
                            data.setTotal(Checker.getIntegerValue(order.getTotal()));
                            data.setDoctorName(Checker.getStringValue(order.getDoctorName()));
                            data.setDoctorCode(Checker.getStringValue(order.getDoctorCode()));
//                            data.setHisClinicCode(Checker.getStringValue(payItem.getClinicCode()));
                            data.setAge(Checker.getIntegerValue(pAge));
                            data.setType(0);
                            list.add(data);
                        }
                        break;
                }
                break;
        }
        Pagination pagination = new Pagination(pageIndex, pageSize, total);
        PageVO<PayHistoryResponseData> res = new PageVO<>(pagination, list);
        return res;
    }

    @Override
    public ComputeSelfPaidOrderResponseData computeSelfPaidOrder(ComputeSelfPaidOrderRequest request) {
        return null;
    }

    @Override
    public ComputeMedicarePayOrderResponseData computeMedicarePayOrder(ComputeMedicarePayOrderRequest request) {
        return null;
    }

    @Override
    public TradeNoForOrderResponseData tradeNoForOrder(TradeNoForOrderRequest request) throws Exception {
        TradeNoForOrderResponseData data = new TradeNoForOrderResponseData();
        int userId = ContextHelper.getCurrentUserIdWrapped();
        int hospitalId = BizUtil.getCurrentHospitalId();
        int terminal = ContextHelper.getCurrentTerminalWrapped();
        String invoiceNo = prePayConfirm(request.getHisPatientId(), request.getHisClinicCode(), request.getHisOrderNo(), hospitalId, request.getTotal());
        Date pDate = DateUtil.parseDate(request.getPrescribeDate(), "yyyy-MM-dd HH:mm:ss");
        int sex = 1;
        if (request.getSex().equals("女")) {
            sex = 2;
        }

        //该版本只有自费，没有医保
        CreateOutpatientOrderRequest req = CreateOutpatientOrderRequest.newBuilder()
                .setDeptCode("")
                .setDeptName(request.getDeptName())
                .setDoctorCode(request.getDoctorCode())
                .setDoctorName(request.getDoctorName())
                .setTotal(request.getTotal())
                .setReimbursement(0)
                .setIndividual(request.getTotal())
                .setHisPatientId(request.getHisPatientId())
                .setHisClinicCode(request.getHisClinicCode())
                .setHisOrderNo(request.getHisOrderNo())
                .setPayName(request.getName())
                .setPrescriptionDate(Checker.isNone(pDate) ? 0L : pDate.getTime())
                .setPatientName(request.getName())
                .setPatientAge(request.getAge())
                .setPatientSex(sex)
                .setOrderInsType("自费")
                .setInvoiceNo(invoiceNo)
                .setPayInsType(1)
                .setHospitalId(hospitalId)
                .setTerminal(terminal)
                .build();
        Result result = orderServiceBlockingStub.createOutpatientOrder(req);
        if (result.getCode() != ResultCode.SUCCEED) {
            throw new AppMessageException(result.getInfo());
        }
        String orderNo = result.getValue();
        int orderId = getOrderIdByOrderNo(orderNo);
        //判断是否已线下缴费
        com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailRequest requ =
                com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailRequest.newBuilder()
                        .setOrderId(orderId).build();
        com.ywt.gapi.taihe.outpaitent.GetOutpatientDetailResponse res = taiheOutpatientServiceBlockingStub.getOutpatientDetail(requ);
        if (res.getCode() != ResultCode.SUCCEED_VALUE) {
            throw new AppMessageException(res.getMsg());
        }
        com.ywt.gapi.taihe.outpaitent.OutpatientOrder order = res.getOrder();
        if (order.getPaymentStatus() == PaymentStatusEnum.Success.getValue()) {
            throw new AppMessageException("该订单已缴费");
        }
        CreateAlipayOrderResponse response = orderCenterServiceBlockingStub.createAlipayOrder(CreateAlipayOrderRequest.newBuilder()
                .setBody("门诊缴费")
                .setAlipayUid(request.getAlipayUid())
                .setOrderId(orderId)
                .setOrderNo(orderNo)
                .setAmount(request.getTotal())
                .setUserId(userId)
                .setTerminal(ContextHelper.getCurrentTerminalWrapped())
                .build());
        if (response.getCode() != ResultCode.SUCCEED_VALUE) {
            throw new AppMessageException(response.getInfo());
        }
        data = new TradeNoForOrderResponseData();
        data.setNeedPay(true);//设置是否需要支付宝自费支付
        data.setOutTradeNo(orderNo);
        data.setTradeNo(response.getTradeNo());
        return data;
    }


    /**
     * 根据身份证或出生日期获取年龄，避免当身份证为空的情况下获取年龄会返回奇怪的值
     *
     * @param idNo     身份证
     * @param birthday 出生年月日，格式 yyyy-MM-dd
     * @return
     */
    private int getPatientAgeSafely(String idNo, String birthday) {
        if (!Checker.isNone(idNo)) {
            return IdCardUtil.getCurrentAge(idNo);
        } else {
//            logger.info("DHOutpatientController#getPatientAgeSafely(birthday = {}): 身份证为空", birthday);
            return IdCardUtil.getCurrentAgeByBirthday(birthday, IdCardUtil.DATE_PATTERN2);
        }
    }

    private String prePayConfirm(String patientId, String clinicCode, String hisOrdNum, int hospitalId, int orderSum) throws AppMessageException {
        PrePayConfirmRequest req = PrePayConfirmRequest.newBuilder()
                .setCardNo("")
                .setPatientId(patientId)
                .setStartDate("")
                .setEndDate("")
                .setClinicCode(clinicCode)
                .setHisOrdNum(hisOrdNum)
                .setOrderSum(orderSum)
                .setHospitalId(hospitalId)
                .setPayMode(Constants.HIS_PAY_MODE_ALIPAY)
                .build();
        PrePayConfirmResponse response = taiheServiceBlockingStub.prePayConfirm(req);
        if (response.getCode() == ResultCode.SUCCEED_VALUE) {
            if (!Checker.isNone(response.getListList())) {
                // 预结算成功，自动取消之前生成的未支付订单，让前端可以重新创建订单
                autoCancelPrevOrder(hisOrdNum);
                PrePayConfirm p = response.getListList().get(0);
                String invoiceNo = p.getInvoiceNo();
                return invoiceNo;
            }
            throw new AppMessageException("预结算：HIS 返回列表数据为空");
        }
        throw new AppMessageException(response.getMsg());
    }

    private void autoCancelPrevOrder(String hisOrderNo) throws AppMessageException {
        GetOutpatientOrderByHisOrderNoRequest request = GetOutpatientOrderByHisOrderNoRequest.newBuilder()
                .setHisOrderNo(hisOrderNo)
                .setHospitalId(BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped()))
                .build();
        GetOutpatientOrderByHisOrderNoResponse response = taiheOutpatientServiceBlockingStub.getOutpatientOrderByHisOrderNo(request);
        if (response.getCode() == ResultCode.SUCCEED_VALUE) {
            String orderNo = response.getOrderNo();
            if (!StringHelper.isNullOrEmpty(orderNo)) {
//                logger.info("DHOutpatientController#autoCancelPrevOrder(): 预结算自动取消之前生成的订单 orderNo = {}", orderNo);
                MarkOpOrderDeletedResponse markOpOrderDeletedResponse = wxInsPayServiceBlockingStub.markOpOrderDeleted(
                        MarkOpOrderDeletedRequest.newBuilder()
                                .setOrderNo(orderNo)
                                .build());
                if (markOpOrderDeletedResponse.getCode() != ResultCode.SUCCEED_VALUE) {

                    throw new AppMessageException(markOpOrderDeletedResponse.getMsg());
                }
            }
        } else {
            throw new AppMessageException(response.getMsg());
        }
    }

    //判断是否已线下缴费
    public GetOutpatientListResponse getOutpatientList(String hisPatientId, int type, Integer hospitalId) {
        int hid = Checker.getIntegerValue(hospitalId) > 0 ? hospitalId : Constants.TAIHE_HOSPITAL_ID;
        GetOutpatientListRequest req = GetOutpatientListRequest.newBuilder()
                .setPatientId(hisPatientId)
                .setType(type)
                .setHospitalId(hid)
                .build();
        return taiheServiceBlockingStub.getOutpatientList(req);
    }

    public int getOrderIdByOrderNo(String orderNo) {
        GetOrderInfoRequest request = GetOrderInfoRequest.newBuilder().setOrderNo(orderNo).build();
        GetOrderInfeResponse getOrderInfeResponse = orderCenterServiceBlockingStub.getOrderInfo(request);
        return getOrderInfeResponse.getOrderId();
    }
}
