package com.ywt.outpatient.service.common;

import com.ywt.biz.common.util.Checker;
import com.ywt.biz.common.util.DateUtil;
import com.ywt.gapi.ResultCode;
import com.ywt.gapi.third.taihe.*;
import com.ywt.outpatient.core.Constants;
import com.ywt.outpatient.service.rpc.common.ServiceResult;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.*;

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

    @DubboReference
    private TaiheService taiheServiceBlockingStub;

    /**
     * 医保试算接口
     *
     * @param patientId     患者his的patientId
     * @param date          处方日期
     * @param hisOrderNum   处方编号：hisOrderNO
     * @param insureKey     医保Key
     * @param insureBizType 医保Key
     * @param insureTreatmentType 医保Key
     * @return
     */
    public CalInsuranceResponse calInsurance(String patientId, String date, String hisOrderNum, String insureKey,
                                             String insureBizType, String insureTreatmentType, int hospitalId) {
        try {
            CalInsuranceRequest req = CalInsuranceRequest.newBuilder()
                    .setPatientId(patientId)
                    .setPrescriptionDate(date)
                    .setHisOrdNum(hisOrderNum)
                    .setInsureKey(insureKey)
                    .setInsureBizType(insureBizType)
                    .setInsureTreatmentType(insureTreatmentType)
                    .setHospitalId(hospitalId)
                    .build();
            return taiheServiceBlockingStub.calInsurance(req);

        } catch (Exception e) {
            logger.error("医保试算接口: calInsurance(): {}", e.getMessage(), e);
            return null;
        }
    }


    /**
     * 获取医生列表
     *
     * @param doctorName
     * @param deptCode
     * @param doctorCode
     * @return
     */
    public GetDoctorListResponse getDoctorList(String doctorName, String deptCode, String doctorCode, int hospitalId) {
        try {
            GetDoctorListRequest req = GetDoctorListRequest.newBuilder()
                    .setDoctorName(doctorName)
                    .setDeptCode(deptCode)
                    .setDoctorCode(doctorCode)
                    .setHospitalId(hospitalId)
                    .build();
            return taiheServiceBlockingStub.getDoctorList(req);
        } catch (Exception e) {
            logger.error("getDoctorList(): {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取患者信息
     *
     * @param patientCard
     * @param patientId
     * @param idNo
     * @param patientName
     * @return
     */
    public GetPatientInfoResponse getPatientInfo(String patientCard, String patientId, String idNo, String patientName,
                                                 int hospitalId) {
        try {
            GetPatientInfoRequest request = GetPatientInfoRequest.newBuilder()
                    .setPatientCard(patientCard)
                    .setPatientId(patientId)
                    .setIdNo(idNo)
                    .setPatientName(patientName)
                    .setHospitalId(hospitalId)
                    .build();
            return taiheServiceBlockingStub.getPatientInfo(request);
        } catch (Exception e) {
            logger.error("getPatientInfo({}, {}, {}, {}): {}", patientCard, patientId, idNo, patientName, e.getMessage());
            return null;
        }
    }

    /**
     * 预约挂号
     *
     * @param scheduleItemCode 门诊排班项代码
     * @param patientId        病人ID
     * @param cardNo           卡号
     * @param startTime        开始时间(09:00)
     * @param endTime          结束时间(09:30)
     * @return
     */
    public ServiceResult createOrder(String scheduleItemCode, String patientId, String cardNo,
                                     String startTime, String endTime, int hospitalId) {
        ServiceResult serviceResult = new ServiceResult();
        try {
            RegisterRequest req = RegisterRequest.newBuilder()
                    .setScheduleItemCode(scheduleItemCode)
                    .setPatientId(patientId)
                    .setCardNo(cardNo)
                    .setStartTime(startTime)
                    .setEndTime(endTime)
                    .setHospitalId(hospitalId)
                    .build();
            RegisterResponse res = taiheServiceBlockingStub.register(req);

            if (res.getCode() == 0) {
                Map<String, Object> map = new HashMap<>();
                map.put("seqCode", res.getSeqCode());              //挂号序号
                map.put("regFee", res.getRegFee());                //挂号费
                map.put("admitRange", res.getAdmitRange());        //就诊时间段
                map.put("admitAddress", res.getAdmitAddress());    //就诊地点
                map.put("orderContent", res.getOrderContent());    //预约单内容（内容说明：卡号^病人Rowid^病人姓名^性别^挂号序号(班别)^挂号序号^科室名称^医生姓名^预约日期^时间^候诊日期^^）
                map.put("orderCode", res.getOrderCode());          //预约单号

                return serviceResult.succeed(res.getMsg(), map);
            }

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

    /**
     * 在线取号
     *
     * @param orderCode
     * @param patientId
     * @return
     */
    public ServiceResult take(String orderCode, String patientId, Integer hospitalId) {
        ServiceResult serviceResult = new ServiceResult();

        try {
            TakeRequest request = TakeRequest.newBuilder()
                    .setOrderCode(orderCode)
                    .setPatientId(patientId)
                    .setHospitalId(Checker.getIntegerValue(hospitalId))
                    .buildPartial();

            TakeResponse response = taiheServiceBlockingStub.take(request);

            if (response.getCode() == 0) {
                Map<String, Object> map = new HashMap<>();
                map.put("registrationId", response.getRegistrationId());             //就诊流水号

                return serviceResult.succeed(response.getMsg(), map);
            }

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

    /**
     * 取消预约
     * 东华 HIS 退号目前是用 ClinicCode
     *
     * @param orderCode 就诊流水号
     * @return
     */
    public ServiceResult cancelOrder(String orderCode, String hisClinicCode, int hospitalId, String transactionId) {
        ServiceResult serviceResult = new ServiceResult();

        try {
            CancelRequest request = CancelRequest.newBuilder()
                    .setOrderCode(orderCode)
                    .setClinicCode(hisClinicCode)
                    .setHospitalId(hospitalId)
                    .setTransactionId(transactionId)
                    .build();
            CancelResponse response = taiheServiceBlockingStub.cancel(request);

            if (response.getCode() == 0) {
                logger.info("TaiheProvider#cancelOrder(orderCode={} , hisClinicCode={} ): 退号成功", orderCode, hisClinicCode);
                return serviceResult.succeed(response.getMsg());
            }

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

    /**
     * 挂号（无须支付）
     *
     * @param orderCode
     * @param patientId
     * @return
     */
    public ServiceResult payFree(String orderCode, String patientId, int hospitalId) {
        ServiceResult serviceResult = new ServiceResult();

        PayFreeRequest req = PayFreeRequest.newBuilder()
                .setOrderCode(orderCode)
                .setPatientId(patientId)
                .setHospitalId(hospitalId)
                .build();
        PayFreeResponse res = taiheServiceBlockingStub.payFree(req);

        if (res.getCode() == ResultCode.SUCCEED_VALUE) {
            return serviceResult.succeed(res.getMsg());
        }

        return serviceResult.failed(res.getMsg());
    }

    /**
     * 支付（挂号费大于0情况）
     *
     * @param orderCode     预约单号
     * @param transactionId 交易流水号（微信支付）
     * @param patientId     病人ID（CardNo为空时必填）
     * @param cardNo        卡号（PatID为空时，必填）
     * @param payAmount     支付金额（单位：分，自费部分金额）
     * @param payTime       支付时间（格式：yyyy-MM-dd HH:mm:ss）
     * @return
     */
    public ServiceResult pay(String orderCode, String transactionId, String patientId,
                             String cardNo, int payAmount, String payTime, int hospitalId) {
        ServiceResult serviceResult = new ServiceResult();

        PayRequest req = PayRequest.newBuilder()
                .setOrderCode(orderCode)
                .setTransactionId(transactionId)
                .setPatientId(patientId)
                .setCardNo(cardNo)
                .setPayAmount(payAmount)
                .setPayMode("wxPay")        //支付方式（wxPay：微信支付）
                .setPayTime(payTime)
                .setHospitalId(hospitalId)
                .build();
        PayResponse res = taiheServiceBlockingStub.pay(req);

        if (res.getCode() == ResultCode.SUCCEED_VALUE) {
            return serviceResult.succeed(res.getMsg());
        }

        return serviceResult.failed(res.getMsg());
    }

    /**
     * 医保试算
     *
     * @param hisPatientId
     * @param hisOrderNo
     * @param prescriptionDate
     * @param insureKey
     * @param insureBizType
     * @param insureTreatmentType
     * @param insureFeeType
     * @return
     */
    public ServiceResult calInsurance(
            String hisPatientId, String hisOrderNo, Date prescriptionDate, String insureKey,
            String insureBizType, String insureTreatmentType, String insureFeeType) {
        ServiceResult serviceResult = new ServiceResult();

        try {
            CalInsuranceRequest req = CalInsuranceRequest.newBuilder()
                    .setPatientId(hisPatientId)
                    .setPrescriptionDate(DateUtil.convertToString(prescriptionDate))
                    .setHisOrdNum(hisOrderNo)
                    .setInsureKey(insureKey)
                    .setInsureBizType(insureBizType)
                    .setInsureTreatmentType(insureTreatmentType)
                    .build();
            CalInsuranceResponse res = taiheServiceBlockingStub.calInsurance(req);

            if (res.getCode() == ResultCode.SUCCEED_VALUE) {
                Map<String, Object> map = new HashMap<>();
                map.put("total", res.getTotal());
                map.put("reimbursement", res.getReimbursement());
                map.put("individual", res.getIndividual());
                map.put("insureKey", insureKey);
                map.put("insureBizType", insureBizType);
                map.put("insureTreatmentType", insureTreatmentType);
                map.put("insureFeeType", insureFeeType);

                serviceResult.setData(map);
                return serviceResult.succeed();
            }

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

    /**
     * 排队信息
     *
     * @param registrationId
     * @return
     */
    public ServiceResult getQueueInfo(String registrationId, Integer hospitalId) {
        int hid = Checker.getIntegerValue(hospitalId) > 0 ? hospitalId : Constants.TAIHE_HOSPITAL_ID;
        ServiceResult serviceResult = new ServiceResult();

        GetQueueInfoRequest req = GetQueueInfoRequest.newBuilder()
                .setRegistrationId(registrationId)
                .setHospitalId(hid)
                .build();
        GetQueueInfoResponse res = taiheServiceBlockingStub.getQueueInfo(req);

        if (res.getCode() == ResultCode.SUCCEED_VALUE) {
            Map<String, Object> data = new HashMap<>();
            data.put("waitingNumber", res.getQueueInfo().getWaitingNumber());
            serviceResult.setData(data);
            return serviceResult.succeed();
        }

        return serviceResult.failed(res.getMsg());
    }

    /**
     * 获取加号信息
     *
     * @param hisPatientId
     * @param cardNo
     * @param patientName
     * @param idNo
     * @return
     */
    public GetAddInfoResponse getAddInfo(String hisPatientId, String cardNo, String patientName, String idNo) {
        GetAddInfoRequest req = GetAddInfoRequest.newBuilder()
                .setPatientId(hisPatientId)
                .setCardNo(cardNo)
                .setPatientName(patientName)
                .setIdNo(idNo)
                .build();
        return taiheServiceBlockingStub.getAddInfo(req);
    }

    /**
     * 获取门诊缴费单列表
     *
     * @param hisPatientId
     * @param type         类型：1-门诊待缴费记录 2-门诊已缴费记录 3-门诊已退费记录
     * @return
     */
    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);
    }

    /**
     * 获取病历详情
     *
     * @param hisPatientId
     * @param registrationId
     * @return
     */
    public GetMedicalRecordResponse getMedicalRecord(String hisPatientId, int registrationId, int hospitalId) {
        GetMedicalRecordRequest req = GetMedicalRecordRequest.newBuilder()
                .setPatientId(hisPatientId)
                .setRegistrationId(registrationId)
                .setHospitalId(hospitalId)
                .build();
        return taiheServiceBlockingStub.getMedicalRecord(req);
    }

    /**
     * 获取挂号记录
     *
     * @param hisPatientId
     * @param cardNo
     * @param endDate
     * @return
     */
    public GetRegistrationListResponse getRegistrationList(String hisPatientId, String cardNo, String startDate,
                                                           String endDate, int hospitalId) {
        startDate = !Checker.isNone(startDate) ? startDate :"2018-01-01" ;
        GetRegistrationListRequest req = GetRegistrationListRequest.newBuilder()
                .setPatientId(hisPatientId)
                .setCardNo(cardNo)
                .setStartDate(startDate)
                .setEndDate(endDate)
                .setHospitalId(hospitalId)
                .build();
        return taiheServiceBlockingStub.getRegistrationList(req);
    }

    /**
     * 判断医生在指定科室、指定日期时间段内是否有排班
     *
     * @param serviceDate
     * @param period
     * @param doctorCode
     * @param deptCode
     * @return
     */
    public boolean hasScheduling(String serviceDate, int period, String doctorCode, String deptCode) {
        GetScheduleTimeInfoRequest getScheduleTimeInfoRequest = GetScheduleTimeInfoRequest.newBuilder()
                .setDeptCode(deptCode)
                .setDoctorCode(doctorCode)
                .setServiceDate(serviceDate)
                .setDatePeriod(period)
                .build();
        GetScheduleTimeInfoResponse getScheduleTimeInfoResponse = taiheServiceBlockingStub.getScheduleTimeInfo(getScheduleTimeInfoRequest);

        if (getScheduleTimeInfoResponse.getCode() == ResultCode.SUCCEED_VALUE) {
            if (getScheduleTimeInfoResponse.getScheduleTimeInfosList().size() > 0) {
                return true;
            }
        }

        return false;
    }

    public List<Schedule> getScheduleList(String deptCode, String doctorCode, String serviceDate, Integer hospitalId) {
        List<Schedule> scheduleList;
        GetScheduleListRequest getScheduleListRequest = GetScheduleListRequest.newBuilder()
                .setDeptCode(deptCode)
                .setDoctorCode(doctorCode)
                .setServiceDate(serviceDate)
                .setHospitalId(Checker.getIntegerValue(hospitalId))
                .build();
        GetScheduleListResponse getScheduleListResponse = taiheServiceBlockingStub.getScheduleList(getScheduleListRequest);

        if (getScheduleListResponse.getCode() == ResultCode.SUCCEED_VALUE) {
            scheduleList = getScheduleListResponse.getSchedulesList();
        } else {
            scheduleList = new LinkedList<>();
        }
        return scheduleList;
    }
}
