package com.ywt.outpatient.controllers.taihe;

import com.ywt.biz.common.constant.YwtCommonRespCode;
import com.ywt.biz.common.enums.PaymentChannelEnum;
import com.ywt.biz.common.enums.PaymentStatusEnum;
import com.ywt.biz.common.enums.TerminalEnum;
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.base.lbs.GetDistanceRequest;
import com.ywt.gapi.base.lbs.GetDistanceResponse;
import com.ywt.gapi.base.lbs.LbsService;
import com.ywt.gapi.doctor.*;
import com.ywt.gapi.medicalrecord.*;
import com.ywt.gapi.medicalrecord.MedicalRecord;
import com.ywt.gapi.offline.CreateOfflineConsultationRequest;
import com.ywt.gapi.offline.CreateOfflineConsultationResponse;
import com.ywt.gapi.offline.OfflineConsultingService;
import com.ywt.gapi.order.CreateTaiheRegisteredOrderRequest;
import com.ywt.gapi.order.CreateTaiheRegisteredOrderResponse;
import com.ywt.gapi.order.OrderService;
import com.ywt.gapi.system.Dept;
import com.ywt.gapi.system.*;
import com.ywt.gapi.taihe.register.*;
import com.ywt.gapi.third.taihe.Doctor;
import com.ywt.gapi.third.taihe.*;
import com.ywt.gapi.user.*;
import com.ywt.outpatient.api.req.CreateMedCardReq;
import com.ywt.outpatient.api.resp.BaseResponse2;
import com.ywt.outpatient.api.resp.CreateMedCardResp;
import com.ywt.outpatient.config.ParameterConfigurer;
import com.ywt.outpatient.controllers.DevController;
import com.ywt.outpatient.core.BaseResponse;
import com.ywt.outpatient.core.annotations.UserLogin;
import com.ywt.outpatient.core.utils.BizUtil;
import com.ywt.outpatient.core.utils.CheckUtil;
import com.ywt.outpatient.core.utils.IdCardUtil;
import com.ywt.outpatient.core.Constant;
import com.ywt.outpatient.api.checkIn.*;
import com.ywt.outpatient.domain.models.enums.DatePeriodEnum;
import com.ywt.outpatient.domain.models.enums.OfflineConsultationSourceEnum;
import com.ywt.outpatient.api.union_reg.*;
import com.ywt.outpatient.service.web.DoctorSrv;
import com.ywt.outpatient.service.web.MedicalCardService;
import com.ywt.outpatient.service.web.SystemSrv;
import com.ywt.outpatient.service.web.UserSrv;
import com.ywt.outpatient.core.WebAppContext;
import com.ywt.outpatient.service.web.taihe.TaiheUserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@RestController("/taihe/register")
@RequestMapping({"/taihe/register"})
public class RegisterController {
    private static Logger logger = LoggerFactory.getLogger(RegisterController.class);

    @DubboReference
    private TaiheService taiheServiceBlockingStub;

    @DubboReference
    private OrderService orderServiceBlockingStub;

    @DubboReference
    private UserService userServiceBlockingStub;

    @Autowired
    private TaiheUserService userService;

    @DubboReference
    private DoctorService doctorServiceBlockingStub;

    @DubboReference
    private MedicalRecordService medicalRecordServiceBlockingStub;

    @DubboReference
    private OfflineConsultingService offlineConsultingServiceBlockingStub;

    @Autowired
    private SystemSrv systemSrv;

    @Autowired
    private DoctorSrv doctorSrv;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @DubboReference
    private TaiheRegisterService taiheRegisterServiceBlockingStub;

    @DubboReference
    private SystemService systemServiceBlockingStub;

    @Autowired
    private ParameterConfigurer parameterConfigurer;

    @Autowired
    private DevController devController;

    @DubboReference
    private LbsService lbsServiceBlockingStub;

    @Autowired
    private UserSrv userSrv;

    @Autowired
    private MedicalCardService medicalCardService;


    /**
     * 科室列表
     *
     * @return
     */
    @UserLogin(need = false)
    @RequestMapping({"/deptList"})
    public @ResponseBody
    BaseResponse getDeptList(@RequestParam(name = "subHospitalId", required = false, defaultValue = "0") int subHospitalId,
                             @RequestParam(name = "hospitalId", required = false, defaultValue = "0") int hospitalId,
                             @RequestParam(name = "name", required = false, defaultValue = "") String name) {
        int hId = hospitalId > 0 ? hospitalId : BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
        return systemSrv.getDeptList(hId, subHospitalId, name);
    }



    /**
     * 医生列表
     *
     * @param deptCode
     * @param doctorName
     * @return
     */
    @UserLogin(need = false)
    @RequestMapping({"/doctorList"})
    public @ResponseBody
    BaseResponse getDoctorList(@RequestParam(name = "hospitalId") int hospitalId,
                               @RequestParam(name = "deptCode", required = false, defaultValue = "") String deptCode,
                               @RequestParam(name = "doctorName", required = false, defaultValue = "") String doctorName) {
        BaseResponse response = new BaseResponse();

//        if (hospitalId != 12) {
//            return response.failed(BaseResponse.PARAMETER_ERROR, "医院不存在");
//        }

        try {
            int hId = hospitalId > 0 ? hospitalId : BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
            GetDoctorListRequest getDoctorListRequest = GetDoctorListRequest.newBuilder()
                    .setDeptCode(deptCode)
                    .setDoctorName(doctorName)
                    .setHospitalId(hId)
                    .build();
            GetDoctorListResponse getDoctorListResponse = taiheServiceBlockingStub.getDoctorList(getDoctorListRequest);

            if (getDoctorListResponse.getCode() == ResultCode.SUCCEED_VALUE) {
                List<Doctor> doctorsList = getDoctorListResponse.getDoctorsList();
                List<Map<String, Object>> doctorList = new LinkedList<>();

                for (Doctor doctor : doctorsList) {

                    Map<String, Object> doctorMap = new LinkedHashMap<>();
                    doctorMap.put("doctorCode", doctor.getDoctorCode());        //医生代码
                    doctorMap.put("doctorName", doctor.getDoctorName());        //医生名称
                    doctorMap.put("doctorTitle", doctor.getDoctorTitle());      //医生职称
                    doctorMap.put("doctorSpeciality", doctor.getDoctorSpeciality());    //医生擅长
                    doctorMap.put("doctorIntro", doctor.getDoctorIntro());              //医生简介
                    doctorMap.put("deptName", doctor.getDoctorDept());                //医生科室
                    doctorMap.put("deptCode", doctor.getDoctorDeptCode());        //医生科室代码

                    doctorList.add(doctorMap);
                }

                Map<String, Object> map = new LinkedHashMap<>();
                map.put("hospitalId", hospitalId);
                map.put("count", getDoctorListResponse.getCount());
                map.put("list", doctorList);
                response.setData(map);
                return response.succeed("处理成功");
            }

            return response.failed(BaseResponse.APP_ERROR, getDoctorListResponse.getMsg());
        } catch (Exception e) {
            logger.error("getDoctorList():{}", e.getMessage());
            return response.failed(BaseResponse.APP_EXCEPTION, Constant.ERROR_PROMPT);
        }
    }

    /**
     * 得到排班记录
     * 太和公众号使用
     *
     * @param hospitalId
     * @param deptCode
     * @param doctorCode
     * @param serviceDate
     * @return
     */
    @UserLogin(need = false)
    @RequestMapping({"/schedule"})
    public @ResponseBody
    BaseResponse getScheduleList(@RequestParam(name = "hospitalId", required = false) Integer hospitalId,
                                 @RequestParam(name = "deptCode", defaultValue = "") String deptCode,
                                 @RequestParam(name = "doctorCode", required = false, defaultValue = "") String doctorCode,
                                 @RequestParam(name = "serviceDate", required = false) String serviceDate,
                                 @RequestParam(name = "serviceCode", defaultValue = "", required = false) String serviceCode) {
        BaseResponse response = new BaseResponse();
        String firstCode = deptCode;
        Map<String, Object> map;

        if (doctorCode.equals("0")) {
            doctorCode = "";
        }
        if (Checker.getIntegerValue(hospitalId) <= 0) {
            hospitalId = BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
        }
        String key = String.format("SCHEDULE_LIST_%s_%s_%d_%s", deptCode, doctorCode, hospitalId, serviceCode);

        try {
            String value = redisTemplate.opsForValue().get(key)+"";
            if (!StringHelper.isNullOrWhiteSpace(value)) {
                Map cacheMap = JsonSerializer.from(value, Map.class);
                if (cacheMap != null) {
                    return response.succeed("处理成功", cacheMap);
                }
            }
            List<Dept> deptList = systemSrv.getDeptListByHospitalId(hospitalId);

            if (deptList == null || deptList.size() == 0) {
                return response.failed(BaseResponse.APP_ERROR, "invalid request");
            }

            List<Dept> tmpDeptList = deptList.stream().filter(p -> p.getDeptCode().equals(deptCode)).collect(Collectors.toList());

            if (tmpDeptList.size() == 0) {
                return response.failed(BaseResponse.PARAMETER_ERROR, "deptCode not exist");
            }

            Dept secDept = tmpDeptList.get(0);
            tmpDeptList = deptList.stream().filter(p -> p.getDeptId() == secDept.getParentId()).collect(Collectors.toList());

            if (tmpDeptList.size() == 0) {
                return response.failed(BaseResponse.PARAMETER_ERROR, "invalid deptCode");
            }

//            Dept firstDept = tmpDeptList.get(0);
//            firstCode = firstDept.getDeptCode();

            map = new HashMap<>();
            map.put("hospitalId", hospitalId);
            map.put("hospitalName", BizUtil.getHospitalNameByIdSimply(hospitalId));
            map.put("deptCode", deptCode);
            map.put("deptName", secDept.getDeptName());

            List<Map<String, Object>> lst = new LinkedList<>();
            Calendar calendar = Calendar.getInstance();

            List<DeptScheduleDoctor> doctorList = doctorSrv.getDeptScheduleDoctorListFromCache();
            doctorList = doctorList.stream().filter(p -> p.getDeptCode().equals(deptCode)).collect(Collectors.toList());

            GetScheduleListRequest getScheduleListRequest;
            GetScheduleListResponse getScheduleListResponse;
            List<Schedule> scheduleList;

            int nDaysMore = 8;
            // 2021年4月13日
            // 临时调整：白云分院排班记录只返回 6 天的数据
            if (hospitalId == Constant.NFYYBYFY_HOSPITAL_ID) {
                nDaysMore = 6;
            }
            for (int offset = 0; offset < nDaysMore; offset++) {
                calendar.add(Calendar.DATE, 1);     //不包括今天
                String strDate = DateUtil.formatDate(calendar.getTime(), "yyyy-MM-dd"); //日期

                getScheduleListRequest = GetScheduleListRequest.newBuilder()
                        .setDeptCode(firstCode)
                        .setDoctorCode(doctorCode)
                        .setServiceDate(strDate)
                        .setHospitalId(hospitalId)
                        .setServiceCode(serviceCode)
                        .build();
                getScheduleListResponse = taiheServiceBlockingStub.getScheduleList(getScheduleListRequest);

                if (getScheduleListResponse.getCode() == ResultCode.SUCCEED_VALUE) {
                    scheduleList = getScheduleListResponse.getSchedulesList();
                } else {
                    scheduleList = new LinkedList<>();
                }
                lst.add(convertToScheduleMap(scheduleList, doctorList, calendar, strDate, offset, hospitalId));
            }

            map.put("list", lst);
            redisTemplate.opsForValue().set(key, JsonSerializer.toJson(map), Constant.REDIS_EXPIRE_TIME_TEN_MINUTES, TimeUnit.SECONDS);
            response.setData(map);
            return response.succeed("处理成功");
        } catch (Exception e) {
            logger.error("getScheduleList(){}", e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 排班记录转为Map
     *
     * @param scheduleList
     * @param doctorList
     * @param calendar
     * @param strDate
     * @param offset
     * @return
     */
    private Map<String, Object> convertToScheduleMap(List<Schedule> scheduleList, List<DeptScheduleDoctor> doctorList,
                                                     Calendar calendar, String strDate, int offset, int hospitalId) {
        List<Map<String, Object>> forenoonList = new LinkedList<>();
        List<Map<String, Object>> afternoonList = new LinkedList<>();
        List<Map<String, Object>> nightList = new LinkedList<>();
        List<Map<String, Object>> afterMidnightList = new LinkedList<>();   // 下半夜排班
        GetDoctorByHisCodeResponse getDoctorByHisCodeResponse;
        String avatar;

        int doctorId;
        boolean hasScheduling = scheduleList.size() > 0;    //当期日期是否有排班

        Map<String, Object> groupMap = new HashMap<>();
        groupMap.put("serviceDate", strDate);
        groupMap.put("offset", offset);
        groupMap.put("week", DateUtil.getDayOfWeekShort(calendar));

        for (Schedule s : scheduleList) {
//            if (doctorList.stream().noneMatch(p -> s.getDoctorCode().equals(p.getDoctorCode()))) {
//                continue;
//            }

            doctorId = 0;
            avatar = Constant.DOCTOR_AVATAR_URL;
            getDoctorByHisCodeResponse = getDoctorByHisCode(s.getDoctorCode(), hospitalId);

            if (getDoctorByHisCodeResponse.getResult().getCode() == ResultCode.SUCCEED) {
                if (!StringHelper.isNullOrWhiteSpace(getDoctorByHisCodeResponse.getAvatar())) {
                    avatar = getDoctorByHisCodeResponse.getAvatar();
                }

                doctorId = getDoctorByHisCodeResponse.getDoctorId();
            }
            if (doctorId <= 0) {
                continue;
            }
            // 需求改动：
            // v3.3.8 名医关闭咨询，也可以继续挂号和创建线下就诊订单
//            if (systemSrv.checkIsNetDept(s.getDeptCode())) {
//                //南方医院太和分院（互联网医院名医诊区）
//                GetConsultSettingsRequest getConsultSettingsReq = GetConsultSettingsRequest.newBuilder()
//                        .setUserId(doctorId)
//                        .build();
//                GetConsultSettingsResponse getConsultSettingsRes = doctorServiceBlockingStub.getConsultSettings(getConsultSettingsReq);
//                if (getConsultSettingsRes.getResult().getCode() != ResultCode.SUCCEED) {
//                    continue;
//                }
//                if (getConsultSettingsRes.getStatus() != 1) {
//                    //医生需要开启咨询功能
//                    continue;
//                }
//            }

            Map<String, Object> scheduleMap = new HashMap<>();
            scheduleMap.put("scheduleItemCode", s.getScheduleItemCode());       //门诊排班项记录标识
            scheduleMap.put("serviceDate", s.getServiceDate());                 //门诊排班日期(yyyy-MM-dd)
            scheduleMap.put("datePeriod", s.getDatePeriod());           //排班时段代码
            scheduleMap.put("datePeriodName", s.getDatePeriodName());   //排班时段名称
            scheduleMap.put("deptCode", s.getDeptCode());               //科室代码
            scheduleMap.put("deptName", s.getDeptName());               //科室名称
            scheduleMap.put("doctorCode", s.getDoctorCode());           //医生代码
            scheduleMap.put("doctorName", s.getDoctorName());           //医生名称
            scheduleMap.put("doctorId", doctorId);                      //医生Id
            scheduleMap.put("avatar", avatar);                          //医生图片链接
            scheduleMap.put("doctorTitle", s.getDoctorTitle());         //医生职称
            scheduleMap.put("doctorSpec", s.getDoctorSpec());           //医生专长
            scheduleMap.put("fee", s.getFee());                         //预约挂号总费用
            scheduleMap.put("regFee", s.getRegFee());                   //挂号费
            scheduleMap.put("checkupFee", s.getCheckupFee());           //诊查费
            scheduleMap.put("serviceFee", s.getServiceFee());           //服务费
            scheduleMap.put("otherFee", s.getOtherFee());               //其它费
            scheduleMap.put("admitAddress", s.getAdmitAddress());       //就诊地址
            scheduleMap.put("scheduleStatus", s.getScheduleStatus());       //出诊状态（1-可预约 0-已满 2-停诊 3-其它(不可预约)）
            scheduleMap.put("availableTotalNum", s.getAvailableTotalNum()); //该时段可预约的总号源数
            scheduleMap.put("availableLeftNum", s.getAvailableLeftNum());   //该时段剩余号源数
            scheduleMap.put("doctorSessTypeCode", s.getDoctorSessTypeCode());// 出诊级别code
            scheduleMap.put("doctorSessTypeName", s.getDoctorSessTypeName());// 出诊级别name

            String statusName = "";

            switch (s.getScheduleStatus()) {
                case 1:
                    statusName = "可预约";
                    break;
                case 0:
                    statusName = "已满";
                    break;
                case 2:
                    statusName = "停诊";
                    break;
                default:
                    statusName = "停诊";
                    break;
            }

            scheduleMap.put("scheduleStatusName", statusName);

            switch (s.getDatePeriod()) {
                case 2:
                    forenoonList.add(scheduleMap);
                    break;
                case 3:
                    afternoonList.add(scheduleMap);
                    break;
                case 4:
                    nightList.add(scheduleMap);
                case 5:
                    afterMidnightList.add(scheduleMap);
                    break;
            }
        }

        groupMap.put("hasScheduling", hasScheduling ? 1 : 0);   //当期日期是否有排班
        groupMap.put("forenoonSchedules", forenoonList);        //上午排班记录
        groupMap.put("afternoonSchedules", afternoonList);      //下午排班记录
        groupMap.put("nightSchedules", nightList);              //晚上排班记录
        groupMap.put("afterMidnightSchedules", afterMidnightList);              //晚上排班记录

        return groupMap;
    }

    /**
     * 得到今日排班记录
     *
     * @param hospitalId
     * @param deptCode
     * @param doctorCode
     * @return
     */
    @UserLogin(need = false)
    @RequestMapping({"/todaySchedule"})
    public @ResponseBody
    BaseResponse getTodayScheduleList(@RequestParam(name = "hospitalId") int hospitalId,
                                      @RequestParam(name = "deptCode", defaultValue = "") String deptCode,
                                      @RequestParam(name = "doctorCode", required = false, defaultValue = "") String doctorCode,
                                      @RequestParam(name = "serviceCode", defaultValue = "", required = false) String serviceCode) {
        BaseResponse response = new BaseResponse();

        try {
            if (Checker.getIntegerValue(hospitalId) <= 0) {
                hospitalId = BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
            }
            List<Dept> deptList = systemSrv.getDeptListByHospitalId(hospitalId);

            if (deptList == null || deptList.size() == 0) {
                return response.failed(BaseResponse.APP_ERROR, "invalid request");
            }

            List<Dept> tmpDeptList = deptList.stream().filter(p -> p.getDeptCode().equals(deptCode)).collect(Collectors.toList());

            if (tmpDeptList == null || tmpDeptList.size() == 0) {
                return response.failed(BaseResponse.PARAMETER_ERROR, "deptCode not exist");
            }

            Dept secDept = tmpDeptList.get(0);
            tmpDeptList = deptList.stream().filter(p -> p.getDeptId() == secDept.getParentId()).collect(Collectors.toList());

            if (tmpDeptList == null || tmpDeptList.size() == 0) {
                return response.failed(BaseResponse.PARAMETER_ERROR, "invalid deptCode");
            }

            Map<String, Object> map = new HashMap<>();
            map.put("hospitalId", hospitalId);
            map.put("hospitalName", BizUtil.getHospitalNameByIdSimply(hospitalId));
            map.put("deptCode", deptCode);
            map.put("deptName", secDept.getDeptName());

            List<Map<String, Object>> lst = new LinkedList<>();
            Calendar calendar = Calendar.getInstance();

            List<DeptScheduleDoctor> doctorList = doctorSrv.getDeptScheduleDoctorListFromCache();
            doctorList = doctorList.stream().filter(p -> p.getDeptCode().equals(deptCode)).collect(Collectors.toList());

            GetScheduleListRequest getScheduleListRequest;
            GetScheduleListResponse getScheduleListResponse;
            List<Schedule> scheduleList;

            String strDate = DateUtil.formatDate(calendar.getTime(), "yyyy-MM-dd"); //日期

            getScheduleListRequest = GetScheduleListRequest.newBuilder()
                    .setDeptCode(deptCode)
                    .setDoctorCode(doctorCode)
                    .setServiceDate(strDate)
                    .setHospitalId(hospitalId)
                    .setServiceCode(serviceCode)
                    .build();
            getScheduleListResponse = taiheServiceBlockingStub.getScheduleList(getScheduleListRequest);

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

            lst.add(convertToScheduleMap(scheduleList, doctorList, calendar, strDate, 0, hospitalId));

            map.put("list", lst);
            response.setData(map);
            return response.succeed("处理成功");
        } catch (Exception e) {
            logger.error("getScheduleList(){}", e.getMessage());
            return response.failed(BaseResponse.APP_EXCEPTION, Constant.ERROR_PROMPT);
        }
    }

    /**
     * 得到医生分时排班信息
     *
     * @param hospitalId
     * @param deptCode    一级科室编码
     * @param doctorCode
     * @param serviceDate
     * @param period
     * @return
     */
    @UserLogin(need = false)
    @RequestMapping({"/doctorSchedule"})
    public @ResponseBody
    BaseResponse getDoctorScheduleList(@RequestParam(name = "hospitalId") int hospitalId,
                                       @RequestParam(name = "deptCode") String deptCode,
                                       @RequestParam(name = "doctorCode") String doctorCode,
                                       @RequestParam(name = "serviceDate", required = false) String serviceDate,
                                       @RequestParam(name = "period", required = false) Integer period) {
        BaseResponse response = new BaseResponse();

        if (StringHelper.isNullOrWhiteSpace(deptCode)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "科室不存在");
        }

        if (StringHelper.isNullOrWhiteSpace(doctorCode)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "医生不存在");
        }

        if (hospitalId <= 0) {
            hospitalId = BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
        }

        List<Map<String, Object>> dataList = new LinkedList<>();

        if (!StringHelper.isNullOrWhiteSpace(serviceDate)) {
            Date date = DateUtil.parseDate(serviceDate, "yyyy-MM-dd");
            if (date == null) {
                return response.failed(BaseResponse.PARAMETER_ERROR, "invalid serviceDate");
            }
            //查询医生某一天的排班分时信息
            if (period == null) {
                return response.failed(BaseResponse.PARAMETER_ERROR, "请选择时段");
            }

            if (DatePeriodEnum.valueOf(period) == null) {
                return response.failed(BaseResponse.PARAMETER_ERROR, "时段不存在");
            }

            String strDate = DateUtil.formatDate(date, "yyyy-MM-dd");
            Map<String, Object> map = getScheduleTimeInfoResponse(deptCode, doctorCode, strDate, period, hospitalId);

            if (map != null) {
                dataList.add(map);
            }
        } else {
            //取医生8天排班的分时信息
            int[] periods = {DatePeriodEnum.MORNING.getValue(), DatePeriodEnum.AFTERNOON.getValue()};
            Calendar calendar = Calendar.getInstance();

            for (int offset = 0; offset < 8; offset++) {
                calendar.add(Calendar.DATE, 1);
                String strDate = DateUtil.formatDate(calendar.getTime(), "yyyy-MM-dd");

                for (int p : periods) {
                    Map<String, Object> map = getScheduleTimeInfoResponse(deptCode, doctorCode, strDate, p, hospitalId);

                    if (map != null) {
                        dataList.add(map);
                    }
                }
            }
        }

        String deptName = "";
        String doctorName = "";
        String avatar = "";
        String doctorTitle = "";
        String doctorSpec = "";
        double fee = 0;     //单位：元
        int regFee = 0;     //单位：分
        int treatFee = 0;   //单位：分
        int amount = 0;     //单位：分
        String feeStr = "";
        String regFeeStr = "";
        String treatFeeStr = "";
        int doctorId = 0;
        String doctorSessTypeCode = "";// 出诊级别code
        String doctorSessTypeName = "";// 出诊级别name

        if (dataList.size() > 0) {
            Map<String, Object> map = dataList.get(0);
            String strDate = map.get("serviceDate").toString();
            GetScheduleListRequest getScheduleListRequest = GetScheduleListRequest.newBuilder()
                    .setDeptCode(deptCode)
                    .setDoctorCode(doctorCode)
                    .setServiceDate(strDate)
                    .setHospitalId(hospitalId)
                    .build();
            GetScheduleListResponse getScheduleListResponse = taiheServiceBlockingStub.getScheduleList(getScheduleListRequest);

            if (getScheduleListResponse.getCode() == ResultCode.SUCCEED_VALUE) {
                List<Schedule> scheduleList = getScheduleListResponse.getSchedulesList();
                if (scheduleList.size() > 0) {
                    Schedule schedule = scheduleList.stream().filter(s -> s.getDatePeriod() == Checker.getIntegerValue(period)).findFirst().orElse(null);
                    if (schedule != null) {
                        deptName = schedule.getDeptName();
                        doctorName = schedule.getDoctorName();
                        avatar = schedule.getAvatar();
                        doctorTitle = schedule.getDoctorTitle();
                        doctorSpec = schedule.getDoctorSpec();
                        amount = schedule.getFee();
                        fee = schedule.getFee() / 100d;
                        regFee = schedule.getRegFee();
                        treatFee = schedule.getCheckupFee();

                        doctorSessTypeCode = schedule.getDoctorSessTypeCode();// 出诊级别code
                        doctorSessTypeName = schedule.getDoctorSessTypeName();// 出诊级别name
                    } else {
                        return response.failedWithAppError("当前时间段没有匹配的排班数据");
                    }
                }
            }
        }

        GetDoctorByHisCodeResponse getDoctorByHisCodeResponse = getDoctorByHisCode(doctorCode, hospitalId);
        if (getDoctorByHisCodeResponse.getResult().getCode() == ResultCode.SUCCEED) {
            if (!StringHelper.isNullOrWhiteSpace(getDoctorByHisCodeResponse.getAvatar())) {
                avatar = getDoctorByHisCodeResponse.getAvatar();
            } else {
                avatar = Constant.DOCTOR_AVATAR_URL;
            }

            doctorId = getDoctorByHisCodeResponse.getDoctorId();
        }

        if (systemSrv.checkIsNetDept(deptCode, hospitalId)) {
            //南方医院太和分院（互联网医院名医诊区）
            // v3.2.0 线下就诊费用单独设置
            // v3.3.8 即使咨询关闭，仍然可以线下问诊，问诊费用要正常显示
            DoctorRequest doctorRequest = DoctorRequest.newBuilder()
                    .setUserid(doctorId)
                    .build();
            DoctorInfoResponse doctorInfoResponse = doctorServiceBlockingStub.getDoctorInfo(doctorRequest);
            if (doctorInfoResponse.getResult().getCode() != ResultCode.SUCCEED) {
                return response.failedWithAppError(String.format("无法获取医生信息: %s", doctorInfoResponse.getResult().getInfo()));
            }
            // 线下就诊费用跟问诊费分开，线下就诊费用读取 offline_fee 字段
            int consultFee = Checker.getIntegerValue(doctorInfoResponse.getInfo().getOfflineFee());
            amount = consultFee;
            fee = consultFee / 100d;
            regFee = 0;
            treatFee = 0;
        }

//        amount = 1;
//        fee = 0.01;
//        regFee = 0;
//        treatFee = 1;//测试

        feeStr = String.format("¥%.2f", fee);
        regFeeStr = String.format("¥%.2f", regFee / 100d);
        treatFeeStr = String.format("¥%.2f", treatFee / 100d);

        Map<String, Object> data = new HashMap<>();
        data.put("list", dataList);
        data.put("hospitalName", BizUtil.getHospitalNameByIdSimply(hospitalId));
        data.put("deptCode", deptCode);
        data.put("deptName", deptName);
        data.put("doctorCode", doctorCode);
        data.put("doctorName", doctorName);
        data.put("avatar", avatar);
        data.put("doctorTitle", doctorTitle);
        data.put("doctorSpec", doctorSpec);
        data.put("amount", amount);
        data.put("fee", fee);
        data.put("regFee", regFee);
        data.put("treatFee", treatFee);
        data.put("feeStr", feeStr);
        data.put("regFeeStr", regFeeStr);
        data.put("treatFeeStr", treatFeeStr);
        data.put("doctorId", doctorId);        //医生ID
        data.put("doctorSessTypeCode", doctorSessTypeCode);
        data.put("doctorSessTypeName", doctorSessTypeName);

        // todo：20210527 为了提高预约挂号速度，弄一个列表用作缓冲
//        String userKey = String.format(ConstantDef.YWT_COVID19_LIST_KEY, userService.getCurrentOpenId());
//        if (!checkExistYwtCovid19ListKey(userKey)) {
//            return response.failedWithParameterError("请稍后再查询，谢谢！");
//        }

        return response.succeed(data);
    }

    /**
     * 是否可以获取新冠疫苗号(如果该用户已有key，则表示可以获取，后面再覆盖新的)
     *
     * @return false: 不能， true: 可以
     */
    private boolean checkExistYwtCovid19ListKey(String userKey) {
        if (Checker.isNone(userKey)) {
            return true;
        }
        String key = String.format(Constant.YWT_COVID19_LIST_KEY, "*");
        // 缓存类型：0-GuavaCache, 1-Redis
        int cacheType = 1;
        // 键匹配模式：0-match, 1-pattern
        int keyType = 1;
        List<String> keys = devController.getKeys(key, keyType, cacheType);
        if (Checker.isNone(keys)) {
            redisTemplate.opsForValue().set(userKey,  "1", Constant.YWT_COVID19_KEY_EXPIRE_TIME, TimeUnit.SECONDS);
            return true;
        }
        String value = keys.stream().filter(p -> p.equals(userKey)).findFirst().orElse(null);
        // 如果不包含，而且队列的数量尚未满，那么则可以插入
        if (Checker.isNone(value) && keys.size() <= parameterConfigurer.getYwtCovid19ListCount()) {
            redisTemplate.opsForValue().set(userKey, "1", Constant.YWT_COVID19_KEY_EXPIRE_TIME, TimeUnit.SECONDS);
            return true;
        }
        return false;
    }

    /**
     * 得到分时排班信息
     *
     * @param deptCode
     * @param doctorCode
     * @param serviceDate
     * @param period
     * @return
     */
    private Map<String, Object> getScheduleTimeInfoResponse(String deptCode, String doctorCode, String serviceDate,
                                                            int period, int hospitalId) {
        List<Map<String, Object>> lst = new LinkedList<>();

        GetScheduleTimeInfoRequest getScheduleTimeInfoRequest = GetScheduleTimeInfoRequest.newBuilder()
                .setDeptCode(deptCode)
                .setDoctorCode(doctorCode)
                .setServiceDate(serviceDate)
                .setDatePeriod(period)
                .setHospitalId(hospitalId)
                .build();
        GetScheduleTimeInfoResponse getScheduleTimeInfoResponse = taiheServiceBlockingStub.getScheduleTimeInfo(getScheduleTimeInfoRequest);

        if (getScheduleTimeInfoResponse.getCode() == ResultCode.SUCCEED_VALUE) {
            List<ScheduleTimeInfo> scheduleTimeInfoList = getScheduleTimeInfoResponse.getScheduleTimeInfosList();
            Calendar calendar = Calendar.getInstance();
            String strDate = DateUtil.formatDate(calendar.getTime(), "yyyy-MM-dd");
            String strTime = DateUtil.formatDate(calendar.getTime(), "HHmm");
            int time = Integer.parseInt(strTime);

            String strEndTime;
            String flag;
            int tmp;
            int left;

            for (ScheduleTimeInfo scheduleTimeInfo : scheduleTimeInfoList) {
                flag = scheduleTimeInfo.getAvailableFlag();
                left = scheduleTimeInfo.getAvailableLeftNum();

                if (strDate.equals(serviceDate) && !StringHelper.isNullOrWhiteSpace(scheduleTimeInfo.getEndTime())) {
                    strEndTime = scheduleTimeInfo.getEndTime();
                    tmp = Integer.parseInt(strEndTime.replace(":", ""));

                    if (tmp < time) {
                        left = 0;
                        flag = "N";
                    }
                }

                Map<String, Object> map = new HashMap<>();
                map.put("scheduleItemCode", scheduleTimeInfo.getScheduleItemCode());
                map.put("startTime", scheduleTimeInfo.getStartTime());
                map.put("endTime", scheduleTimeInfo.getEndTime());
                map.put("availableTotalNum", scheduleTimeInfo.getAvailableTotalNum());
                map.put("availableLeftNum", left);
                map.put("availableFlag", flag);
                map.put("availableNumStr", scheduleTimeInfo.getAvailableNumStr());

                lst.add(map);
            }
        }

        if (lst.size() > 0) {
            Map<String, Object> dateMap = new HashMap<>();
            dateMap.put("serviceDate", serviceDate);
            dateMap.put("period", period);
            dateMap.put("datePeriod", DatePeriodEnum.valueOf(period).getDisplayName());
            dateMap.put("schedule", lst);

            return dateMap;
        }

        return null;
    }

    /**
     * 创建预约挂号订单
     *
     * @param hospitalId       医院Id
     * @param deptCode         科室Code
     * @param deptName         科室名称
     * @param doctorCode       医生Code
     * @param doctorName       医生名称
     * @param registeredFee    挂号费
     * @param medicalFee       诊查费
     * @param registeredDate   预约日期
     * @param period           预约时间段
     * @param startTime        预约开始时间：HH:MI
     * @param endTime          预约结束时间：HH:MI
     * @param medicalCardId    就诊人Id
     * @param scheduleItemCode 门诊排班项记录标识
     * @return
     */
    @Deprecated
    @RequestMapping({"/createRegisteredOrder"})
    public @ResponseBody
    BaseResponse createRegisteredOrder(
            @RequestParam(name = "hospitalId") int hospitalId,
            @RequestParam(name = "deptCode") String deptCode,
            @RequestParam(name = "deptName") String deptName,
            @RequestParam(name = "doctorCode") String doctorCode,
            @RequestParam(name = "doctorName") String doctorName,
            @RequestParam(name = "registeredFee") double registeredFee,
            @RequestParam(name = "medicalFee") double medicalFee,
            @RequestParam(name = "registeredDate") String registeredDate,
            @RequestParam(name = "period") int period,
            @RequestParam(name = "startTime") String startTime,
            @RequestParam(name = "endTime") String endTime,
            @RequestParam(name = "medicalCardId") int medicalCardId,
            @RequestParam(name = "scheduleItemCode") String scheduleItemCode) {
        BaseResponse response = new BaseResponse();

        if (hospitalId < 1) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "医院不存在");
        }
        if (StringHelper.isNullOrWhiteSpace(deptCode) || StringHelper.isNullOrWhiteSpace(deptName)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "科室不存在");
        }
        if (StringHelper.isNullOrWhiteSpace(doctorCode) || StringHelper.isNullOrWhiteSpace(doctorName)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "医生不存在");
        }
        if (StringHelper.isNullOrWhiteSpace(registeredDate)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "请选择挂号日期");
        }

        Date date = DateUtil.parseDate(registeredDate, "yyyy-MM-dd");
        if (date == null) {
            return response.failedWithParameterError("预约日期格式不正确");
        }

        DatePeriodEnum datePeriodEnum = DatePeriodEnum.valueOf(period);
        if (datePeriodEnum == null) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "预约时段不存在");
        }

        if (StringHelper.isNullOrWhiteSpace(startTime)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "预约开始时间不存在");
        }

        if (StringHelper.isNullOrWhiteSpace(endTime)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "预约结束时间不存在");
        }

        if (medicalCardId < 1) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "请选择就诊人");
        }

        if (StringHelper.isNullOrWhiteSpace(scheduleItemCode)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "门诊排班项记录标识不能为空");
        }

        try {
            int userId = userService.getCurrentUserIdWrapped();
            int total = (int) ((registeredFee + medicalFee) * 100);
            int source;
            int terminal = WebAppContext.current().getTerminal();
            switch (TerminalEnum.valueOf(terminal)) {
                case TAI_HE_OFFICIAL:
                    source = TerminalEnum.TAI_HE_OFFICIAL.getValue();
                    break;
                case NFYYBYFY_WXAPP:
                    source = TerminalEnum.NFYYBYFY_WXAPP.getValue();
                    break;
                default:
                    source = TerminalEnum.TaiheWxOfficial.getValue();
                    break;
            }
            int paymentChannel = total > 0 ? PaymentChannelEnum.WeChat.getValue() : PaymentChannelEnum.FREE.getValue();

            CreateTaiheRegisteredOrderRequest req = CreateTaiheRegisteredOrderRequest.newBuilder()
                    .setHospitalId(hospitalId)
                    .setDeptCode(deptCode)
                    .setDeptName(deptName)
                    .setDoctorCode(doctorCode)
                    .setDoctorName(doctorName)
                    .setTotal(total)
                    .setRegisteredFee((int) (registeredFee * 100))
                    .setMedicalFee((int) (medicalFee * 100))
                    .setRegisteredDate(date.getTime())
                    .setStartTime(startTime)
                    .setEndTime(endTime)
                    .setUserId(userId)
                    .setMedicalCardId(medicalCardId)
                    .setScheduleItemCode(scheduleItemCode)
                    .setPaymentChannel(paymentChannel)
                    .setSource(source)
                    .build();
            CreateTaiheRegisteredOrderResponse res = orderServiceBlockingStub.createTaiheRegisteredOrder(req);
            Result result = res.getResult();

            if (result.getCode() != ResultCode.SUCCEED) {
                return response.failedWithAppError(result.getInfo());   //预约失败
            }
            if (!systemSrv.checkIsNetDept(deptCode, hospitalId)) {
                //非互联网医院名医诊区挂号
                Map<String, Object> map = new HashMap<>();
                map.put("orderId", res.getOrderId());
                map.put("orderType", res.getOrderType());
                map.put("status", res.getStatus());
                return response.succeed(map);
            }

            //如果是南方医院太和分院（互联网医院名医诊区），则创建线下就诊订单
            int doctorId = 0;
            String name = res.getName();
            String idNo = res.getIdNo();
            String mobile = res.getMobile();

            GetDoctorByHisCodeResponse getDoctorByHisCodeResponse = getDoctorByHisCode(doctorCode, hospitalId);
            if (getDoctorByHisCodeResponse.getResult().getCode() == ResultCode.SUCCEED) {
                doctorId = getDoctorByHisCodeResponse.getDoctorId();
            }

            //创建线下就诊订单
            CreateOfflineConsultationRequest createOfflineConsultationReq = CreateOfflineConsultationRequest.newBuilder()
                    .setHisClinicCode(0)
                    .setDoctorId(doctorId)
                    .setName(name)
                    .setIdNo(idNo)
                    .setMobile(mobile)
                    .setUserId(userId)
                    .setSource(OfflineConsultationSourceEnum.TAIHE_WX_OFFICIAL.getValue())
                    .setRegisteredDate(date.getTime())
                    .build();
            CreateOfflineConsultationResponse createOfflineConsultationRes =
                    offlineConsultingServiceBlockingStub.createOfflineConsultation(createOfflineConsultationReq);
            if (createOfflineConsultationRes.getCode() != ResultCode.SUCCEED_VALUE) {
                return response.failedWithAppError(createOfflineConsultationRes.getMsg());
            }

            Map<String, Object> data = new HashMap<>();
            data.put("orderId", createOfflineConsultationRes.getOrderId());
            data.put("orderNo", createOfflineConsultationRes.getOrderNo());
            data.put("orderType", createOfflineConsultationRes.getOrderType());
            return response.succeed(data);
        } catch (Exception e) {
            logger.error("createTaiheRegisteredOrder(): {}", e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 太和取号接口
     * 接入 taihe-rpc 服务，2019/5/23 4:00 PM
     *
     * @param orderId 订单ID
     * @return
     */
    @RequestMapping({"/take"})
    public @ResponseBody
    BaseResponse takeOrder(@RequestParam(name = "orderId") int orderId,
                           @RequestParam(name = "hospitalId", defaultValue = "0", required = false) int hospitalId) {
        BaseResponse response = new BaseResponse();
        int userId = userService.getCurrentUserIdWrapped();

        try {
            if (hospitalId <= 0) {
                hospitalId = BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
            }
            com.ywt.gapi.taihe.register.TakeRequest req = com.ywt.gapi.taihe.register.TakeRequest.newBuilder()
                    .setOrderId(orderId)
                    .setUserId(userId)
                    .setHospitalId(hospitalId)
                    .build();
            com.ywt.gapi.taihe.register.TakeResponse res = taiheRegisterServiceBlockingStub.take(req);
            if (res.getCode() == ResultCode.SUCCEED_VALUE) {
                Map<String, Object> map = new HashMap<>();
                map.put("registrationId", res.getHisClinicCode());
                return response.succeed("已成功取号，请到分诊台报到！", map);
            }
            return response.failedWithAppError(res.getMsg());
//            TakeTaiheRegisteredOrderRequest req = TakeTaiheRegisteredOrderRequest.newBuilder()
//                    .setOrderId(orderId)
//                    .setUserId(userId)
//                    .build();
//            TakeTaiheRegisteredOrderResponse res = orderServiceBlockingStub.takeTaiheRegisteredOrder(req);
//            Result result = res.getResult();

//            if (result.getCode() == ResultCode.SUCCEED) {
//                Map<String, Object> map = new HashMap<>();
//                map.put("registrationId", res.getRegistrationId());
//                return response.succeed("已成功取号，请到分诊台报到！", map);
//            }
//            return response.failedWithAppError(result.getInfo());
        } catch (Exception e) {
            logger.error("take(orderId-{}, userId-{}): {}", orderId, userId, e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 取消预约挂号订单
     *
     * @param orderId
     * @return
     */
    @RequestMapping({"/cancel"})
    public @ResponseBody
    BaseResponse cancelOrder(@RequestParam(name = "orderId") int orderId) {
        BaseResponse response = new BaseResponse();
        if (orderId < 1) {
            return response.failedWithParameterError("订单不存在");
        }

        try {
//            CancelTaiheRegisteredOrderRequest cancelTaiheRegisteredOrderRequest = CancelTaiheRegisteredOrderRequest.newBuilder()
//                    .setOrderId(orderId)
//                    .setUserId(userService.getCurrentUserId())
//                    .build();
//            ResultInt result = orderServiceBlockingStub.cancelTaiheRegisteredOrder(cancelTaiheRegisteredOrderRequest);
//            if (result.getCode() == ResultCode.SUCCEED) {
//                Map<String, Object> map = new HashMap<>();
//                map.put("status", result.getValue());
//                return response.succeed(result.getInfo(), map);
//            }
//            return response.failedWithAppError(result.getInfo());
            CancelRegisteredRequest req = CancelRegisteredRequest.newBuilder()
                    .setOrderId(orderId)
                    .setUserId(userService.getCurrentUserIdWrapped())
                    .build();
            CancelRegisteredResponse res = taiheRegisterServiceBlockingStub.cancelRegistered(req);
            if (res.getCode() == ResultCode.SUCCEED_VALUE) {
                Map<String, Object> data = new HashMap<>();
                data.put("status", res.getStatus());
                return response.succeed(data);
            }
            return response.failedWithAppError(res.getMsg());
        } catch (Exception e) {
            logger.error("cancelOrder(): {}", e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 获取就诊当天排队候诊订单列表
     * 接入 taihe-rpc 服务，2019/5/23 4:20 PM
     *
     * @return
     */
    @Deprecated
    @RequestMapping({"/getQueueOrderList"})
    public @ResponseBody
    BaseResponse GetQueueOrderList(@RequestParam(name = "hospitalId", defaultValue = "0", required = false) int hospitalId) {
        BaseResponse response = new BaseResponse();
        Map<String, Object> data = new LinkedHashMap<>();
        List<Map<String, Object>> list = new LinkedList<>();

        try {
            int userId = userService.getCurrentUserIdWrapped();
            if (hospitalId <= 0) {
                hospitalId = BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
            }
            com.ywt.gapi.taihe.register.GetQueueListRequest req = com.ywt.gapi.taihe.register.GetQueueListRequest.newBuilder()
                    .setUserId(userId)
                    .setHospitalId(hospitalId)
                    .build();
            com.ywt.gapi.taihe.register.GetQueueListResponse res = taiheRegisterServiceBlockingStub.getQueueList(req);

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

            List<RegisteredOrder> queueList = res.getOrderList();

//            GetQueueOrderListRequest req = GetQueueOrderListRequest.newBuilder()
//                    .setUserId(userId)
//                    .build();
//            GetQueueOrderListResponse res = orderServiceBlockingStub.getQueueOrderList(req);
//            Result result = res.getResult();
//            if (result.getCode() == ResultCode.SUCCEED) {
//                List<QuneueOrder> queueOrderList = res.getQueueOrderList();
            LocalDate now = LocalDate.now();

//                for (QuneueOrder order : queueOrderList) {
            for (com.ywt.gapi.taihe.register.RegisteredOrder order : queueList) {
                Map<String, Object> reportMap = new LinkedHashMap<>();
                int cancel = 0; //是否显示退号按钮，1-是，0-否
                LocalDate regDate = DateUtil.convertToLocalDate(new Date(order.getRegisteredDate()));//预约日期
                if (now.isBefore(regDate)) {
                    cancel = 1;
                }

                reportMap.put("cancel", cancel);
                reportMap.put("regDate", order.getRegisteredDate() != -1 ? DateUtil.convertTimestampToDateString(order.getRegisteredDate(), "yyyy.M.d") : "");
                reportMap.put("paymentDate", order.getPaymentDate() != -1 ? DateUtil.convertTimestampToDateString(order.getRegisteredDate(), "yyyy.M.d") : "");
                reportMap.put("startTime", order.getStartTime());       //开始时间
                reportMap.put("endTime", order.getEndTime());           //截止时间
                reportMap.put("patientName", order.getPatientName());   //患者姓名
                reportMap.put("deptName", order.getDeptName());         //预约科室
                reportMap.put("address", order.getAddress());           //就诊地点
                reportMap.put("doctorName", order.getDoctorName());     //预约医生
                reportMap.put("paymentStatus", order.getPaymentStatus());     //支付状态
                reportMap.put("paymentStatusName", order.getPaymentStatus() == PaymentStatusEnum.Success.getValue() ? "已缴费" : "未缴费");

                String statusName = order.getStatusName();
                int status = order.getStatus();

                if (order.getStatus() == 1) {
                    //已预约
                    statusName = "未取号";

                    if (DateUtil.convertTimestampToDateString(order.getRegisteredDate(), "yyyy-MM-dd").equals(
                            DateUtil.formatDate(new Date(), "yyyy-MM-dd"))) {

                    } else {
                        status = 0;
                    }
                }

                reportMap.put("statusName", statusName);     //取号状态（文字）
                reportMap.put("status", status);             //取号状态（数字）
                reportMap.put("orderId", order.getOrderId());           //预约挂号订单ID
                reportMap.put("registrationId", order.getHisClinicCode());           //就诊流水号
                reportMap.put("hisSeqCode", order.getHisSeqCode());
                list.add(reportMap);
            }
            data.put("list", list);
            return response.succeed("处理成功", data);
//            }
//            data.put("list", list);
//            return response.succeed("处理成功", data);
        } catch (Exception e) {
            logger.error("GetQueueOrderList(): {}", e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 获取排队信息
     *
     * @param registrationId 就诊流水号
     * @return
     */
    @RequestMapping({"/getQueueInfo"})
    public @ResponseBody
    BaseResponse getQueueInfo(@RequestParam(name = "registrationId") String registrationId,
                              @RequestParam(name = "hospitalId", defaultValue = "0", required = false) int hospitalId) {
        BaseResponse response = new BaseResponse();

        try {
            if (hospitalId <= 0) {
                hospitalId = BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
            }
            GetQueueInfoRequest getQueueInfoRequest = GetQueueInfoRequest.newBuilder()
                    .setRegistrationId(registrationId)
                    .setHospitalId(hospitalId)
                    .build();
            GetQueueInfoResponse getQueueInfoResponse = taiheServiceBlockingStub.getQueueInfo(getQueueInfoRequest);

            if (getQueueInfoResponse.getCode() == ResultCode.SUCCEED_VALUE) {
                QueueInfo data = getQueueInfoResponse.getQueueInfo();
                Map<String, Object> itemMap = new LinkedHashMap<>();
                itemMap.put("doctorName", data.getDoctorName());    //就诊医生
                itemMap.put("deptName", data.getDeptName());        //就诊科室
                itemMap.put("deptCode", data.getDeptCode());  //就诊科室代码
                itemMap.put("patientName", data.getPatientName());  //病人姓名
                itemMap.put("waitingNumber", data.getWaitingNumber());  //排队号
                itemMap.put("hospitalName", BizUtil.getHospitalNameByIdSimply(hospitalId));  //就诊医院

                return response.succeed("处理成功", itemMap);
            }

            return response.failed(BaseResponse.APP_ERROR, getQueueInfoResponse.getMsg());
        } catch (Exception e) {
            logger.error("getQueueInfo(): {}", e.getMessage());
            return response.error();
        }
    }


    /**
     * 获取门诊病历列表
     *
     * @param medicalCardId 就诊卡Id
     * @param pageIndex     页码
     * @param pageSize      页大小
     * @return
     */
    @RequestMapping({"/medicalrecordlist"})
    public @ResponseBody
    BaseResponse getMedicalRecordsList(@RequestParam(name = "medicalCardId") int medicalCardId,
                                       @RequestParam(name = "pageIndex") int pageIndex,
                                       @RequestParam(name = "pageSize") int pageSize) {
        BaseResponse response = new BaseResponse();

        if (pageIndex < 1) {
            pageIndex = 1;
        }

        if (pageSize < 1) {
            pageSize = 20;
        }

        try {
            int userId = userService.getCurrentUserIdWrapped();
            int hospitalId = BizUtil.getHospitalIdByTerminalId(userSrv.getCurrentTerminal());
            medicalCardService.verifyMedicalCard(userId, hospitalId, medicalCardId);
            GetOutpatientRecordListRequest req = GetOutpatientRecordListRequest.newBuilder()
                    .setMedicalCardId(medicalCardId)
                    .setUserId(userId)
                    .setPageIndex(pageIndex)
                    .setPageSize(pageSize)
                    .build();
            GetOutpatientRecordListResponse res = medicalRecordServiceBlockingStub.getOutpatientRecordList(req);
            Result result = res.getResult();

            if (result.getCode() == ResultCode.SUCCEED) {
                List<Map<String, Object>> lst = new LinkedList<>();

                for (MedicalRecord record : res.getMedicalRecordList()) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("admTime", record.getAdmTime());
                    map.put("clinicCode", record.getClinicCode());
                    map.put("hospitalName", record.getHospitalName());
                    map.put("doctorName", record.getDoctorName());
                    map.put("doctorTitle", record.getDoctorTitle());
                    map.put("recordId", record.getRecordId());
                    lst.add(map);
                }

                Map<String, Object> map = new HashMap<>();
                map.put("count", res.getCount());
                map.put("totalPages", res.getTotalPages());
                map.put("list", lst);

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

            return response.failed(BaseResponse.APP_ERROR, result.getInfo());
        } catch (Exception e) {
            logger.error("getMedicalRecordsList(): {}", e.getMessage(), e);
            return response.error(e.getMessage());
        }
    }

    /**
     * 获取门诊病历详情
     *
     * @param recordId
     * @return
     */
    @RequestMapping({"/getMedicalRecordDetail"})
    public @ResponseBody
    BaseResponse getMedicalRecordDetail(@RequestParam(name = "recordId") int recordId) {
        BaseResponse response = new BaseResponse();

        if (recordId < 1) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "invalid recordId");
        }

        try {
            GetMedicalRecordByIdRequest req = GetMedicalRecordByIdRequest.newBuilder()
                    .setRecordId(recordId)
                    .build();
            GetMedicalRecordByIdResponse res = medicalRecordServiceBlockingStub.getMedicalRecordById(req);
            Result result = res.getResult();

            if (result.getCode() == ResultCode.SUCCEED) {
                com.ywt.gapi.medicalrecord.MedicalRecord detail = res.getMedicalRecord();

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

                if (!StringHelper.isNullOrEmpty(detail.getAdmTime())) {
                    String pattern;
                    int len = detail.getAdmTime().length();

                    switch (len) {
                        case 19:
                            pattern = "yyyy-MM-dd HH:mm:ss";
                            break;
                        case 10:
                            pattern = "yyyy-MM-dd";
                            break;
                        default:
                            pattern = "yyyy-M-d";
                            break;
                    }

                    Date date = DateUtil.parseDate(detail.getAdmTime(), pattern);
                    strAdmTime = DateUtil.formatDate(date, "yyyy年MM月dd日");
                } else {
                    strAdmTime = DateUtil.convertTimestampToDateString(detail.getCreateTime(), "yyyy年MM月dd日");
                }

                data.put("admTime", detail.getAdmTime());
                data.put("strAdmTime", strAdmTime);
                data.put("hospitalName", detail.getHospitalName());
                data.put("doctorName", detail.getDoctorName());
                data.put("patientName", detail.getPatientName());
                data.put("selfReport", detail.getSelfReport());
                data.put("phyExam", detail.getPhyExam());
                data.put("diagnose", detail.getDiagnose());
                data.put("suggestion", detail.getSuggestion());
                data.put("advice", detail.getAdvice());           //医嘱
                data.put("hospitalId", detail.getHospitalId());

                List<Map<String, Object>> laboratoryReportList = new LinkedList<>();
                List<Map<String, Object>> inspectionReportList = new LinkedList<>();

                if (detail.getLaboratoryReportList() != null) {
                    for (com.ywt.gapi.medicalrecord.LaboratoryReport report : detail.getLaboratoryReportList()) {
                        Map<String, Object> item = new HashMap<>();
                        item.put("id", report.getId());
                        item.put("title", report.getInspectionName());
                        item.put("inspectionId", report.getInspectionId());
                        item.put("reportDate", DateUtil.convertTimestampToDateString(report.getInspectionDate(), "yyyy年MM月dd日"));

                        laboratoryReportList.add(item);
                    }
                }

                if (detail.getInspectionReportList() != null) {
                    for (com.ywt.gapi.medicalrecord.InspectionReport report : detail.getInspectionReportList()) {
                        Map<String, Object> map = new HashMap<>();
                        map.put("id", report.getId());
                        map.put("title", report.getReportTitle());
                        map.put("reportId", report.getReportId());
                        map.put("reportDate", DateUtil.convertTimestampToDateString(report.getReportDate(), "yyyy年MM月dd日"));
                        map.put("hospitalId", report.getHospitalId());
                        map.put("reportNum", report.getReportNum());
                        map.put("reportType", report.getReportType());
                        inspectionReportList.add(map);
                    }
                }

                data.put("laboratoryReportList", laboratoryReportList);
                data.put("inspectionReportList", inspectionReportList);

                return response.succeed(data);
            }

            return response.failed(BaseResponse.APP_ERROR, result.getInfo());

        } catch (Exception e) {
            logger.error("getMedicalRecordDetail({}): {}", recordId, e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 获取检查结果报告列表
     *
     * @param medicalCardId
     * @return
     */
    @RequestMapping({"/getInspectionReportList"})
    public @ResponseBody
    BaseResponse getInspectionReportList(@RequestParam(name = "medicalCardId") int medicalCardId) {
        BaseResponse response = new BaseResponse();
        List<Map<String, Object>> lst = new LinkedList<>();

        if (medicalCardId < 0) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "诊疗卡Id不存在");
        }

        try {
            com.ywt.gapi.user.GetInspectionReportListRequest req = com.ywt.gapi.user.GetInspectionReportListRequest.newBuilder()
                    .setMedicalCardId(medicalCardId)
                    .setUserId(userService.getCurrentUserIdWrapped())
                    .build();
            com.ywt.gapi.user.GetInspectionReportListResponse res = userServiceBlockingStub.getInspectionReportList(req);
            Result result = res.getResult();

            if (result.getCode() == ResultCode.SUCCEED) {
                for (com.ywt.gapi.user.InspectionReport report : res.getReportList()) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("id", report.getId());
                    map.put("title", report.getReportTitle());
                    map.put("reportId", report.getReportId());
                    map.put("reportDate", DateUtil.convertTimestampToDateString(report.getReportDate(), "yyyy年MM月dd日"));

                    lst.add(map);
                }

                Map<String, Object> data = new HashMap<>();
                data.put("list", lst);
                return response.succeed(data);
            }

            return response.failed(BaseResponse.APP_ERROR, result.getInfo());
        } catch (Exception e) {
            logger.error("getInspectionReportList({}): {}", medicalCardId, e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 获取检查结果报告详情
     *
     * @param reportId
     * @return
     */
    @RequestMapping({"/getInspectionReportDetail"})
    public @ResponseBody
    BaseResponse getInspectionReportDetail(@RequestParam(name = "reportId") String reportId) {
        BaseResponse response = new BaseResponse();

        if (StringHelper.isNullOrWhiteSpace(reportId)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "参数错误");
        }

        try {
            com.ywt.gapi.user.GetInspectionReportDetailRequest req = com.ywt.gapi.user.GetInspectionReportDetailRequest.newBuilder()
                    .setReportId(reportId)
                    .build();
            com.ywt.gapi.user.GetInspectionReportDetailResponse res = userServiceBlockingStub.getInspectionReportDetail(req);
            Result result = res.getResult();

            if (result.getCode() == ResultCode.SUCCEED) {
                com.ywt.gapi.user.InspectionReportDetail detail = res.getReport();
                Map<String, Object> map = new HashMap<>();

                map.put("Id", detail.getId());
                map.put("reportId", detail.getReportId());
                map.put("deptName", detail.getDeptName());
                map.put("appDocName", detail.getAppDocName());
                map.put("checkParts", detail.getCheckParts());
                map.put("examination", detail.getExamination());
                map.put("diagnosis", detail.getDiagnosis());
                map.put("checkDoctorName", detail.getCheckDoctorName());
                map.put("examinationDate", DateUtil.convertTimestampToDateString(detail.getExaminationDate(), "yyyy年MM月dd日 HH:mm:ss"));

                return response.succeed(map);
            }

            return response.failed(BaseResponse.APP_ERROR, result.getInfo());
        } catch (Exception e) {
            logger.error("getInspectionReportDetail({}): {}", reportId, e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 获取化验结果报告列表
     *
     * @param medicalCardId
     * @return
     */
    @RequestMapping({"/getLaboratoryReportList"})
    public @ResponseBody
    BaseResponse getLaboratoryReportList(@RequestParam(name = "medicalCardId") int medicalCardId) {
        BaseResponse response = new BaseResponse();
        List<Map<String, Object>> lst = new LinkedList<>();

        if (medicalCardId < 0) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "诊疗卡Id不存在");
        }

        try {
            com.ywt.gapi.user.GetLaboratoryReportListRequest req = com.ywt.gapi.user.GetLaboratoryReportListRequest.newBuilder()
                    .setMedicalCardId(medicalCardId)
                    .setUserId(userService.getCurrentUserIdWrapped())
                    .build();
            com.ywt.gapi.user.GetLaboratoryReportListResponse res = userServiceBlockingStub.getLaboratoryReportList(req);
            Result result = res.getResult();

            if (result.getCode() == ResultCode.SUCCEED) {
                for (com.ywt.gapi.user.LaboratoryReport report : res.getReportList()) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("id", report.getId());
                    map.put("title", report.getInspectionName());
                    map.put("inspectionId", report.getInspectionId());
                    map.put("reportDate", DateUtil.convertTimestampToDateString(report.getInspectionDate(), "yyyy年MM月dd日"));

                    lst.add(map);
                }

                Map<String, Object> data = new HashMap<>();
                data.put("list", lst);
                return response.succeed(data);
            }

            return response.failed(BaseResponse.APP_ERROR, result.getInfo());
        } catch (Exception e) {
            logger.error("getLaboratoryReportList({}): {}", medicalCardId, e.getMessage(), e);
            return response.error();
        }
    }

    /**
     * 获取检查结果报告详情
     *
     * @param inspectionId
     * @return
     */
    @RequestMapping({"/getLaboratoryReportDetail"})
    public @ResponseBody
    BaseResponse getLaboratoryReportDetail(@RequestParam(name = "inspectionId") String inspectionId) {
        BaseResponse response = new BaseResponse();

        if (StringHelper.isNullOrWhiteSpace(inspectionId)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "参数错误");
        }

        try {
            com.ywt.gapi.user.GetLaboratoryReportDetailRequest req = com.ywt.gapi.user.GetLaboratoryReportDetailRequest.newBuilder()
                    .setInspectionId(inspectionId)
                    .build();
            com.ywt.gapi.user.GetLaboratoryReportDetailResponse res = userServiceBlockingStub.getLaboratoryReportDetail(req);
            Result result = res.getResult();

            if (result.getCode() == ResultCode.SUCCEED) {
                String specimenNo = "";
                List<Map<String, Object>> lst = new LinkedList<>();

                for (com.ywt.gapi.user.LaboratoryReportDetail detail : res.getDetailList()) {
                    if (!StringHelper.isNullOrWhiteSpace(detail.getSpecimType())) {
                        specimenNo = detail.getSpecimType();
                    }

                    Map<String, Object> itemMap = new LinkedHashMap<>();
                    itemMap.put("itemId", detail.getItemId());
                    itemMap.put("itemName", detail.getItemName());
                    itemMap.put("itemRef", detail.getItemRef());
                    itemMap.put("orderNo", detail.getOrderNo());
                    itemMap.put("resultFlag", detail.getResultFlag());
                    itemMap.put("specimType", detail.getSpecimType());
                    itemMap.put("testDate", DateUtil.convertTimestampToDateString(detail.getTestDate(), "yyyy-MM-dd HH:mm:ss"));
                    itemMap.put("testEngName", detail.getTestEngName());
                    itemMap.put("testResult", detail.getTestResult());
                    itemMap.put("unit", detail.getUnit());
                    lst.add(itemMap);
                }

                Map<String, Object> data = new LinkedHashMap<>();
                data.put("title", res.getInspectionName());
                data.put("reportDate", DateUtil.convertTimestampToDateString(res.getInspectionDate()));
                data.put("status", res.getStatus() == 0 ? "未审核" : "已审核");
                data.put("checkDoctorName", res.getCheckDoctorName());
                data.put("specimenNo", specimenNo);
                data.put("count", lst.size());
                data.put("list", lst);
                return response.succeed(data);
            }

            return response.failed(BaseResponse.APP_ERROR, result.getInfo());
        } catch (Exception e) {
            logger.error("getInspectionReportDetail({}): {}", inspectionId, e.getMessage(), e);
            return response.error();
        }
    }

    private GetDoctorByHisCodeResponse getDoctorByHisCode(String doctorCode, int hospitalId) {
        GetDoctorByHisCodeRequest getDoctorByHisCodeRequest = GetDoctorByHisCodeRequest.newBuilder()
                .setHospitalId(hospitalId)
                .setHisCode(doctorCode)
                .build();
        return doctorServiceBlockingStub.getDoctorByHisCode(getDoctorByHisCodeRequest);
    }

    /**
     * 获取互联网医院科室代码列表（二级）
     *
     * @return 互联网医院科室代码列表
     */
    public List<HospitalDept> getNetDeptList(int hospitalId) {
        List<HospitalDept> netDeptList = new LinkedList<>();
        HospitalDeptListRequest req = HospitalDeptListRequest.newBuilder()
                .setHospitalId(hospitalId)
                .build();
        HospitalDeptListResponse res = systemServiceBlockingStub.getHospitalDeptList(req);
        if (res.getResult().getCode() == ResultCode.SUCCEED) {
            List<HospitalDept> hospitalDepts = res.getHospitalDeptListList();
            if (!Checker.isNone(hospitalDepts)) {
                netDeptList = hospitalDepts.stream()
                        .filter(hospitalDept -> BizUtil.getNetDeptCodeListByHospitalId(hospitalId).contains(hospitalDept.getDeptCode()))
                        .flatMap(d -> d.getDeptListList().stream())
                        .map(d -> HospitalDept.newBuilder()
                                .setDeptCode(d.getDeptCode())
                                .setDeptId(d.getDeptId())
                                .setDeptName(d.getDeptName())
                                .build())
                        .collect(Collectors.toList());
            }
        }

        return netDeptList;
    }

    @RequestMapping(value = {"/netDeptList"}, method = RequestMethod.POST)
    public @ResponseBody
    BaseResponse2<List<String>> netDeptList(@RequestBody Map<String, Object> reqData) {
        BaseResponse2<List<String>> baseResponse = new BaseResponse2<>();
        try {
            int hospitalId = Checker.getIntegerValue((Integer) reqData.getOrDefault("hospitalId", 0));
            if (hospitalId <= 0) {
                hospitalId = BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
            }
            List<HospitalDept> netDepts = getNetDeptList(hospitalId);
            if (!Checker.isNone(netDepts)) {
                List<String> deptCodes = netDepts.stream()
                        .map(HospitalDept::getDeptCode)
                        .collect(Collectors.toList());
                // 加入一级科室
                deptCodes.add(0, BizUtil.getNetDeptCodeByHospitalId(hospitalId));
                return baseResponse.succeed(deptCodes);
            }
            return baseResponse.succeed("没有科室数据");
        } catch (Exception e) {
            logger.error("RegisterController#netDeptList(reqData={} ):\n {}", reqData, e.getMessage(), e);
            return baseResponse.error(e.getMessage());
        }
    }


    /**
     * 获取扫码报到信息
     * <p>
     * cardNo 患者卡号
     * areaId 区域ID
     *
     * @return {@link BaseResponse}
     */
    @RequestMapping(value = {"/getCheckInInfo"}, method = RequestMethod.POST)
    public BaseResponse getCheckInInfo(@RequestBody Map<String, Object> reqData) {
        String cardNo = (String) reqData.getOrDefault("cardNo", "");
        String areaId = (String) reqData.getOrDefault("areaId", "");
        Boolean sendMessage = (Boolean) reqData.getOrDefault("sendMessage", false);
        int hospitalId = Checker.getIntegerValue((Integer) reqData.getOrDefault("hospitalId", 0));
        Map<String, Object> data = new HashMap<>();
        if (hospitalId <= 0) {
            hospitalId = BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
        }
        int userId = userSrv.getCurrentUserIdWrapped();

        BaseResponse response = new BaseResponse();
        GetCheckInRequest req = GetCheckInRequest.newBuilder()
                .setCardNo(cardNo)
                .setAreaCode(areaId)
                .setHospitalId(hospitalId)
                .build();
        GetCheckInResponse resp = taiheServiceBlockingStub.getCheckIn(req);
        if (resp.getCode() == ResultCode.SUCCEED_VALUE) {
            List<Map<String, Object>> lst = new LinkedList<>();
            List<CheckInItem> list = resp.getListList();
            for (int size = list.size(), i = 0; i < size; i++) {
                CheckInItem item = list.get(size - i - 1);
                Map<String, Object> map = new HashMap<>();
                map.put("patName", item.getPatName());
                map.put("admLoc", item.getAdmLoc());
                map.put("resultText", item.getResultText());
                map.put("queueNo", item.getQueueNo());
                map.put("admStatus", item.getAdmStatus());
                map.put("rangTime", item.getRangTime());
                map.put("admArriveDate", item.getAdmArriveDate());
                map.put("admWaitNumber", item.getAdmWaitNumber());
                map.put("admBoroughDesc", item.getAdmBoroughDesc());
                map.put("admWaitTrueNumber", item.getAdmWaitTrueNumber());
                map.put("admDoc", item.getAdmDoc());
                if (sendMessage) {
                    RegisterCheckInMessageRequest request = RegisterCheckInMessageRequest.newBuilder()
                            .setUserId(userId)
                            .setHospitalId(hospitalId)
                            .setPatName(item.getPatName())
                            .setCardNo(cardNo)
                            .setAreaCode(areaId)
                            .setQueueNo(item.getQueueNo())
                            .setAdmArriveDate(item.getAdmArriveDate())
                            .setAdmBoroughDesc(item.getAdmBoroughDesc())
                            .setAdmLoc(item.getAdmLoc())
                            .setAdmDoc(item.getAdmDoc())
                            .setRangTime(item.getRangTime())
                            .build();
                    RegisterCheckInMessageResponse res = taiheRegisterServiceBlockingStub.registerCheckInMessage(request);

                    if (res.getCode() != ResultCode.SUCCEED_VALUE) {
                        logger.error("RegisterController#getCheckInInfo():registerCheckInMessage\n{}", res.getInfo());
//                        data.put("list", lst);
//                        return response.succeed("处理成功", data);
                    }
                }
                lst.add(map);
            }

            data.put("list", lst);
            return response.succeed("处理成功", data);
        }
        return response.failed(BaseResponse.APP_ERROR, resp.getInfo());

    }

    /**
     * 医院列表
     *
     * @return
     */
    @UserLogin(need = false)
    @RequestMapping(value = {"/hospitalList"}, method = RequestMethod.POST)
    public BaseResponse hospitalList(@RequestBody Map<String, Object> reqData) {
        List<Integer> hospitalIds = (List<Integer>) reqData.getOrDefault("hospitalIds", null);
        return systemSrv.getHospitalListByHospitalIds(hospitalIds);
    }

    /**
     * 根据 hospitalIds 获取医院或其分医院。如果医院有分院，则返回分院；如果无分院，返回该医院。
     */
    @UserLogin(need = false)
    @RequestMapping(value = {"/hospitalListNew"}, method = RequestMethod.POST)
    public BaseResponse hospitalListNew(@RequestBody Map<String, Object> reqData) {
        List<Integer> hospitalIds = (List<Integer>) reqData.getOrDefault("hospitalIds", null);
        return systemSrv.getHospitalListByHospitalIdsNew(hospitalIds);
    }

    /**
     * 调用 HIS 接口建档，建档成功后新建就诊卡
     */
    @RequestMapping(value = {"/createMedCard"}, method = RequestMethod.POST)
    public @ResponseBody
    BaseResponse2<CreateMedCardResp> createMedCard(@RequestBody CreateMedCardReq reqData) {
        BaseResponse2<CreateMedCardResp> baseResponse = new BaseResponse2<>();
        try {
            String phoneNo = reqData.getPhoneNo();
            String idNo = reqData.getIdNo();
            String patientName = reqData.getPatientName();
            String city = reqData.getCity();
            String address = reqData.getAddress();
            String isInsu = Checker.getStringValue(reqData.getIsInsu());
            String cardType = Checker.getStringValue(reqData.getCardType(), "1");
            int hospitalId = Checker.getIntegerValue(reqData.getHospitalId());
            if (Checker.isNone(cardType)) {
                cardType = "1";
            }
            if ("1".equals(cardType) && !IdCardUtil.verify(idNo)) {
                throw new YwtCommonException(YwtCommonRespCode.P_ERR, "“身份证号”或“证件类型”有误，建档不成功，请修改！");
            }
            CheckUtil.ensureValidPhoneNumber(phoneNo, String.format("手机号不合法：%s", phoneNo));
            CheckUtil.ensureNotEmpty(patientName, "请完善姓名");
            CheckUtil.ensureNotEmpty(city, "请完善在线建卡市区");
            CheckUtil.ensureNotEmpty(address, "请完善详细地址");
            if (hospitalId <= 0) {
                hospitalId = BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
            }
            int terminal = userSrv.getCurrentTerminal();
            CreateMedicalCardResponse response = taiheRegisterServiceBlockingStub.createMedicalCard(CreateMedicalCardRequest.newBuilder()
                    .setPhoneNo(phoneNo)
                    .setIdNo(idNo)
                    .setPatientName(patientName)
                    .setCity(city)
                    .setAddress(address)
                    .setIsInsu(isInsu)
                    .setHospitalId(hospitalId)
                    .setUserId(userService.getCurrentUserIdWrapped())
                    .setCardType(cardType)
                    .setTerminal(terminal)
                    .build());
            if (response.getCode() == BaseResponse.SUCCEED) {
                CreateMedCardResp resp = new CreateMedCardResp();
                resp.setMedicalCardId(response.getMedicalCardId());
                resp.setMedicalCardNo(response.getMedicalCardNo());
                return baseResponse.succeed(response.getInfo(), resp);
            }
            return baseResponse.failed(BaseResponse.APP_ERROR, response.getInfo());
        } catch (YwtCommonException appMessageException) {
            return baseResponse.error(appMessageException.getMessage());
        } catch (Exception e) {
            logger.error("RegisterController#createMedCard(): {}", e.getMessage(), e);
            return baseResponse.error(e.getMessage());
        }
    }

    @RequestMapping(value = {"/testRedis"}, method = RequestMethod.POST)
    public @ResponseBody
    BaseResponse testRedis(@RequestBody Map<String, Object> reqMap) {
        BaseResponse baseResponse = new BaseResponse();
        try {
            String method = (String) reqMap.getOrDefault("method", "GET");
            String key = (String) reqMap.getOrDefault("key", "1");
            String redisKey = String.format(Constant.YWT_COVID19_LIST_KEY, key);
            int expireTime = (int) reqMap.getOrDefault("expireTime", 10);
            String patternKey = String.format(Constant.YWT_COVID19_LIST_KEY, "*");
            logger.error("redisKey:" + redisKey + "\tpatternKey:" + patternKey);

            if (method.equals("GET")) {

                // 缓存类型：0-GuavaCache, 1-Redis
                int cacheType = 1;
                // 键匹配模式：0-match, 1-pattern
                int keyType = 1;
                List<String> keys = devController.getKeys(patternKey, keyType, cacheType);
                baseResponse.setData(JsonSerializer.toJson(keys));
                return baseResponse.succeed("length:" + keys.size());
            }
            if (method.equals("SET")) {
                redisTemplate.opsForValue().set(redisKey, "1", expireTime, TimeUnit.SECONDS);
            }
            if (method.equals("DEL")) {
                redisTemplate.delete(redisKey);
            }
            if (method.equals("TEST")) {
                String userKey = String.format(Constant.YWT_COVID19_LIST_KEY, key);
                if (!checkExistYwtCovid19ListKey(userKey)) {
                    return baseResponse.failedWithParameterError("请稍后再查询，谢谢！");
                }
            }
            return baseResponse.succeed("处理成功");
        } catch (Exception e) {
            logger.error("RegisterController#testRedis(): {}", e.getMessage(), e);
            return baseResponse.error(e.getMessage());
        }
    }

    private boolean unitTestDemo(String userKey) {
        if (Checker.isNone(userKey)) {
            return true;
        }
        String key = String.format(Constant.YWT_COVID19_LIST_KEY, "*");
        // 缓存类型：0-GuavaCache, 1-Redis
        int cacheType = 1;
        // 键匹配模式：0-match, 1-pattern
        int keyType = 1;
        List<String> keys = devController.getKeys(key, keyType, cacheType);
        if (Checker.isNone(keys)) {
            redisTemplate.opsForValue().set(userKey, "1", Constant.YWT_COVID19_KEY_EXPIRE_TIME, TimeUnit.SECONDS);
            return true;
        }
        String value = keys.stream().filter(p -> p.equals(userKey)).findFirst().orElse(null);
        // 如果不包含，而且队列的数量尚未满，那么则可以插入
        if (Checker.isNone(value) && keys.size() <= parameterConfigurer.getYwtCovid19ListCount()) {
            redisTemplate.opsForValue().set(userKey, "1", Constant.YWT_COVID19_KEY_EXPIRE_TIME, TimeUnit.SECONDS);
            return true;
        }
        return false;
    }

    private List<GetDistanceReq> getDestList() {
        List<GetDistanceReq> list = new ArrayList<>();
        GetDistanceReq d = new GetDistanceReq();
        d.setHospitalId(Constant.NFYYBYFY_HOSPITAL_ID);
        d.setSubHospitalId(CheckInConstants.NFYYBYFY_SH_SUB_HOSPITAL_ID);
        d.setLongitude(CheckInConstants.NFYYBYFY_SH_LONGITUDE);
        d.setLatitude(CheckInConstants.NFYYBYFY_SH_LATITUDE);
        list.add(d);
        GetDistanceReq d2 = new GetDistanceReq();
        d2.setHospitalId(Constant.NFYYBYFY_HOSPITAL_ID);
        d2.setSubHospitalId(CheckInConstants.NFYYBYFY_HS_SUB_HOSPITAL_ID);
        d2.setLongitude(CheckInConstants.NFYYBYFY_HS_LONGITUDE);
        d2.setLatitude(CheckInConstants.NFYYBYFY_HS_LATITUDE);
        list.add(d2);
        return list;
    }

    /**
     * 根据当前位置计算离目的地距离
     */
    @RequestMapping(value = {"/getDistance"}, method = RequestMethod.POST)
    public @ResponseBody
    BaseResponse2<GetDistanceResp> getDistance(@RequestBody GetDistanceReq reqData) {
        BaseResponse2<GetDistanceResp> baseResponse = new BaseResponse2<>();
        try {
            int userId = userService.getCurrentUserIdWrapped();
            CheckUtil.ensureLargerThanZero(userId, "请登录");
            String longitude = Checker.getStringValue(reqData.getLongitude()).trim();
            String latitude = Checker.getStringValue(reqData.getLatitude()).trim();
            CheckUtil.ensureNotEmpty(longitude, "经度参数不能为空");
            CheckUtil.ensureNotEmpty(latitude, "纬度参数不能为空");
            List<GetDistanceReq> destList = getDestList();
            GetDistanceResp resp = new GetDistanceResp();
            List<DistanceInfo> infoList = new LinkedList<>();
            boolean nearby = false;
            for (GetDistanceReq d : destList) {
                GetDistanceResponse response = lbsServiceBlockingStub.getDistance(GetDistanceRequest.newBuilder()
                        .setMode(CheckInConstants.GET_DISTANCE_MODE)
                        .setFrom(latitude + "," + longitude)
                        .setTo(d.getLatitude() + "," + d.getLongitude())
                        .build());
                if (response.getCode() == BaseResponse.SUCCEED) {
                    DistanceInfo i = new DistanceInfo();
                    i.setHospitalId(d.getHospitalId());
                    i.setSubHospitalId(d.getSubHospitalId());
                    i.setLongitude(d.getLongitude());
                    i.setLatitude(d.getLatitude());
                    double distance = 0;
                    List<GetDistanceResponse.LocationDistance> el = response.getElementList();
                    if (!Checker.isNone(el)) {
                        distance = el.get(0).getDistance();
                    }
                    i.setDistance(distance);
                    infoList.add(i);
                    if (distance <= parameterConfigurer.getNearBYDistance()) {
                        nearby = true;
                        break;
                    }
                } else {
                    return baseResponse.failedWithAppError(response.getMsg());
                }
            }
            resp.setNearby(nearby);
            resp.setDistanceInfoList(infoList);
            return baseResponse.succeed(resp);
        } catch (YwtCommonException appMessageException) {
            return baseResponse.error(appMessageException.getMessage());
        } catch (Exception e) {
            logger.error("RegisterController#getDistance(): {}", e.getMessage(), e);
            return baseResponse.error(e.getMessage());
        }
    }

    /**
     * 查询医生联合排班
     */
    @RequestMapping(value = {"/doctorScheduleUnionList"}, method = RequestMethod.POST)
    public @ResponseBody
    BaseResponse2<GetDoctorScheduleUnionListResp> doctorScheduleUnionList(@RequestBody GetDoctorScheduleUnionListReq reqData) {
        BaseResponse2<GetDoctorScheduleUnionListResp> baseResponse = new BaseResponse2<>();
        try {

            int hospId = BizUtil.getHospitalIdByTerminalId(userSrv.getCurrentTerminal());
            int doctorId = reqData.getDoctorId();
            CheckUtil.ensureLargerThanZero(doctorId, "医生 id 有误");
            GetDoctorHisCodeListResponse response = doctorServiceBlockingStub.getDoctorHisCodeList(GetDoctorHisCodeListRequest.newBuilder()
                    .setDoctorId(doctorId)
                    .build());
            if (response.getResult().getCodeValue() != BaseResponse.SUCCEED) {
                return baseResponse.failed(BaseResponse.APP_ERROR, String.format("医生 id 无法获取信息(%d-%s)", doctorId, response.getResult().getInfo()));
            }
            List<DoctorHisCode> doctorHisCodes = response.getDoctorHisCodeList();
            List<ScheduleItem> unionItems = new ArrayList<>();
            String doctorName = "";
            for (DoctorHisCode doctorHisCode : doctorHisCodes) {
                int hospitalId = doctorHisCode.getHospitalId();
                if (hospitalId == hospId) {
                    doctorName = Checker.getStringValue(doctorHisCode.getDoctorName());

                    String doctorCode = doctorHisCode.getDoctorCode();
                    String deptCode = doctorHisCode.getDeptCode();
                    List<Dept> deptList = systemSrv.getDeptListByHospitalId(hospitalId);
                    // 默认查从当天开始共计 6 天
                    Map<String, Object> data;
                    try {
                        data = getScheduleListCommon(hospitalId, deptCode, doctorCode, "", 0, 6);
                    } catch (YwtCommonException e) {
                        logger.error("NfyyByfyRegisterController#doctorScheduleUnionList(reqData={} ):\n {}", reqData, e.getMessage(), e);
                        continue;
                    }
                    List<Map<String, Object>> scheduleList = (List<Map<String, Object>>) data.getOrDefault("list", new ArrayList<>());
                    for (Map<String, Object> map : scheduleList) {
                        int offset = (int) map.getOrDefault("offset", 0);
                        String week = (String) map.getOrDefault("week", "");
                        String deptName = (String) map.getOrDefault("deptName", "");
                        List<Map<String, Object>> forenoonSchedules = tryGetDatePeriodScheduleList("forenoonSchedules", map);
                        List<Map<String, Object>> afternoonSchedules = tryGetDatePeriodScheduleList("afternoonSchedules", map);
                        List<Map<String, Object>> nightSchedules = tryGetDatePeriodScheduleList("nightSchedules", map);
                        List<Map<String, Object>> afterMidnightSchedules = tryGetDatePeriodScheduleList("afterMidnightSchedules", map);
                        List<ScheduleItem> forenoonScheduleItems = forenoonSchedules.stream().map(i -> tryGetScheduleItem(i, hospitalId, offset, week, deptList, deptName)).collect(Collectors.toList());
                        List<ScheduleItem> afternoonScheduleItems = afternoonSchedules.stream().map(i -> tryGetScheduleItem(i, hospitalId, offset, week, deptList, deptName)).collect(Collectors.toList());
                        List<ScheduleItem> nightScheduleItems = nightSchedules.stream().map(i -> tryGetScheduleItem(i, hospitalId, offset, week, deptList, deptName)).collect(Collectors.toList());
                        List<ScheduleItem> afterMidnightScheduleItems = afterMidnightSchedules.stream().map(i -> tryGetScheduleItem(i, hospitalId, offset, week, deptList, deptName)).collect(Collectors.toList());
                        unionItems.addAll(forenoonScheduleItems);
                        unionItems.addAll(afternoonScheduleItems);
                        unionItems.addAll(nightScheduleItems);
                        unionItems.addAll(afterMidnightScheduleItems);
                        // Add an empty list while no schedules
                        if (Checker.isNone(forenoonScheduleItems) && Checker.isNone(afternoonScheduleItems) &&
                                Checker.isNone(nightScheduleItems) && Checker.isNone(afterMidnightScheduleItems)) {
                            ScheduleItem i = new ScheduleItem();
                            Calendar calendar = Calendar.getInstance();
                            calendar.add(Calendar.DATE, offset);
                            String dateStr = DateUtil.formatDate(calendar.getTime(), "yyyy-MM-dd"); //日期
                            i.setServiceDate(dateStr);
                            i.setWeek(DateUtil.getDayOfWeekShort(calendar));
                            i.setOffset(offset);
                            i.setDeptName(deptName);
                            unionItems.add(i);
                        }
                    }
                }
            }
            Map<String, List<ScheduleItem>> map = unionItems.stream().collect(Collectors.groupingBy(ScheduleItem::getServiceDate));
            GetDoctorScheduleUnionListResp resp = new GetDoctorScheduleUnionListResp();
            List<DoctorScheduleUnionItem> doctorScheduleUnionItems = new ArrayList<>();
            for (String k : map.keySet()) {
                List<ScheduleItem> schedules = map.get(k);
                ScheduleItem s = Checker.isNone(schedules) ? null : schedules.get(0);
                DoctorScheduleUnionItem i = new DoctorScheduleUnionItem();
                i.setOffset(Optional.ofNullable(s).map(ScheduleItem::getOffset).orElse(0));
                i.setWeek(Optional.ofNullable(s).map(ScheduleItem::getWeek).orElse(""));
                i.setDeptName(Optional.ofNullable(s).map(ScheduleItem::getDeptName).orElse(""));

                schedules = schedules.stream().filter(ss -> !StringHelper.isNullOrEmpty(ss.getDoctorCode())).collect(Collectors.toList());
                if (!Checker.isNone(schedules)) {
                    schedules.sort(Comparator.comparingInt(ScheduleItem::getPeriod));
                }
                int hasSchedule = Checker.isNone(schedules) ? 0 : 1;
                i.setServiceDate(k);
                i.setHasScheduling(hasSchedule);
                i.setScheduleItems(schedules);
                doctorScheduleUnionItems.add(i);
            }
            doctorScheduleUnionItems.sort(Comparator.comparingInt(DoctorScheduleUnionItem::getOffset));
            resp.setDoctorId(doctorId);
            resp.setDoctorName(doctorName);
            resp.setDoctorScheduleUnionItems(doctorScheduleUnionItems);
            return baseResponse.succeed(resp);

        } catch (YwtCommonException appMessageException) {
            return baseResponse.error(appMessageException.getMessage());
        } catch (Exception e) {
            logger.error("NfyyByfyRegisterController#doctorScheduleUnionList(): {}", e.getMessage(), e);
            return baseResponse.error(e.getMessage());
        }
    }

    public ScheduleItem tryGetScheduleItem(Map<String, Object> mm, int hospitalId, int offset, String week, List<Dept> deptList, String deptName) {
        if (mm == null) return null;
        String serviceDate = (String) mm.getOrDefault("serviceDate", "");
        int period = (int) mm.getOrDefault("datePeriod", 0);
        String deptCode = (String) mm.getOrDefault("deptCode", "");
        String doctorCode = (String) mm.getOrDefault("doctorCode", "");

        int subHospitalId = 0;
        Dept dept = deptList.stream().filter(p -> p.getDeptCode().equals(deptCode)).findFirst().orElse(null);
        if (dept != null) {
            subHospitalId = Checker.getIntegerValue(dept.getSubHospitalId());
        }
        HospitalCustomInfo p = BizUtil.getHospitalCustomInfo(subHospitalId > 0 ? subHospitalId : hospitalId);
        String hospitalName = p.getAlias();
        String hospitalAddr = p.getAddr();
        ScheduleItem i = new ScheduleItem();
        i.setServiceDate(serviceDate);
        i.setPeriod(period);
        i.setHospitalName(hospitalName);
        i.setHospitalAddr(hospitalAddr);
        i.setDeptCode(deptCode);
        i.setHospitalId(hospitalId);
        i.setDoctorCode(doctorCode);
        i.setOffset(offset);
        i.setWeek(week);
        i.setDeptName(deptName);
        return i;
    }

    /**
     * 原来的获取科室排班列表方法抽离
     *
     * @param startOffset 开始日期 offset, 值取 0 表示当天；
     * @param endOffset   结束日期 offset, 值取 0 表示当天；
     *                    <p>
     *                    startOffset 和 endOffset 其中一个为负值时，表示不指定日期范围，默认按照“太和查未来 8 天，不包括当天；白云查未来 6 天，包括当天”的规则查询。
     *                    都不为负值时，按照传入的 offset 计算开始结束日期。
     */
    private Map<String, Object> getScheduleListCommon(int hospitalId, String deptCode, String doctorCode,
                                                      String serviceCode, int startOffset, int endOffset) throws YwtCommonException {
        String redisKeyPattern = "SCHEDULE_LIST_%s_%s_%d_%s";
        String key = String.format(redisKeyPattern, deptCode, doctorCode, hospitalId, serviceCode);
        if (startOffset >= 0 && endOffset >= 0) {
            redisKeyPattern = "SCHEDULE_LIST_%s_%s_%d_%s_%d_%d";
            key = String.format(redisKeyPattern, deptCode, doctorCode, hospitalId, serviceCode, startOffset, endOffset);
        }
        String value = redisTemplate.opsForValue().get(key)+"";
        if (!StringHelper.isNullOrWhiteSpace(value)) {
            Map<String, Object> cacheMap = JsonSerializer.from(value, Map.class);
            if (cacheMap != null) {
                return cacheMap;
            }
        }

        List<Dept> deptList = systemSrv.getDeptListByHospitalId(hospitalId);
        if (deptList == null || deptList.size() == 0) {
            throw new YwtCommonException(YwtCommonRespCode.P_ERR, String.format("无法获取科室数据(%d)", hospitalId));
        }
        List<Dept> tmpDeptList = deptList.stream().filter(p -> p.getDeptCode().equals(deptCode)).collect(Collectors.toList());
        if (tmpDeptList.size() == 0) {
            logger.error(String.format("deptCode 不存在(%d-%s-%s)", hospitalId, deptCode, doctorCode));
            throw new YwtCommonException(YwtCommonRespCode.P_ERR, "暂无出诊信息");
        }
        Dept secDept = tmpDeptList.get(0);
        tmpDeptList = deptList.stream().filter(p -> p.getDeptId() == secDept.getParentId()).collect(Collectors.toList());
        if (tmpDeptList.size() == 0) {
            logger.error(String.format("deptCode 不合法(%d-%s-%s)", hospitalId, deptCode, doctorCode));
            throw new YwtCommonException(YwtCommonRespCode.P_ERR, "暂无出诊信息");
        }

        Map<String, Object> map = new HashMap<>();
        map.put("hospitalId", hospitalId);
        map.put("hospitalName", BizUtil.getHospitalNameByIdSimply(hospitalId));
        map.put("deptCode", deptCode);
        map.put("deptName", secDept.getDeptName());

        List<DeptScheduleDoctor> doctorList = doctorSrv.getDeptScheduleDoctorListFromCache();
//        doctorList = doctorList.stream().filter(p -> p.getDeptCode().equals(deptCode)).collect(Collectors.toList());

        // 批量日期查询 HIS 接口
        boolean isTaihe = hospitalId == Constant.TAIHE_HOSPITAL_ID;
        if (startOffset < 0 || endOffset < 0) {
            startOffset = isTaihe ? 1 : 0;
            endOffset = isTaihe ? 9 : 7;
        }
        List<Map<String, Object>> lst = getConvertedScheduleList(hospitalId, startOffset, endOffset, deptCode,
                doctorCode, serviceCode, secDept.getDeptName());
        map.put("list", lst);
        redisTemplate.opsForValue().set(key, JsonSerializer.toJson(map), Constant.REDIS_EXPIRE_TIME_THREE_MINUTES, TimeUnit.SECONDS);
        return map;
    }

    private List<Map<String, Object>> getConvertedScheduleList(int hospitalId, int startOffset, int endOffset, String deptCode,
                                                               String doctorCode, String serviceCode, String deptName) {
        Calendar calendar = Calendar.getInstance();
        if (startOffset > 0) {
            calendar.add(Calendar.DATE, startOffset);
        }
        String startDate = DateUtil.formatDate(calendar.getTime(), "yyyy-MM-dd"); //日期
        calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, endOffset);
        String endDate = DateUtil.formatDate(calendar.getTime(), "yyyy-MM-dd"); //日期

        GetScheduleListRequest getScheduleListRequest = GetScheduleListRequest.newBuilder()
                .setDeptCode(deptCode)
                .setDoctorCode(doctorCode)
                .setServiceDate(startDate)
                .setServiceEndDate(endDate)
                .setHospitalId(hospitalId)
                .setServiceCode(serviceCode)
                .build();
        GetScheduleListResponse getScheduleListResponse = taiheServiceBlockingStub.getScheduleList(getScheduleListRequest);
        List<Schedule> scheduleList;
        if (getScheduleListResponse.getCode() == ResultCode.SUCCEED_VALUE) {
            scheduleList = getScheduleListResponse.getSchedulesList();
        } else {
            logger.error("NfyyByfyRegisterController#getConvertedScheduleList(): HIS 获取排班接口出错：{}", getScheduleListResponse.getMsg());
            scheduleList = new LinkedList<>();
        }
        // 单日查询的情况
        if (startOffset == endOffset) {
            Calendar c = Calendar.getInstance();
            if (startOffset > 0) {
                c.add(Calendar.DATE, startOffset);
            }
            String strDate = DateUtil.formatDate(c.getTime(), "yyyy-MM-dd"); //日期
            List<Map<String, Object>> list = new ArrayList<>();
            list.add(convertToScheduleMap(scheduleList, c, strDate, 0, hospitalId, deptName));
            return list;
        } else {
            return IntStream.range(startOffset, endOffset).mapToObj(offset -> {
                Calendar c = Calendar.getInstance();
                if (offset > 0) {
                    c.add(Calendar.DATE, offset);
                }
                String strDate = DateUtil.formatDate(c.getTime(), "yyyy-MM-dd"); //日期
                return convertToScheduleMap(scheduleList.stream().filter(s -> strDate.equals(s.getServiceDate())).collect(Collectors.toList()),
                        c, strDate, offset, hospitalId, deptName);
            }).collect(Collectors.toList());
        }
    }


    /**
     * 排班记录转为Map
     */
    private Map<String, Object> convertToScheduleMap(List<Schedule> scheduleList, Calendar calendar, String strDate,
                                                     int offset, int hospitalId, String deptName) {
        List<Map<String, Object>> forenoonList = new LinkedList<>();
        List<Map<String, Object>> afternoonList = new LinkedList<>();
        List<Map<String, Object>> nightList = new LinkedList<>();
        List<Map<String, Object>> afterMidnightList = new LinkedList<>();   // 下半夜排班
        List<Map<String, Object>> midnoonList = new ArrayList<>();          //午间排班记录
        GetDoctorByHisCodeResponse getDoctorByHisCodeResponse;
        String avatar;

        int doctorId;
        boolean hasScheduling = scheduleList.size() > 0;    //当期日期是否有排班

        Map<String, Object> groupMap = new HashMap<>();
        groupMap.put("serviceDate", strDate);
        groupMap.put("offset", offset);
        groupMap.put("week", DateUtil.getDayOfWeekShort(calendar));
        groupMap.put("deptName", deptName);

        for (Schedule s : scheduleList) {
//            if (doctorList.stream().noneMatch(p -> s.getDoctorCode().equals(p.getDoctorCode()))) {
//                continue;
//            }

            doctorId = 0;
            avatar = Constant.DOCTOR_AVATAR_URL;
            getDoctorByHisCodeResponse = getDoctorByHisCode(s.getDoctorCode(), hospitalId);

            if (getDoctorByHisCodeResponse.getResult().getCode() == ResultCode.SUCCEED) {
                if (!StringHelper.isNullOrWhiteSpace(getDoctorByHisCodeResponse.getAvatar())) {
                    avatar = getDoctorByHisCodeResponse.getAvatar();
                }

                doctorId = getDoctorByHisCodeResponse.getDoctorId();
            }
            if (doctorId <= 0) {
                continue;
            }
            // 需求改动：
            // v3.3.8 名医关闭咨询，也可以继续挂号和创建线下就诊订单
//            if (systemSrv.checkIsNetDept(s.getDeptCode())) {
//                //南方医院太和分院（互联网医院名医诊区）
//                GetConsultSettingsRequest getConsultSettingsReq = GetConsultSettingsRequest.newBuilder()
//                        .setUserId(doctorId)
//                        .build();
//                GetConsultSettingsResponse getConsultSettingsRes = doctorServiceBlockingStub.getConsultSettings(getConsultSettingsReq);
//                if (getConsultSettingsRes.getResult().getCode() != ResultCode.SUCCEED) {
//                    continue;
//                }
//                if (getConsultSettingsRes.getStatus() != 1) {
//                    //医生需要开启咨询功能
//                    continue;
//                }
//            }

            Map<String, Object> scheduleMap = new HashMap<>();
            scheduleMap.put("scheduleItemCode", s.getScheduleItemCode());       //门诊排班项记录标识
            scheduleMap.put("serviceDate", s.getServiceDate());                 //门诊排班日期(yyyy-MM-dd)
            scheduleMap.put("datePeriod", s.getDatePeriod());           //排班时段代码
            scheduleMap.put("datePeriodName", s.getDatePeriodName());   //排班时段名称
            scheduleMap.put("deptCode", s.getDeptCode());               //科室代码
            scheduleMap.put("deptName", s.getDeptName());               //科室名称
            scheduleMap.put("doctorCode", s.getDoctorCode());           //医生代码
            scheduleMap.put("doctorName", s.getDoctorName());           //医生名称
            scheduleMap.put("doctorId", doctorId);                      //医生Id
            scheduleMap.put("avatar", avatar);                          //医生图片链接
            scheduleMap.put("doctorTitle", s.getDoctorTitle());         //医生职称
            scheduleMap.put("doctorSpec", s.getDoctorSpec());           //医生专长
            scheduleMap.put("fee", s.getFee());                         //预约挂号总费用
            scheduleMap.put("regFee", s.getRegFee());                   //挂号费
            scheduleMap.put("checkupFee", s.getCheckupFee());           //诊查费
            scheduleMap.put("serviceFee", s.getServiceFee());           //服务费
            scheduleMap.put("otherFee", s.getOtherFee());               //其它费
            scheduleMap.put("admitAddress", s.getAdmitAddress());       //就诊地址
            scheduleMap.put("scheduleStatus", s.getScheduleStatus());       //出诊状态（1-可预约 0-已满 2-停诊 3-其它(不可预约)）
            scheduleMap.put("availableTotalNum", s.getAvailableTotalNum()); //该时段可预约的总号源数
            scheduleMap.put("availableLeftNum", s.getAvailableLeftNum());   //该时段剩余号源数
            scheduleMap.put("serviceName", s.getServiceName());   //亚专科名称
            scheduleMap.put("serviceCode", s.getServiceCode());   //亚专科代码

            String statusName = "";

            switch (s.getScheduleStatus()) {
                case 1:
                    statusName = "可预约";
                    break;
                case 0:
                    statusName = "已满";
                    break;
                case 2:
                    statusName = "停诊";
                    break;
                default:
                    statusName = "停诊";
                    break;
            }

            scheduleMap.put("scheduleStatusName", statusName);

            switch (s.getDatePeriod()) {
                case 2:
                    forenoonList.add(scheduleMap);
                    break;
                case 3:
                    afternoonList.add(scheduleMap);
                    break;
                case 4:
                    nightList.add(scheduleMap);
                    break;
                case 5:
                    afterMidnightList.add(scheduleMap);
                    break;
                case 6:                 //午间排班记录返回数
                    midnoonList.add(scheduleMap);
                    break;

            }
        }

        groupMap.put("hasScheduling", hasScheduling ? 1 : 0);   //当期日期是否有排班
        groupMap.put("forenoonSchedules", forenoonList);        //上午排班记录
        groupMap.put("afternoonSchedules", afternoonList);      //下午排班记录
        groupMap.put("nightSchedules", nightList);              //晚上排班记录
        groupMap.put("afterMidnightSchedules", afterMidnightList);              //晚上排班记录
        groupMap.put("midnoonSchedules", midnoonList);          //午间排班记录
        return groupMap;
    }

    private List<Map<String, Object>> tryGetDatePeriodScheduleList(String key, Map<String, Object> m) {
        if (m.get(key) == null) return new ArrayList<>();
        try {
            return (List<Map<String, Object>>) m.get(key);
        } catch (Exception e) {
            logger.error("NfyyByfyRegisterController#tryGetDatePeriodScheduleList(key={} , m={} ):\n {}", key, m, e.getMessage(), e);
        }
        return new ArrayList<>();
    }

    @UserLogin(need = false)
    @RequestMapping({"/getMedicalDeptList"})
    public @ResponseBody
    BaseResponse getMedicalDeptList(@RequestParam(name = "subHospitalId", required = false, defaultValue = "0") int subHospitalId,
                             @RequestParam(name = "hospitalId", required = false, defaultValue = "0") int hospitalId,
                                @RequestParam(name = "name", required = false, defaultValue = "") String name){
        int hId = hospitalId > 0 ? hospitalId : BizUtil.getHospitalIdByTerminalId(BizUtil.getCurrentTerminalWrapped());
        HospitalMedicalDeptListRequest req =  HospitalMedicalDeptListRequest.newBuilder()
                .setHospitalId(hId)
                .setSubHospitalId(subHospitalId)
                .setName(name)
                .build();
        HospitalMedicalDeptListResponse res = systemServiceBlockingStub.hospitalMedicalDeptList(req);
        Result result = res.getResult();
        if (result.getCode() != ResultCode.SUCCEED) {
            return new BaseResponse().failed(BaseResponse.PARAMETER_ERROR, result.getInfo());
        }
        HashMap<Object, Object> map = new HashMap<>();
        List<Map<String, Object>> lst = new LinkedList<>();
        List<Dept> deptList = null;
        deptList = res.getDeptListList();
        if(!Checker.isNone(deptList)){
            for(Dept d : deptList){
                Map<String, Object> item = new HashMap<>();
                item.put("deptId", d.getDeptId());
                item.put("deptCode", d.getDeptCode());
                item.put("deptName", d.getDeptName());
                lst.add(item);
            }
        }
        Map<String, Object> data = new HashMap<>();
        data.put("list", lst);
        map.put("data", data);
        return new BaseResponse().succeed(map);
    }

}
