package com.ywt.outpatient.service.rpc;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ywt.biz.common.enums.SexEnum;
import com.ywt.biz.common.enums.TerminalEnum;
import com.ywt.biz.common.util.*;
import com.ywt.biz.common.util.serializers.JsonSerializer;
import com.ywt.gapi.Result;
import com.ywt.gapi.ResultCode;
import com.ywt.gapi.base.file.FileService;
import com.ywt.gapi.base.file.UploadImageRequest;
import com.ywt.gapi.base.file.UploadImageResponse;
import com.ywt.gapi.base.wechat.CreateQrCodeLimitStrSceneRequest;
import com.ywt.gapi.base.wechat.CreateQrCodeLimitStrSceneResponse;
import com.ywt.gapi.base.wechat.WeChatService;
import com.ywt.gapi.doctor.SaveDoctorHisCodeListRequest;
import com.ywt.gapi.doctor.SaveDoctorHisCodeListResponse;
import com.ywt.outpatient.core.Constant;
import com.ywt.outpatient.domain.models.*;
import com.ywt.gapi.doctor.TeamDoctorInfo;
import com.ywt.gapi.statistics.DoctorStatisticsService;
import com.ywt.gapi.statistics.GetDoctorStatisticsTotalInfoRequest;
import com.ywt.gapi.statistics.GetDoctorStatisticsTotalInfoResponse;
import com.ywt.gapi.system.SearchDoctorByNameFromMultiHospRequest;
import com.ywt.gapi.system.SearchDoctorListByNameRequest;
import com.ywt.gapi.system.SearchDoctorListByNameResponse;
import com.ywt.gapi.third.taihe.Schedule;
import com.ywt.outpatient.core.PagedList;
import com.ywt.outpatient.core.SqlHelper;
import com.ywt.outpatient.domain.entity.center.*;
import com.ywt.outpatient.core.Constants;
import com.ywt.outpatient.domain.models.enums.*;
import com.ywt.outpatient.service.common.TaiheProvider;
import com.ywt.outpatient.service.rpc.common.*;
import com.ywt.outpatient.domain.entity.center.DrugProvider;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.ParameterMode;
import javax.persistence.StoredProcedureQuery;
import java.lang.reflect.Type;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@SuppressWarnings("javadoc")
@Service
public class DoctorService {
    private static Logger logger = LoggerFactory.getLogger(DoctorService.class);

    @Autowired
    UserRepository userRepository;

    @Autowired
    DoctorRepository doctorRepository;

    @Autowired
    HospitalRepository hospitalRepository;

    @Autowired
    private SqlHelper sqlHelperYwtCenter;

    @Autowired
    private PatientRepository patientRepository;

    @Autowired
    private IdGenerator idGenerator;

    @Autowired
    private UnionDoctorRepository unionDoctorRepository;

    @Autowired
    private DoctorDeptRepository doctorDeptRepository;

    @Autowired
    private DepartmentRepository departmentRepository;

    @Autowired
    private AttendingOrderViewRepository attendingOrderViewRepository;

    @Autowired
    private TreatmentOrderViewRepository treatmentOrderViewRepository;

    @Autowired
    private TransferOrderViewRepository transferOrderViewRepository;

    @Autowired
    private EntityManager entityManager;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private MedicalRecordsImageRepository medicalRecordsImageRepository;

    @Autowired
    private MedicalRecordsRepository medicalRecordsRepository;

    @Autowired
    private DoctorSignRepository doctorSignRepository;

    @Autowired
    private ConfigServiceProvider configServiceProvider;

    @Autowired
    private DoctorInfoAuditRepository doctorInfoAuditRepository;

    @Autowired
    private DoctorInfoViewRepository doctorInfoViewRepository;

    @Autowired
    private MedicalModuleRepository medicalModuleRepository;

    @Autowired
    private HospitalService hospitalService;

    @Autowired
    private MedicalCardRepository medicalCardRepository;

    @Autowired
    private AccountDetailRepository accountDetailRepository;

    @Autowired
    private QuickLanguageRepository quickLanguageRepository;

    @Autowired
    private DoctorScheduleRepository doctorScheduleRepository;

    @Autowired
    private ScheduleConfigRepository scheduleConfigRepository;

    @Autowired
    private AddressRepository addressRepository;

    @Autowired
    private AdditionalRegistrationRepository additionalRegistrationRepository;

    @Autowired
    private OrderService orderService;

    @Autowired
    private SnsUserRepository snsUserRepository;

    @Autowired
    private SnsUserInfoRepository snsUserInfoRepository;

    @Autowired
    private TeamRepository teamRepository;

    @Autowired
    private TeamDoctorRepository teamDoctorRepository;

    @Autowired
    private DoctorHisCodeRepository doctorHisCodeRepository;

    @Autowired
    private DrugProviderRepository drugProviderRepository;

    @Autowired
    private AgentRepository agentRepository;

    @Autowired
    private UserUnionsRepository userUnionsRepository;

    @Autowired
    private ArticlesRepository articlesRepository;

    @Autowired
    private ArticlesUnionRepository articlesUnionRepository;

    @DubboReference
    private WeChatService weChatServiceBlockingStub;

    @DubboReference
    private FileService fileServiceBlockingStub;

    @Autowired
    private TeamDoctorInfoViewRepository teamDoctorInfoViewRepository;

    @Autowired
    private TeamDoctorViewRepository teamDoctorViewRepository;

    @Autowired
    private TaiheProvider taiheProvider;

    @Autowired
    private NfyyProvider nfyyProvider;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private DoctorInfoAuditViewRepository doctorInfoAuditViewRepository;

    @DubboReference
    private DoctorStatisticsService doctorStatisticsServiceBlockingStub;

    @Autowired
    private WxProvider wxProvider;

    @Autowired
    private WeChatMsgProvider weChatMsgProvider;

    @Autowired
    BizConfigurer bizConfigurer;

    @Autowired
    private DoctorTitleRepository doctorTitleRepository;

    @Autowired
    private DoctorFixedPointRepository doctorFixedPointRepository;

    @Autowired
    private DoctorQrCodeUrlRepository doctorQrCodeUrlRepository;

    @Autowired
    private CommonDoctorSettingRepository commonDoctorSettingRepository;

    // 所有医生信息（包括正在认证的）缓存键
    private final String ALL_DOCTOR_LIST = "allDoctors";
    // 所有医生信息（包括正在认证的）map 缓存键
    private final String ALL_DOCTOR_MAP = "allDoctorsMap";

    public static final String REDIS_KEY_DISPLAY_TEAM_LIST = "DisplayTeamList";

    /**
     * 获取医生好友列表
     *
     * @param doctorId
     * @return
     */
    public PagedList<FriendInfo> getFriendList(int doctorId, int hospitalId, int deptId, String name, int pageIndex, int pageSize) {
        int start = (pageIndex - 1) * pageSize;
        StoredProcedureQuery storedProcedureQuery = entityManager.createStoredProcedureQuery("get_friend_list_new")
                .registerStoredProcedureParameter("uid", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("start", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("size", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("hospitalId", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("deptId", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("name", String.class, ParameterMode.IN)
                .registerStoredProcedureParameter("total", Integer.class, ParameterMode.OUT)
                .setParameter("uid", doctorId)
                .setParameter("hospitalId", hospitalId)
                .setParameter("deptId", deptId)
                .setParameter("name", Checker.getStringValue(name, ""))
                .setParameter("start", start)
                .setParameter("size", pageSize);
        storedProcedureQuery.execute();
        List resultList = storedProcedureQuery.getResultList();
        List<FriendInfo> items = new LinkedList<>();

        for (int i = 0; i < resultList.size(); i++) {
            Object[] arr = (Object[]) resultList.get(i);
            FriendInfo friendInfo = new FriendInfo();
            friendInfo.setDoctorId(doctorId);
            friendInfo.setUnionDoctorId((int) arr[0]);
            friendInfo.setTitle(StringHelper.toString(arr[1]));
            friendInfo.setSpecialty(StringHelper.toString(arr[2]));
            friendInfo.setBriefIntro(StringHelper.toString(arr[3]));
            friendInfo.setRealName(StringHelper.toString(arr[4]));
            friendInfo.setAvatar(StringHelper.toString(arr[5]));
            friendInfo.setCity(StringHelper.toString(arr[6]));
            friendInfo.setHospitalIds(StringHelper.toString(arr[7]));
            friendInfo.setDeptIds(StringHelper.toString(arr[8]));
            friendInfo.setScheduleStatus((int) arr[9]);
            friendInfo.setAvatar2(StringHelper.toString(arr[10]));

            items.add(friendInfo);
        }

        int total = (int) storedProcedureQuery.getOutputParameterValue("total");
        return new PagedList<>(pageIndex, pageSize, total, items);
    }

    public PagedList<FriendInfo> getFriendList(int doctorId, String hospitalId, int deptId, String name, int pageIndex, int pageSize) {
        int start = (pageIndex - 1) * pageSize;
        StoredProcedureQuery storedProcedureQuery = entityManager.createStoredProcedureQuery("get_friend_list3352")
                .registerStoredProcedureParameter("uid", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("start", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("size", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("hospitalId", String.class, ParameterMode.IN)
                .registerStoredProcedureParameter("deptId", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("name", String.class, ParameterMode.IN)
                .registerStoredProcedureParameter("total", Integer.class, ParameterMode.OUT)
                .setParameter("uid", doctorId)
                .setParameter("hospitalId", hospitalId)
                .setParameter("deptId", deptId)
                .setParameter("name", Checker.getStringValue(name, ""))
                .setParameter("start", start)
                .setParameter("size", pageSize);
        storedProcedureQuery.execute();
        List resultList = storedProcedureQuery.getResultList();
        List<FriendInfo> items = new LinkedList<>();

        for (int i = 0; i < resultList.size(); i++) {
            Object[] arr = (Object[]) resultList.get(i);
            FriendInfo friendInfo = new FriendInfo();
            friendInfo.setDoctorId(doctorId);
            friendInfo.setUnionDoctorId((int) arr[0]);
            friendInfo.setTitle(StringHelper.toString(arr[1]));
            friendInfo.setSpecialty(StringHelper.toString(arr[2]));
            friendInfo.setBriefIntro(StringHelper.toString(arr[3]));
            friendInfo.setRealName(StringHelper.toString(arr[4]));
            friendInfo.setAvatar(StringHelper.toString(arr[5]));
            friendInfo.setCity(StringHelper.toString(arr[6]));
            friendInfo.setHospitalIds(StringHelper.toString(arr[7]));
            friendInfo.setDeptIds(StringHelper.toString(arr[8]));
            friendInfo.setScheduleStatus((int) arr[9]);

            items.add(friendInfo);
        }

        int total = (int) storedProcedureQuery.getOutputParameterValue("total");
        return new PagedList<>(pageIndex, pageSize, total, items);
    }

    /**
     * 获取医生详细信息
     *
     * @param mobile
     * @return
     */
    public DoctorInfo getDoctorInfoByMobile(String mobile) {
        User user = userRepository.getDoctorByMobile(mobile);
        return getDoctorInfo(user);
    }

    /**
     * 获取医生详细信息
     *
     * @param id
     * @return
     */
    public DoctorInfo getDoctorInfoById(int id) {
        User user = userRepository.findById(id).orElse(null);
        return getDoctorInfo(user);
    }

    public int getDoctorIdentity(int doctorId) {
        Doctor doctor = doctorRepository.findById(doctorId).orElse(null);
        if (doctor != null) {
            return Checker.getIntegerValue(doctor.getIdentity());
        }
        return 0;
    }

    public boolean isUserADoctor(User user) {
        return user != null && !user.getIsDeleted() && (user.getUsertype() & UserTypeEnum.Doctor.getValue()) == UserTypeEnum.Doctor.getValue();
    }

    /**
     * 获取医生详细信息
     *
     * @param user
     * @return
     */
    private DoctorInfo getDoctorInfo(User user) {
        if (user == null || user.getIsDeleted() || (user.getUsertype() & UserTypeEnum.Doctor.getValue()) != UserTypeEnum.Doctor.getValue()) {
            //用户不存在或用户不是医生类型
            return null;
        }

        DoctorInfo info = new DoctorInfo();
        info.setDoctorId(user.getId());
        info.setName(user.getRealname());
        info.setAvatar(user.getAvatar());
        info.setCity(user.getCity());
        info.setStatus(user.getStatus());
        info.setMobile(user.getMobile());
        info.setSex(user.getSex());

        Doctor d = doctorRepository.findById(user.getId()).orElse(null);
        info.setIdentity(d == null ? 0 : Checker.getIntegerValue(d.getIdentity()));

        int uid = user.getId();
        Doctor doctor = doctorRepository.findById(uid).orElse(null);
        int hospitalIdInt = hospitalService.getFirstIdByIds(Checker.getStringValue(d.getHospitalIds()));
        List<DoctorQrCodeUrl> qrCodeList = getDoctorQrCodeUrlListByDoctorId(doctor.getId(), hospitalIdInt);
        if (doctor != null) {
            if (Checker.isNone(qrCodeList)) {
                // 如果存在为空的情况，那就异步处理，再次请求时则会有数据了
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // 目前该方法删除
                        // getDoctorQrCodeList(uid);
                    }
                }).start();
            }
            info.setAvatar2(doctor.getAvatar2());
            info.setSpecialty(doctor.getSpecialty());
            info.setBriefIntro(doctor.getBriefIntro());
            info.setTitle(doctor.getTitle());
            info.setQrCodeUrl(getDoctorQrCodeUrlByTypeNew(qrCodeList, CREATE_QR_CODE_TYPE_QR_CODE_URL));
            info.setScheduleStatus(doctor.getScheduleStatus());
            info.setDoctorStatus(doctor.getStatus());
            info.setAuthType(doctor.getAuthType());
            info.setRpContent(getDoctorQrCodeContentByTypeNew(qrCodeList, CREATE_QR_CODE_TYPE_RP_URL));
            info.setRpUrl(getDoctorQrCodeUrlByTypeNew(qrCodeList, CREATE_QR_CODE_TYPE_RP_URL));
            info.setRpContentPc(getDoctorQrCodeContentByTypeNew(qrCodeList, CREATE_QR_CODE_TYPE_RP_URL_PC));
            info.setRpUrlPc(getDoctorQrCodeUrlByTypeNew(qrCodeList, CREATE_QR_CODE_TYPE_RP_URL_PC));
            info.setPharmacyId(doctor.getPharmacyId());
            info.setNegReception(Checker.getBooleanValue(doctor.getNegReception()));
            info.setNegReceptionHint(Checker.getStringValue(doctor.getNegReceptionHint()));
            info.setEnableNextConsultChance(Checker.getIntegerValue(doctor.getNextConsultChance()) > 0);
            info.setOfflineFee(Checker.getIntegerValue(doctor.getOfflineFee()));
            info.setPrescriptionRightStatus(Checker.getIntegerValue(doctor.getPrescriptionRightStatus()));
            info.setPrescriptionRightPharmacyIds(Checker.getStringValue(doctor.getPrescriptionRightPharmacyIds()));

            if (doctor.getConsultFee() == null) {
                info.setConsultAmount(configServiceProvider.getConsultFee());
            } else {
                info.setConsultAmount(doctor.getConsultFee());
            }

            String[] hospitalIds = doctor.getHospitalIds().split(",");
            for (String strHospitalId : hospitalIds) {
                if (!StringHelper.isNullOrEmpty(strHospitalId)) {
                    int hospitalId = Checker.parseInt(strHospitalId, 0);
                    if (hospitalId > 0) {
                        //医院id
                        Hospital hospital = hospitalService.getHospital(hospitalId);

                        if (hospital != null && !hospital.isDeleted()) {
                            info.setHospitalId(hospital.getId());
                            info.setHospitalName(hospital.getName());
                            break;
                        }
                    }
                }
            }

            String[] deptIds = doctor.getDeptIds().split(",");
            for (String strDeptId : deptIds) {
                if (!StringHelper.isNullOrEmpty(strDeptId)) {
                    int deptId = Checker.parseInt(strDeptId, 0);
                    if (deptId > 0) {
                        //科室id
                        Department department = hospitalService.getDepartment(deptId);
                        if (department != null && !department.isDeleted()) {
                            info.setDeptId(department.getId());
                            info.setDeptName(department.getName());
                            break;
                        }
                    }
                }
            }
        }

        return info;
    }

    /**
     * 从医生的 hospitalIds里找出第一个有效的医院 id
     *
     * @param doctorHospitalIds
     * @return
     */
    public int getDoctorHospitalId(String doctorHospitalIds) {
        int hospitalId = 0;
        String[] hospitalIds = Checker.getStringValue(doctorHospitalIds).split(",");
        for (String strHospitalId : hospitalIds) {
            if (!StringHelper.isNullOrEmpty(strHospitalId)) {
                hospitalId = Checker.parseInt(strHospitalId, 0);
                if (hospitalId > 0) {
                    //医院id
                    Hospital hospital = hospitalRepository.findById(hospitalId).orElse(null);

                    if (hospital != null && !hospital.isDeleted()) {
                        return hospitalId;
                    }
                }
            }
        }
        return hospitalId;
    }

    public ServiceResult createMedicalRecords(
            String typeName, String desc, String images, int doctorId, int patientId, String diagnose) {
        ServiceResult serviceResult = new ServiceResult();

//        if (StringHelper.isNullOrWhiteSpace(typeName)) {
//            return serviceResult.failed("病历类型不能为空");
//        }
        if (StringHelper.isNullOrWhiteSpace(diagnose)) {
            return serviceResult.failed("诊断不能为空");
        }
//        if (StringHelper.isNullOrWhiteSpace(desc)) {
//            return serviceResult.failed("病情描述不能为空");
//        }

        List<String> imageUrlList = new LinkedList<>();

        if (!StringHelper.isNullOrWhiteSpace(images)) {
            String[] arrImage = images.split(",");

            for (String image : arrImage) {
                if (!StringHelper.isNullOrWhiteSpace(image)) {
                    imageUrlList.add(image);
                }
            }
        }

        if (imageUrlList.size() > 20) {
            return serviceResult.failed("最多只能添加20张图片");
        }

        MedicalRecords records = new MedicalRecords();
        records.setId(idGenerator.genMedicalRecordsId());
        records.setAge(0);
        records.setPresentHistory(desc);
        records.setCreateTime(new Date());
        records.setUpdateTime(null);
        records.setDeleted(false);
        records.setDiagnosis("");
        records.setDoctorId(doctorId);
        records.setMobile("");
        records.setRemark("");
        records.setSex(0);
        records.setUserId(0);
        records.setTypeName(typeName);
        records.setPatientId(patientId);
        records.setDiagnosis(diagnose);
        records.setType(MedicalRecordsTypeEnum.MedicalRecords.getValue());

        medicalRecordsRepository.save(records);

        if (imageUrlList.size() > 0) {
            List<MedicalRecordsImage> lst = new LinkedList<>();

            for (String url : imageUrlList) {
                //本次新增的图片链接
                MedicalRecordsImage image = new MedicalRecordsImage();
                image.setId(idGenerator.genMedicalRecordsImageId());
                image.setCreateTime(new Date());
                image.setDeleted(false);
                image.setDoctorId(doctorId);
                image.setImageUrl(url);
                image.setMedicalRecordsId(records.getId());
                image.setPatientId(patientId);
                image.setType(MedicalRecordsImageTypeEnum.MedicalRecords.getValue());

                lst.add(image);
            }

            medicalRecordsImageRepository.saveAll(lst);
        }

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

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

    public ServiceResult updateMedicalRecords(
            String typeName, String desc, String images, int recordId, int doctorId, String diagnose) {
        ServiceResult serviceResult = new ServiceResult();

//        if (StringHelper.isNullOrWhiteSpace(typeName)) {
//            return serviceResult.failed("病历类型不能为空");
//        }
        if (StringHelper.isNullOrWhiteSpace(diagnose)) {
            return serviceResult.failed("诊断不能为空");
        }
        if (StringHelper.isNullOrWhiteSpace(desc)) {
            return serviceResult.failed("病情描述不能为空");
        }

        List<String> imageUrlList = new LinkedList<>();

        if (!StringHelper.isNullOrWhiteSpace(images)) {
            String[] arrImage = images.split(",");

            for (String image : arrImage) {
                if (!StringHelper.isNullOrWhiteSpace(image)) {
                    imageUrlList.add(image);
                }
            }
        }
        if (imageUrlList.size() > 20) {
            return serviceResult.failed("最多只能添加20张图片");
        }

        MedicalRecords records = medicalRecordsRepository.findById(recordId).orElse(null);
        if (records == null || records.getDeleted() || records.getType() != MedicalRecordsTypeEnum.MedicalRecords.getValue()) {
            return serviceResult.failed("病历不存在");
        }
        if (records.getDoctorId() != doctorId) {
            return serviceResult.failed("您无权修改该病历");
        }

        records.setDiagnosis(diagnose);
//        records.setTypeName(typeName);
//        records.setChiefComplaint(desc);
        records.setPresentHistory(desc);
        records.setUpdateTime(new Date());
        medicalRecordsRepository.save(records);

        if (imageUrlList.size() > 0) {
            List<MedicalRecordsImage> lst = new LinkedList<>();
            List<MedicalRecordsImage> medicalRecordsImages = medicalRecordsImageRepository.getListByRecordId(recordId);
            List<String> existedImages = new LinkedList<>();    //已存在的病历图片链接

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

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

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

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

                    lst.add(image);
                }
            }

            medicalRecordsImageRepository.saveAll(lst);
        } else {
            jdbcTemplate.execute(String.format("update medical_records_image set deleted = 1 where medical_records_id = %d;", recordId));
        }
        return serviceResult.succeed("处理成功");
    }

    /**
     * 添加患者
     * 思路：1、当通过手机号在user表能找到对象时，可在patient表中添加对应的信息；
     * 2、当在user表中找不到对象时，在patient表添加记录的时候，该记录的userId默认为0
     * 3、对于能在user表中找到记录，需要再去patient表里面匹配，同一个人不能添加重复的手机号和患者姓名（暂时以手机号和患者姓名为标准）
     * Edit by daiyihua
     *
     * @param name
     * @param sex
     * @param age
     * @param mobile
     * @param doctorId
     * @return
     */
    public ServiceResult createPatient(String name, int sex, int age, String mobile, int doctorId,
                                       String chiefComplaint, String diagnosis, String remark, String images,
                                       String allergicHistory, String description, String idCardNo) {
        ServiceResult result = new ServiceResult();

        if (StringHelper.isNullOrWhiteSpace(name)) {
            return result.failed("请输入姓名");
        }

        SexEnum sexEnum = SexEnum.valueOf(sex);
        if (sexEnum == null) {
            return result.failed("请选择性别");
        }

        if (age < 0 || age > 130) {
            return result.failed("请输入正确的年龄");
        }

        if (StringHelper.isNullOrWhiteSpace(mobile)) {
            return result.failed("请输入手机号码");
        }

        if (!PhoneNumChecker.isPhoneNum(mobile)) {
            return result.failed("请输入正确的手机号码");
        }

        List<String> imageUrlList = new LinkedList<>();

        if (!StringHelper.isNullOrWhiteSpace(images)) {
            String[] arrImage = images.split(",");

            for (String image : arrImage) {
                if (!StringHelper.isNullOrWhiteSpace(image)) {
                    imageUrlList.add(image);
                }
            }
        }

        if (imageUrlList.size() > 20) {
            return result.failed("最多只能添加20张图片");
        }

        int userId = 0;
        Date currentDate = new Date();
        User user = userRepository.getUserByMobile(mobile);

        if (user != null && !user.getIsDeleted()) {
            userId = user.getId();
        }

        int patientId = 0;
        Patient patient = null;
        if (Checker.isNone(idCardNo)) {
            patient = patientRepository.getPatient(doctorId, mobile, name);
        } else {
            patient = patientRepository.getByIdCardNo(doctorId, idCardNo.trim());
        }

        if (!StringHelper.isNullOrWhiteSpace(description)) {
            description = StringHelper.filterEmoji(description);
        }

        if (patient != null) {
            patientId = patient.getId();

            patient.setAge(age);
            patient.setSex(sex);
            patient.setUpdateTime(currentDate);
            patient.setChiefComplaint(chiefComplaint);
            patient.setDiagnosis(diagnosis);
            patient.setRemark(remark);
            patient.setDeleted(false);
            patient.setUserId(userId);
            patient.setAllergicHistory(allergicHistory);
            patient.setDescription(description);
        } else {
            patientId = idGenerator.generatePatientId();
            patient = new Patient();
            patient.setId(patientId);
            patient.setRealName(name);
            patient.setAge(age);
            patient.setSex(sex);
            patient.setMobile(mobile);
            patient.setDoctorId(doctorId);
            patient.setUserId(userId);
            patient.setCreateTime(currentDate);
            patient.setUpdateTime(currentDate);
            patient.setDeleted(false);
            patient.setChiefComplaint(chiefComplaint);
            patient.setDiagnosis(diagnosis);
            patient.setRemark(remark);
            patient.setAllergicHistory(allergicHistory);
            patient.setDescription(description);
            patient.setIdCardNo(idCardNo);
        }

        patientRepository.save(patient);

        if (imageUrlList.size() > 0) {
            List<MedicalRecordsImage> lst = new LinkedList<>();
            List<MedicalRecordsImage> medicalRecordsImages = medicalRecordsImageRepository.getPatientImageList(patient.getId(), doctorId);
            List<String> existedImages = new LinkedList<>();    //已存在的病历图片链接

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

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

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

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

                    lst.add(image);
                }
            }

            medicalRecordsImageRepository.saveAll(lst);
        } else {
            jdbcTemplate.execute(String.format("update medical_records_image set deleted = 1 where patient_id = %d and doctor_id = %d and type = 0;", patientId, doctorId));
        }

        //保存病历编辑历史
        MedicalRecords records = new MedicalRecords();
        records.setId(idGenerator.genMedicalRecordsId());
        records.setAge(age);
        records.setChiefComplaint(chiefComplaint);
        records.setCreateTime(currentDate);
        records.setUpdateTime(null);
        records.setDeleted(false);
        records.setDiagnosis(diagnosis);
        records.setDoctorId(doctorId);
        records.setMobile(mobile);
        records.setRemark(remark);
        records.setSex(sex);
        records.setUserId(userId);
        records.setType(MedicalRecordsTypeEnum.EditHistory.getValue());

        medicalRecordsRepository.save(records);

        Map<String, Object> data = new HashMap<>();
        data.put("userId", userId);
        data.put("patientId", patientId);
        return result.succeed("添加成功", data);
    }


    /**
     * 修改患者
     *
     * @param name
     * @param sex
     * @param age
     * @param mobile
     * @param doctorId
     * @return
     */
    public ServiceResult updatePatient(int patientId, String name, int sex, int age, String mobile, int doctorId,
                                       String chiefComplaint, String diagnosis, String remark, String images,
                                       String allergicHistory, String description) {
        ServiceResult result = new ServiceResult();

        if (StringHelper.isNullOrWhiteSpace(name)) {
            return result.failed("请输入姓名");
        }

        SexEnum sexEnum = SexEnum.valueOf(sex);
        if (sexEnum == null || sexEnum == SexEnum.Unknown || sexEnum == SexEnum.Unspecified) {
            return result.failed("请选择性别");
        }

        if (age < 0 || age > 130) {
            return result.failed("请输入正确的年龄");
        }

        if (StringHelper.isNullOrWhiteSpace(mobile)) {
            return result.failed("请输入手机号码");
        }

        if (!PhoneNumChecker.isPhoneNum(mobile)) {
            return result.failed("请输入正确的手机号码");
        }

        List<String> imageUrlList = new LinkedList<>();

        if (!StringHelper.isNullOrWhiteSpace(images)) {
            String[] arrImage = images.split(",");

            for (String image : arrImage) {
                if (!StringHelper.isNullOrWhiteSpace(image)) {
                    imageUrlList.add(image);
                }
            }
        }

        if (imageUrlList.size() > 20) {
            return result.failed("最多只能添加20张图片");
        }

        int userId = 0;
        Date currentDate = new Date();
        User user = userRepository.getUserByMobile(mobile);

        if (user != null && !user.getIsDeleted()) {
            userId = user.getId();
        }

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

        if (patient == null) {
            return result.failed("参数错误");
        }
        patient.setAge(age);
        patient.setSex(sex);
        patient.setUpdateTime(currentDate);
        patient.setChiefComplaint(chiefComplaint);
        patient.setDiagnosis(diagnosis);
        patient.setRemark(remark);
        patient.setDeleted(false);
        patient.setUserId(userId);
        patient.setAllergicHistory(allergicHistory);
        patient.setDescription(description);

        patientRepository.save(patient);

        if (imageUrlList.size() > 0) {
            List<MedicalRecordsImage> lst = new LinkedList<>();
            List<MedicalRecordsImage> medicalRecordsImages = medicalRecordsImageRepository.getPatientImageList(patient.getId(), doctorId);
            List<String> existedImages = new LinkedList<>();    //已存在的病历图片链接

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

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

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

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

                    lst.add(image);
                }
            }
            medicalRecordsImageRepository.saveAll(lst);
        } else {
            jdbcTemplate.execute(String.format("update medical_records_image set deleted = 1 where patient_id = %d and doctor_id = %d;", patientId, doctorId));
        }

        Map<String, Object> data = new HashMap<>();
        data.put("userId", userId);
        return result.succeed("添加成功", data);
    }


    /**
     * 获取"我的患者"列表
     *
     * @param doctorId
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public PagedList<Patient> getMyPatientList(int doctorId, int pageIndex, int pageSize, String name, int userId) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = "doctor_id = " + doctorId;

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

        if (userId > 0) {
            whereSql += " and user_id > 0 ";
        }

        whereSql += " and deleted = 0";

        System.out.println(whereSql);

        PagedList<Patient> pagedList = sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc", Patient.class, paramList.toArray());
//        List<Patient> list = pagedList.getItems();

        return pagedList;
    }

    /**
     * 获取我的关联医生
     *
     * @param doctorId
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public PagedList<UnionDoctorDeptInfoView> getUnionDoctorDeptList(int doctorId, int pageIndex, int pageSize,
                                                                     int hospitalId, int deptId, String name) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " doctor_id = ? or union_doctor_id = ? ";
        paramList.add(doctorId);
        paramList.add(doctorId);


        if (hospitalId != 0) {
            whereSql += " and hospital_id = ? ";
            paramList.add(hospitalId);
        }

        if (deptId != 0) {
            whereSql += " and dept_id = ? ";
            paramList.add(deptId);
        }

        if (!Checker.isNone(name)) {
            whereSql += " and real_name like ? ";
            paramList.add("%" + name.trim() + "%");
        }

        PagedList<UnionDoctorDeptInfoView> pagedList = sqlHelperYwtCenter.getPagedList(
                pageIndex, pageSize, "*", whereSql, "create_time desc",
                UnionDoctorDeptInfoView.class, paramList.toArray());
        return pagedList;
    }


    /**
     * 添加或取消关联医生
     *
     * @param userId
     * @param doctorId
     * @param type
     * @return
     */
    public ServiceResult unionDoctor(int userId, int doctorId, int type) {
        ServiceResult result = new ServiceResult();
        User user = userRepository.findById(userId).orElse(null);

        if (userId == doctorId)
            return result.failed("不能添加自己为关联医生");

        if (user != null) {
            // type: 操作类型（1-添加关联，0-取消关联）
            if (type == 1) {
                //查找没有进行物理删除的关联医生
                List<UnionDoctor> unionDoctorList = unionDoctorRepository.getUnionDoctorByUserId(userId, doctorId, doctorId, userId);
                UnionDoctor unionDoctor = null;
                //如果存在关联医生，那就只需要改变其状态就好，数据库中的状态字段为1：添加关联
                if (!Checker.isNone(unionDoctorList)) {
                    unionDoctor = unionDoctorList.get(0);
                    unionDoctor.setStatus(1);
                } else {
                    //如果不存在关联医生，那就添加关联医生，每一个字段都必须要添加，不然就会报错
                    unionDoctor = new UnionDoctor();
                    unionDoctor.setCreateTime(new Date());
                    unionDoctor.setDeleted(false);
                    unionDoctor.setDoctorId(userId);
                    unionDoctor.setId(idGenerator.generateUnionDoctorId());
                    unionDoctor.setStatus(1);
                    unionDoctor.setUnionDoctorId(doctorId);
                }
                unionDoctorRepository.save(unionDoctor);
                return result.succeed("处理成功");
            } else if (type == 0) {
                //能够进行删除的，那么肯定是添加了的，只要得到这个对象并修改其状态就好
                //得到添加的对象
                List<UnionDoctor> unionDoctorList = unionDoctorRepository.getUnionDoctorByUserId(userId, doctorId, doctorId, userId);
                if (!Checker.isNone(unionDoctorList)) {
                    for (UnionDoctor u : unionDoctorList) {
                        //在数据库中的状态，2：表示取消关联
                        u.setStatus(2);
                        //修改状态并保存
                        unionDoctorRepository.save(u);
                    }

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


    /**
     * 获取平台所有医生列表
     *
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public PagedList<DoctorInfoView> getDoctorInfoList(
            int pageIndex, int pageSize, String name, int hospitalId, int deptId) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = "";
        if (!Checker.isNone(name)) {
            whereSql += " real_name like ? and ";
            paramList.add("%" + name + "%");
        }
        //当hospitalId==0或者deptId==0时，查找的是全部的医生
        if (hospitalId != 0) {
            whereSql += " hospital_ids like ? and ";
            paramList.add("," + hospitalId + ",");
        }

        if (deptId != 0) {
            whereSql += " dept_ids like ? and ";
            paramList.add("," + deptId + ",");
        }

        whereSql += " is_deleted = 0 ";
        PagedList<DoctorInfoView> pagedList = sqlHelperYwtCenter.getPagedList(
                pageIndex, pageSize, "*", whereSql, "create_time desc",
                DoctorInfoView.class, paramList.toArray());
        return pagedList;
    }

    /**
     * 获取平台所有医生列表
     *
     * @param pageIndex
     * @param pageSize
     * @param name
     * @param arrHospitalId
     * @param deptId
     * @return
     */
    public PagedList<DoctorInfoView> getDoctorInfoList(
            int pageIndex, int pageSize, String name, int[] arrHospitalId, int deptId) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = "";

        if (!Checker.isNone(name)) {
            whereSql += " real_name like ? and ";
            paramList.add("%" + name + "%");
        }

        if (arrHospitalId.length > 0) {
            String hospitalSql = "";
            for (int hospitalId : arrHospitalId) {
                if (hospitalId != 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids like ? ";
                    } else {
                        hospitalSql += " or hospital_ids like ? ";
                    }
                    paramList.add("%," + hospitalId + ",%");
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }

        if (deptId != 0) {
            whereSql += " dept_ids like ? and ";
            paramList.add("%," + deptId + ",%");
        }

        //过滤被禁用医院的医生（医院下有医生，若后台设置这家医院为禁用，这个医院下的所有医生也不显示在app列表中）
        String idSql = "select id from hospital where status = 1 or is_deleted = 1;";
        List<Integer> hospitalIds = jdbcTemplate.queryForList(idSql, Integer.class);

        if (hospitalIds != null && hospitalIds.size() > 0) {
            String hospitalSql = "";

            for (Integer hospitalId : hospitalIds) {
                if (hospitalId > 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids <> ? ";
                    } else {
                        hospitalSql += " and hospital_ids <> ? ";
                    }

                    paramList.add("," + hospitalId + ",");
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }


        whereSql += " is_deleted = 0 and doctor_status = 0 ";
        return sqlHelperYwtCenter.getPagedList(
                pageIndex, pageSize, "*", whereSql, "create_time desc",
                DoctorInfoView.class, paramList.toArray());
    }

    /**
     * 判断是否关联某个医生
     * 返回的值大于0时，说明已经关联，否则就不关联
     *
     * @param doctorId
     * @param unionDoctorId
     * @return
     */
    public int checkUnionDoctor(int doctorId, int unionDoctorId) {
        return doctorRepository.checkUnionDoctor(doctorId, unionDoctorId, unionDoctorId, doctorId);
    }


    public Patient getPatientById(int id) {
        return patientRepository.findById(id).orElse(null);
    }


    /**
     * 删除我的患者
     * edit by daiyihua
     *
     * @param userId
     * @param patientId
     * @return
     */
    public ServiceResult delPatient(int userId, int patientId) {
        ServiceResult result = new ServiceResult();

        //得到患者对象
        Patient patient = patientRepository.findById((Integer) patientId).orElse(null);
        if (patient == null || patient.getDeleted()) {
            return result.failed("该患者不存在");
        }

        if ((patient.getDoctorId() != userId)) {
            return result.failed("您没有删除该患者的权限");
        }

        //判断当前患者是否有未结束的订单，主要判断的是转诊，询诊、主诊
        int count = 0; //定义为0
        //主诊
        List<AttendingOrderView> attendingOrderViews = attendingOrderViewRepository.checkAttendingPatientOrder(userId, patientId);

        if (!Checker.isNone(attendingOrderViews)) {
            for (AttendingOrderView o : attendingOrderViews) {
                OrderStatusEnum statusEnum = OrderStatusEnum.Pending_Payment;
                Calendar ca2 = Calendar.getInstance();

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

                    if (ca2.after(ca1)) {
                        //转出医生24h内没有收到回复
                        statusEnum = OrderStatusEnum.Over;
                    }
                } else if ((o.getAttendingStatus() & AttendingStatusEnum.Refuse.getValue()) == AttendingStatusEnum.Refuse.getValue()) {
                    //主诊医生拒绝订单
                    statusEnum = OrderStatusEnum.Over;
                } else if ((o.getAttendingStatus() & AttendingStatusEnum.InformPatient.getValue()) == AttendingStatusEnum.InformPatient.getValue()) {
                    //已通知用户
                    Calendar ca1 = Calendar.getInstance();
                    ca1.setTime(o.getAttendingDate());

                    if (ca2.after(ca1)) {
                        //过了预约日期
                        statusEnum = OrderStatusEnum.Over;
                    }
                }
                //如果还有正在进行的订单，那就表示不可以删除
                if (statusEnum != OrderStatusEnum.Over) {
                    return result.failed("患者当前有正在进行的主诊订单");
                }

            }
        }

        //转诊
        List<TransferOrderView> transferOrderViews = transferOrderViewRepository.checkTransferOrder(userId, patientId);
        if (!Checker.isNone(transferOrderViews)) {
            Calendar ca2 = Calendar.getInstance();
            for (TransferOrderView o : transferOrderViews) {
                OrderStatusEnum statusEnum = OrderStatusEnum.Pending_Payment;

                if (o.getTransferStatus() == null) {
                    Calendar ca1 = Calendar.getInstance();

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

                    if (ca2.after(ca1)) {
                        //转出医生24h内没有收到回复
                        statusEnum = OrderStatusEnum.Over;
                    }
                } else if ((o.getTransferStatus() & TransferStatusEnum.InformPatient.getValue()) == TransferStatusEnum.InformPatient.getValue()
                        || (o.getTransferStatus() & TransferStatusEnum.Refuse.getValue()) == TransferStatusEnum.Refuse.getValue()) {
                    //无法安排床位、已通知患者
                    statusEnum = OrderStatusEnum.Over;
                }

                //如果还有正在进行的订单，那就表示不可以删除
                if (statusEnum != OrderStatusEnum.Over) {
                    return result.failed("患者当前有正在进行的转诊订单");
                }
            }
        }

        //询诊订单，不做24小时判断
        int treatmentOrderCount = treatmentOrderViewRepository.checkPresentTreatmentOrder(userId, patientId);
        if (treatmentOrderCount > 0) {
            return result.failed("患者当前有正在进行的主诊订单");
        }

        //这里最后做删除判断
        patient.setDeleted(true);
        patientRepository.save(patient);

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

    public Doctor getDoctorById(int doctorId) {
        return doctorRepository.findById(doctorId).orElse(null);
    }


    /**
     * 保存签名图片
     *
     * @param doctorId
     * @param signUrl
     * @return
     */
    public ServiceResult saveSign(int doctorId, String signUrl) {
        ServiceResult serviceResult = new ServiceResult();

        if (doctorId < 1) {
            return serviceResult.failed("医生不存在");
        }

        if (StringHelper.isNullOrWhiteSpace(signUrl)) {
            return serviceResult.failed("签名不存在");
        }

        DoctorSign sign = new DoctorSign();
        sign.setId(idGenerator.genDoctorSignId());
        sign.setDoctorId(doctorId);
        sign.setSignUrl(signUrl);
        sign.setDeleted(false);
        sign.setCreateTime(new Date());

        doctorSignRepository.save(sign);

        Map<String, Object> map = new HashMap<>();
        map.put("signId", sign.getId());
        serviceResult.setData(map);

        return serviceResult.succeed("保存成功");
    }

    /**
     * 获取医生签名列表
     *
     * @param doctorId
     * @return
     */
    public List<DoctorSign> getDoctorSignList(int doctorId) {
        return doctorSignRepository.getDoctorSignList(doctorId);
    }

    /**
     * 根据Id获取医生签名实体
     *
     * @param id
     * @return
     */
    public DoctorSign getDoctorSignById(int id) {
        return doctorSignRepository.getDoctorSignById(id);
    }

    public String getDoctorSignUrlById(int id) {
        DoctorSign ds = doctorSignRepository.getDoctorSignById(id);
        return ds == null ? "" : Checker.getStringValue(ds.getSignUrl());
    }

    /**
     * 医生出诊状态开关
     *
     * @param doctorId 医生Id
     * @param type     业务类型：1-会诊，2-转诊，3-主诊，4-咨询
     * @param status   业务状态：0-关闭 1-开启
     * @return
     */
    public ServiceResult updateScheduleStatus(int doctorId, int type, int status, int terminal) {
        ServiceResult serviceResult = new ServiceResult();

        if (doctorId < 1) {
            return serviceResult.failed("医生不存在");
        }

        if (status != 0 && status != 1) {
            return serviceResult.failed("出诊状态不正确");
        }

        if (type < 1 || type > 4) {
            return serviceResult.failed("出诊类型不正确");
        }

        Doctor doctor = doctorRepository.findById(doctorId).orElse(null);

        if (doctor == null || doctor.isDeleted()) {
            return serviceResult.failed("医生不存在");
        }

        int scheduleStatus = doctor.getScheduleStatus();

        switch (type) {
            case 1:
                if (status == 0) {
                    scheduleStatus = scheduleStatus & ~DoctorScheduleStatusEnum.Treatment.getValue();
                } else {
                    scheduleStatus = scheduleStatus | DoctorScheduleStatusEnum.Treatment.getValue();
                }
                break;
            case 2:
                if (status == 0) {
                    scheduleStatus = scheduleStatus & ~DoctorScheduleStatusEnum.Transfer.getValue();
                } else {
                    scheduleStatus = scheduleStatus | DoctorScheduleStatusEnum.Transfer.getValue();
                }
                break;
            case 3:
                if (status == 0) {
                    scheduleStatus = scheduleStatus & ~DoctorScheduleStatusEnum.Attending.getValue();
                } else {
                    scheduleStatus = scheduleStatus | DoctorScheduleStatusEnum.Attending.getValue();
                }
                break;
            case 4:
                int programeTerminal = 0;
                if (terminal == TerminalEnum.TAI_HE_INTERNET_HOSPITAL_DOCTOR_WX_OFFICIAL.getValue() || terminal == TerminalEnum.DOCTOR_MINI_PROGRAM.getValue()
                        || terminal == TerminalEnum.DoctorWxOfficial.getValue()) {
                    programeTerminal = TerminalEnum.TAI_HE_INTERNET_HOSPITAL_PATIENT_MINI_PROGRAM.getValue();
                }
                if (terminal == TerminalEnum.NFYYBYFY_DOC_WX_OFFICIAL.getValue()) {
                    programeTerminal = TerminalEnum.NFYYBYFY_WXAPP.getValue();
                }

                CommonDoctorSetting commonDoctorSetting = commonDoctorSettingRepository.findDoctorSettingByType(doctorId, programeTerminal, CommonDoctorSettingTypeEnum.Treat.getValue());
                String treat = "false";

                if (!Checker.isNone(commonDoctorSetting)) {
                    if (status == 0) {
                        commonDoctorSetting.setValue(treat);
                        commonDoctorSetting.setUpdateTime(new Date());
                        commonDoctorSettingRepository.save(commonDoctorSetting);
                    } else {
                        treat = "true";
                        commonDoctorSetting.setValue(treat);
                        commonDoctorSetting.setUpdateTime(new Date());
                        commonDoctorSettingRepository.save(commonDoctorSetting);
                    }
                }
                break;
        }
        doctor.setScheduleStatus(scheduleStatus);
        doctorRepository.save(doctor);

        return serviceResult.succeed("保存成功");
    }

    public ServiceResult updateConsultFee(int doctorId, int fee, int terminal) {
        ServiceResult serviceResult = new ServiceResult();

        if (doctorId < 1) {
            return serviceResult.failed("医生不存在");
        }

        if (fee < 0) {
            return serviceResult.failed("咨询费不能小于0");
        }

        Doctor doctor = doctorRepository.findById(doctorId).orElse(null);

        if (doctor == null || doctor.isDeleted()) {
            return serviceResult.failed("医生不存在");
        }
        int programeTerminal = 0;
        if (terminal == TerminalEnum.TAI_HE_INTERNET_HOSPITAL_DOCTOR_WX_OFFICIAL.getValue() || terminal == TerminalEnum.DOCTOR_MINI_PROGRAM.getValue()
                || terminal == TerminalEnum.DoctorWxOfficial.getValue()) {
            programeTerminal = TerminalEnum.TAI_HE_INTERNET_HOSPITAL_PATIENT_MINI_PROGRAM.getValue();
        }
        if (terminal == TerminalEnum.NFYYBYFY_DOC_WX_OFFICIAL.getValue()) {
            programeTerminal = TerminalEnum.NFYYBYFY_WXAPP.getValue();
        }

        CommonDoctorSetting commonDoctorSetting = commonDoctorSettingRepository.findDoctorSettingByType(doctorId, programeTerminal, CommonDoctorSettingTypeEnum.Amount.getValue());
        if (!Checker.isNone(commonDoctorSetting)) {
            commonDoctorSetting.setValue(String.valueOf(fee));
            commonDoctorSetting.setUpdateTime(new Date());
            commonDoctorSettingRepository.save(commonDoctorSetting);
        }

//        doctor.setConsultFee(fee);
//        doctorRepository.save(doctor);

        return serviceResult.succeed("保存成功");
    }

    /**
     * 获取医生咨询设置
     *
     * @param doctorId
     * @return
     */
    public ServiceResult getConsultSettings(int doctorId, int terminal) {
        ServiceResult serviceResult = new ServiceResult();
        Doctor doctor = doctorRepository.findById(doctorId).orElse(null);

        if (doctor == null || doctor.isDeleted()) {
            return serviceResult.failed("医生不存在");
        }

        int status = 0;
        int consultFee = 0;

        int programeTerminal = 0;
        if (terminal == TerminalEnum.TAI_HE_INTERNET_HOSPITAL_DOCTOR_WX_OFFICIAL.getValue() || terminal == TerminalEnum.DOCTOR_MINI_PROGRAM.getValue()
                || terminal == TerminalEnum.DoctorWxOfficial.getValue()) {
            programeTerminal = TerminalEnum.TAI_HE_INTERNET_HOSPITAL_PATIENT_MINI_PROGRAM.getValue();
        }
        if (terminal == TerminalEnum.NFYYBYFY_DOC_WX_OFFICIAL.getValue()) {
            programeTerminal = TerminalEnum.NFYYBYFY_WXAPP.getValue();
        }
        CommonDoctorSetting statusSet = commonDoctorSettingRepository.findDoctorSettingByType(doctorId, programeTerminal, CommonDoctorSettingTypeEnum.Treat.getValue());
        if (!Checker.isNone(statusSet) && !Checker.isNone(statusSet.getValue())) {
            status = statusSet.getValue().equals("true") ? 1 : 0;
        }

        CommonDoctorSetting fee = commonDoctorSettingRepository.findDoctorSettingByType(doctorId, programeTerminal, CommonDoctorSettingTypeEnum.Amount.getValue());
        if (!Checker.isNone(fee) && !Checker.isNone(fee.getValue())) {
            consultFee = Integer.parseInt(fee.getValue());
        } else {
            consultFee = configServiceProvider.getConsultFee();
        }

        int allowSetting = 0;
        CommonDoctorSetting allow = commonDoctorSettingRepository.findDoctorSettingByType(doctorId, terminal, CommonDoctorSettingTypeEnum.AllowSet.getValue());
        if (!Checker.isNone(allow) && !Checker.isNone(allow.getValue())) {
            allowSetting = allow.getValue().equals("true") ? 1 : 0;
        }


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

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


    /**
     * 修改医生远程会诊费用
     *
     * @param doctorId
     * @param fee
     * @return
     */
    public ServiceResult updateTreatmentFee(int doctorId, int fee) {
        ServiceResult serviceResult = new ServiceResult();

        if (doctorId < 1) {
            return serviceResult.failed("医生不存在");
        }

        if (fee < 0) {
            return serviceResult.failed("咨询费不能小于0");
        }

        Doctor doctor = doctorRepository.findById(doctorId).orElse(null);

        if (doctor == null || doctor.isDeleted()) {
            return serviceResult.failed("医生不存在");
        }

        TreatmentFeeConfig config = null;
        if (StringHelper.isNullOrWhiteSpace(doctor.getTreatmentFeeConfig())) {
            config = new TreatmentFeeConfig();
        } else {
            config = JsonSerializer.from(doctor.getTreatmentFeeConfig(), TreatmentFeeConfig.class);
        }

        config.setPackageItemFee(fee);
        doctor.setTreatmentFeeConfig(JsonSerializer.toJson(config));
        doctorRepository.save(doctor);

        return serviceResult.succeed("保存成功");
    }

    /**
     * 获取医生咨询设置
     *
     * @param doctorId
     * @return
     */
    public ServiceResult getTreatmentSettings(int doctorId) {
        ServiceResult serviceResult = new ServiceResult();
        Doctor doctor = doctorRepository.findById(doctorId).orElse(null);

        if (doctor == null || doctor.isDeleted()) {
            return serviceResult.failed("医生不存在");
        }

        int status = 0;
        int treatmentFee = 0;

        if ((doctor.getScheduleStatus() & DoctorScheduleStatusEnum.Treatment.getValue()) == DoctorScheduleStatusEnum.Treatment.getValue()) {
            status = 1;
        }

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

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

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

    /**
     * 获取医生列表
     *
     * @param pageIndex      页码
     * @param pageSize       页大小
     * @param name           医生姓名
     * @param arrHospitalId  医院Id
     * @param deptId         科室Id
     * @param scheduleStatus 医生出诊状态
     * @return
     */
    public PagedList<DoctorInfoView> getDoctorInfoList(int pageIndex, int pageSize, String name, int[] arrHospitalId,
                                                       int deptId, int scheduleStatus) {
        List<Object> paramList = new ArrayList<>();
        List<Integer> typeList = new ArrayList<>();
        String whereSql = "";

        if (!Checker.isNone(name)) {
            whereSql += " real_name like ? and ";
            paramList.add("%" + name + "%");
            typeList.add(Types.VARCHAR);
        }

        if (arrHospitalId.length > 0) {
            String hospitalSql = "";

            for (int hospitalId : arrHospitalId) {
                if (hospitalId == 0) {
                    continue;
                }

                if ("".equals(hospitalSql)) {
                    hospitalSql += " hospital_ids like ? ";
                } else {
                    hospitalSql += " or hospital_ids like ? ";
                }
                paramList.add("%," + hospitalId + ",%");
                typeList.add(Types.VARCHAR);
            }

            if (!"".equals(hospitalSql)) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }

        if (deptId != 0) {
            whereSql += " dept_ids like ? and ";
            paramList.add("%," + deptId + ",%");
            typeList.add(Types.VARCHAR);
        }

        if (scheduleStatus != 0) {
            whereSql += " (schedule_status & ?) = ? and ";
            paramList.add(scheduleStatus);
            paramList.add(scheduleStatus);
            typeList.add(Types.INTEGER);
            typeList.add(Types.INTEGER);
        }

        whereSql += " is_deleted = 0 and doctor_status = 0 ";
        int[] argTypes = typeList.stream().mapToInt(i -> i).toArray();

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

    public MedicalRecords getMedicalRecords(int recordId) {
        return medicalRecordsRepository.findById(recordId).orElse(null);
    }

    public PagedList<MedicalRecords> getMedicalRecordsDetailList(int doctorId, int patientId, int pageIndex, int pageSize) {
        String whereSql = " doctor_id = ? and patient_id = ? and type = ? and deleted = 0";
        Object[] params = new Object[]{doctorId, patientId, MedicalRecordsTypeEnum.MedicalRecords.getValue()};
        int[] argTypes = new int[]{Types.INTEGER, Types.INTEGER, Types.INTEGER};

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

    public PagedList<MedicalRecords> getMedicalRecordListByUserId(int userId, int pageIndex, int pageSize) {
        String whereSql = " user_id = ? and type = ? and deleted = 0";
        Object[] params = new Object[]{userId, MedicalRecordsTypeEnum.PatientInfo.getValue()};
        int[] argTypes = new int[]{Types.INTEGER, Types.INTEGER};

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

    public List<MedicalRecordsImage> getMedicalRecordsImageList(int doctorId, int userId, int type) {
        return medicalRecordsImageRepository.getListByUserIdAndDoctorId(userId, doctorId, type);
    }

    public List<MedicalRecordsImage> getMedicalRecordsImageList(int patientId, int type) {
        return medicalRecordsImageRepository.getList(patientId, type);
    }

    public List<MedicalRecordsImage> getMedicalRecordsImageListByRecordId(int recordId) {
        return medicalRecordsImageRepository.getListByRecordId(recordId);
    }

    public List<MedicalRecordsImage> getMedicalRecordsImageListByOrderId(int orderId) {
        return medicalRecordsImageRepository.getListByOrderId(orderId);
    }

    public List<MedicalRecordsImage> getDoctorCertificateImageList(int doctorId) {
        return medicalRecordsImageRepository.getDoctorCertificateImageList(doctorId);
    }

    public ServiceResult updateDoctorInfo(int doctorId, String name, int sex, String title, String briefIntro,
                                          int hospitalId, int deptId, String avatar, String specialty, List<String> urls) {
        ServiceResult serviceResult = new ServiceResult();
        DoctorInfoAudit audit = doctorInfoAuditRepository.getDoctorInfoAudit(doctorId);

        if (audit != null && audit.getAuditStatus() == AuditStatusEnum.Pending.getValue()) {
            audit.setName(name);
            audit.setSex(sex);
            audit.setTitle(title);
            audit.setBriefIntro(briefIntro);
            audit.setUpdateTime(new Date());
            audit.setDeleted(false);
            audit.setHospitalIds(String.format(",%d,", hospitalId));
            audit.setDeptIds(String.format(",%d,", deptId));
            audit.setAvatar(avatar);
            audit.setAuditType(0);
            audit.setSpecialty(specialty);
        } else {
            audit = new DoctorInfoAudit();
            audit.setId(idGenerator.genDoctorInfoAuditId());
            audit.setName(name);
            audit.setSex(sex);
            audit.setTitle(title);
            audit.setBriefIntro(briefIntro);
            audit.setCreateTime(new Date());
            audit.setUpdateTime(new Date());
            audit.setDeleted(false);
            audit.setHospitalIds(String.format(",%d,", hospitalId));
            audit.setDeptIds(String.format(",%d,", deptId));
            audit.setAuditStatus(AuditStatusEnum.Pending.getValue());
            audit.setAuditTime(null);
            audit.setAuditRemark(null);
            audit.setAvatar(avatar);
            audit.setSpecialty(specialty);
            audit.setAuditType(0);
            audit.setDoctorId(doctorId);
        }

        doctorInfoAuditRepository.save(audit);

        if (urls != null && urls.size() > 0) {
            List<MedicalRecordsImage> lst = new LinkedList<>();
            List<String> existedImages = new LinkedList<>();    //已存在的病历图片链接
            List<MedicalRecordsImage> images = medicalRecordsImageRepository.getDoctorPendingCertificateImageList(doctorId, MedicalRecordsImageTypeEnum.DoctorCertificate.getValue());

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

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

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

            for (String url : urls) {
                //本次新增的图片链接
                if (!existedImages.contains(url)) {
                    MedicalRecordsImage image = new MedicalRecordsImage();
                    image.setId(idGenerator.genMedicalRecordsImageId());
                    image.setDoctorId(doctorId);
                    image.setImageUrl(url);
                    image.setStatus(0);
                    image.setType(MedicalRecordsImageTypeEnum.DoctorCertificate.getValue());
                    image.setUserId(null);
                    image.setOrderId(null);
                    image.setMedicalRecordsId(null);
                    image.setPatientId(0);
                    image.setCreateTime(new Date());
                    image.setDeleted(false);
                    image.setUpdateTime(null);

                    lst.add(image);
                }
            }

            medicalRecordsImageRepository.saveAll(lst);
        } else {
            //TODO: 删除全部审核中的图片
        }

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

    public DoctorInfoAudit getDoctorInfoAudit(int doctorId) {
        return doctorInfoAuditRepository.getDoctorInfoAudit(doctorId);
    }

    public DoctorInfoAudit getCertificationAudit(int doctorId) {
        return doctorInfoAuditRepository.getCertificationAudit(doctorId);
    }

    public List<DoctorInfoView> getFriendList(int doctorId, int[] arrHospitalId, int deptId, String name) {
        List<DoctorInfoView> lst = new LinkedList<>();

        String sql = "select union_doctor_id from union_doctor " +
                "where doctor_id = ? and is_deleted = 0 and status = 1 " +
                "union " +
                "select doctor_id from union_doctor " +
                "where union_doctor_id= ? and is_deleted = 0 and status = 1;";
        Object[] args = new Object[]{doctorId, doctorId};
        int[] argTypes = new int[]{Types.INTEGER, Types.INTEGER};
        List<Integer> arrDoctorId = jdbcTemplate.queryForList(sql, args, argTypes, Integer.class);

        if (arrDoctorId != null && arrDoctorId.size() > 0) {
            //被禁用医院Id列表
            String idSql = "select id from hospital where status = 1 or is_deleted = 1;";
            List<Integer> hospitalIds = jdbcTemplate.queryForList(idSql, Integer.class);

            for (Integer id : arrDoctorId) {
                DoctorInfoView view = doctorInfoViewRepository.findById(id).orElse(null);

                //医生为禁用状态时，也不出现在app列表中
                if (view == null || view.getDoctorStatus() == 1) {
                    continue;
                }

                if (deptId > 0 && !view.getDeptIds().contains("," + deptId + ",")) {
                    continue;
                }

                if (!"".equals(name) && (view.getRealName() == null || !view.getRealName().contains(name))) {
                    continue;
                }

                //过滤被禁用医院的医生（医院下有医生，若后台设置这家医院为禁用，这个医院下的所有医生也不显示在app列表中）
                if (hospitalIds != null && hospitalIds.size() > 0 && view.getHospitalIds() != null &&
                        hospitalIds.stream().anyMatch(p -> view.getHospitalIds().equals("," + p + ","))) {
                    continue;
                }

                for (int hospitalId : arrHospitalId) {
                    if (hospitalId == 0 || (view.getHospitalIds() != null && view.getHospitalIds().contains("," + hospitalId + ","))) {
                        lst.add(view);
                        break;
                    }
                }
            }
        }

        return lst;
    }

    /**
     * 搜索患者
     *
     * @param patientName
     * @return
     */
    public PagedList<Patient> searchPatientByPatientName(String patientName, int doctorId, int pageIndex, int pageSize) {

        if (Checker.isNone(pageIndex) || pageIndex == 0) {
            pageIndex = 1;
        }
        if (Checker.isNone(pageSize) || pageSize == 0) {
            pageSize = 20;
        }

        String whereSql = "";
        Object[] params = null;
        int[] argTypes = null;
        //如果患者姓名为空，那就去查该医生添加的最近的20个患者
        if (!Checker.isNone(patientName)) {
            whereSql = " real_name like ? and  doctor_id = ? ";
            params = new Object[]{"%" + patientName + "%", doctorId};
            argTypes = new int[]{Types.VARCHAR, Types.INTEGER};
        } else {
            whereSql = " doctor_id = ? ";
            params = new Object[]{doctorId};
            argTypes = new int[]{Types.INTEGER};
        }
        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "create_time desc",
                Patient.class, params, argTypes);
    }

    /**
     * 添加或修改病历模版
     *
     * @param moduleId
     * @param doctorId
     * @param moduleName
     * @param context
     * @param type
     * @return
     */
    public Result addOrUpdateMedicalModule(int moduleId, int doctorId, String moduleName, String context, int type) {


        MedicalModule module = null;
        // 当 moduleId <= 0 时表示添加模版
        if (moduleId <= 0) {

            //判断模版名称有没有重复
//            int count = medicalModuleRepository.checkModuleName(moduleName, type, doctorId);
//            if (count > 0)
//                return Result.newBuilder().setCode(ResultCode.APP_ERROR).setInfo("模版名称不能重复").build();

            module = new MedicalModule();
            moduleId = idGenerator.genMedicalModuleId();
            module.setId(moduleId);
            module.setCreateTime(new Date());
        } else {

            //判断模版名称有没有重复
//            int count = medicalModuleRepository.checkModuleName(moduleId, moduleName, type, doctorId);
//            if (count > 0)
//                return Result.newBuilder().setCode(ResultCode.APP_ERROR).setInfo("模版名称不能重复").build();

            module = medicalModuleRepository.findById(moduleId).orElse(null);
            if (Checker.isNone(module))
                return Result.newBuilder().setCode(ResultCode.APP_ERROR).setInfo("moduleID参数错误").build();
        }

        module.setContext(context);
        module.setDoctorId(doctorId);
        module.setUpdateTime(new Date());
        module.setModuleName(moduleName);
        module.setType(type);
        medicalModuleRepository.save(module);
        return Result.newBuilder().setCode(ResultCode.SUCCEED).setInfo("处理成功").build();
    }


    /**
     * 添加患者病历
     * <p>
     * int32 patientId = 1;
     * string patientName = 2;
     * string patientSex = 3;
     * int32 patientAge = 4;
     * string patientMobile = 5;
     * string chiefComplaint = 6;                           //主诉
     * string presentHistory = 7;                          //现病史
     * string pastHistory = 8;                             //既往史
     * string allergicHistory = 9;                             //过敏史
     * string personalHistory = 10;                             //个人史
     * string phyExam = 11;                                        //体格检查
     * string bodyTemperature = 12;                             //病人体温
     * string specialCondition = 13;                             //专科情况
     * string accessoryExamination = 14;                             //辅助检查
     * string disagenose = 15;                              //诊断
     * int32 single = 16;                             //单病种，1-是，0-否
     * string diseaseTime = 17;                             //发病时间
     * int32 disposition = 18;                             //病人去向
     * int32 treatmentCase = 19;                             //抢救病人
     * int32 treatmentStatus = 20;                             //是否抢救成功
     * string diseaseEvaluation = 21;                             //病情评估
     * string icdCode = 22;                             //ICD编码
     * string management = 23;                             //处置
     *
     * @return
     */
    public ServiceResult addMedicalRecord(int patientId, String patientName,
                                          int patientSex, int patientAge, String patientMobile, String chiefComplaint,
                                          String presentHistory, String pastHistory, String allergicHistory, String personalHistory,
                                          String phyExam, double bodyTemperature, String specialCondition, String accessoryExamination,
                                          String diagnosis, int single, long diseaseTime, int disposition,
                                          int treatmentCase, int treatmentStatus, String diseaseEvaluation, String icdCode,
                                          String management, int doctorId, String remark, String idCardNo, int userId) {
        ServiceResult result = new ServiceResult();

        Doctor doctor = doctorRepository.findById(doctorId).orElse(null);
        if (Checker.isNone(doctor)) {
            return result.failed("参数doctorId错误");
        }
        User user = userRepository.findById(doctorId).orElse(null);
        if (Checker.isNone(user)) {
            return result.failed("参数doctorId错误");
        }

//        int userId = 0;

        // patientId > 0 时表示修改，否则为新增
        Patient patient;
        if (patientId > 0) {
            patient = patientRepository.findById(patientId).orElse(null);
            if (Checker.isNone(patient)) {
                return result.failed("参数patientId错误");
            }

            //如果该医生下刚好存在另一位姓名和手机号一样的患者，那就不能添加成功
            int count = patientRepository.checkAdded(doctorId, patientMobile, patientName, patientId);
            if (count > 0) {
                return result.failed("该患者信息和其他患者出现冲突");
            }

            userId = patient.getUserId();
            //当修改信息时，患者姓名和手机都发生改变了，那就需要新增患者
            if ((!patient.getRealName().equals(patientName)) && (!patient.getMobile().equals(patientMobile))) {
                patient = new Patient();
                patientId = idGenerator.generatePatientId();
                patient.setUserId(0);
                patient.setRemark("");
                patient.setCreateTime(new Date());
                patient.setId(patientId);
            }

        } else {

            //如果该医生下刚好存在另一位姓名和手机号一样的患者，那就不能添加成功
            int count = patientRepository.checkAdded(doctorId, patientMobile, patientName);
            if (count > 0) {
                return result.failed("该患者信息和其他患者出现冲突");
            }

            patient = new Patient();
            patientId = idGenerator.generatePatientId();
            patient.setUserId(0);
            patient.setRemark("");
            patient.setCreateTime(new Date());
            patient.setId(patientId);
        }

        patient.setDeleted(false);
        patient.setAge(patientAge);
        patient.setChiefComplaint(chiefComplaint);
        patient.setDiagnosis(diagnosis);

        patient.setSex(patientSex);
        patient.setUpdateTime(new Date());
        patient.setAllergicHistory(allergicHistory);
        patient.setDoctorId(doctorId);
        patient.setMobile(patientMobile);
        patient.setRealName(patientName);
        patientRepository.save(patient);

        //新增病历
        MedicalRecords record = new MedicalRecords();
        int recordId = idGenerator.genMedicalRecordsId();
        record.setChiefComplaint(chiefComplaint);
        record.setAge(patientAge);
        record.setCreateTime(new Date());
        record.setDeleted(false);
        record.setDoctorId(doctorId);
        record.setMobile(patientMobile);
        record.setSex(patientSex);
        record.setType(MedicalRecordsTypeEnum.MedicalRecords.getValue());
        record.setUpdateTime(new Date());
        record.setId(recordId);
        record.setUserId(userId);
        record.setDiagnosis(diagnosis);
        record.setPatientName(patientName);
        record.setPatientId(patientId);
        record.setRemark(remark);
        record.setTypeName("");
        record.setAdmTime("");
        record.setAdvice("");
        record.setClinicCode("");
        record.setIdNo(idCardNo);
        Map<Integer, Department> deptMap = hospitalService.getDepartmentMap();

        String[] deptIds = doctor.getDeptIds().split(",");
        int dd = 0;
        if (!Checker.isNone(deptIds)) {
            for (String deptId : deptIds) {
                if (!Checker.isNone(deptId) && dd == 0) {
                    Department department = deptMap.get(Checker.parseInt(deptId));
                    if (!Checker.isNone(department)) {
                        dd++;
                        record.setDeptName(department.getName());  //设置科室名称,如果有多个科室，取第一个
                    }
                }
            }
        }
        if (dd == 0) record.setDeptName("");

        String[] hospitalIds = doctor.getHospitalIds().split(",");
        int hh = 0;
        Map<Integer, Hospital> hospitalMap = hospitalService.getHospitalMap();
        if (!Checker.isNone(hospitalIds)) {
            for (String hospitalId : hospitalIds) {
                if (!Checker.isNone(hospitalId) && hh == 0) {
                    Hospital hospital = hospitalMap.get(Checker.parseInt(hospitalId));
                    if (!Checker.isNone(hospital)) {
                        hh++;
                        record.setHospitalId(hospital.getId()); //设置医院ID
                        record.setHospitalName(hospital.getName()); //设置医院名称，如果存在多个科室，取第一个
                    }
                }
            }
        }

        if (hh == 0) {
            record.setHospitalId(0); //之所以这样做是因为刚发布的时候，缓存里面是没有医院和部门数据的
            record.setHospitalName("");
        }

        MedicalCard card = medicalCardRepository.getCardByUserIdAndPatientName(patient.getUserId(), patientName);
        if (!Checker.isNone(card)) {
            record.setMedicalCardId(card.getId());
        } else {
            record.setMedicalCardId(0);
        }

        if (diseaseTime != 0L) {
            record.setDiseaseTime(new Date(diseaseTime));
        }

        record.setDoctorName(user.getRealname());
        record.setDoctorTitle(doctor.getTitle());
        record.setPhyExam(phyExam);
        record.setSuggestion("");
        record.setAllergicHistory(allergicHistory);

        if (treatmentStatus != -1)
            record.setTreatmentStatus(treatmentStatus);

        record.setAccessoryExamination(accessoryExamination);

        if (!Checker.isNone(bodyTemperature))
            record.setBodyTemperature(bodyTemperature);
        record.setDiseaseEvaluation(diseaseEvaluation);

        if (disposition != -1)
            record.setDisposition(disposition);

        record.setIcdCode(icdCode);
        record.setManagement(management);
        record.setPastHistory(pastHistory);
        record.setPersonalHistory(personalHistory);
        record.setPresentHistory(presentHistory);

        if (single != -1)
            record.setSingle(single);

        record.setSpecialCondition(specialCondition);

        if (treatmentCase != -1)
            record.setTreatmentCase(treatmentCase);

        medicalRecordsRepository.save(record);

        Map<String, Object> map = new HashMap();
        map.put("userId", userId);
        map.put("recordId", recordId);
        result.setData(map);
        return result.succeed("添加成功");


    }


    /**
     * 根据医生Id获取医生签名实体
     *
     * @param doctorId
     * @return
     */
    public DoctorSign getDoctorSignByDoctorId(int doctorId) {
        return doctorSignRepository.getDoctorSignByDoctorId(doctorId);
    }


    /**
     * 得到医生最新一个月的账户明细列表
     *
     * @param userId
     * @return
     */
    public List<AccountDetail> getLastMonthTransactionRecord(int userId) {
        String startTime = new SimpleDateFormat("yyyy-MM-00 00:00:00").format(new Date());
        return accountDetailRepository.getLastMonthTransactionRecord(userId, startTime);
    }

    /**
     * 分页获取时间段内的交易记录
     *
     * @param userId
     * @param start
     * @param end
     * @param pageSize
     * @param pageIndex
     * @return
     */
    public PagedList<AccountDetail> getTransactionRecord(int userId, String start, String end, int pageSize, int pageIndex) {
        // 2023-10-13 医生提现记录优化hoftix_v1.1.3，过滤掉用户 2023-05-06 17:51:37 之前的提现记录
        String whereSql = " user_id = ? and create_time >= ? and create_time < ? and deleted = ? and id not in (select a.id from ywt_center.account_detail a where a.user_id = ? and a.type = 2 and a.`create_time` < '2023-05-06 17:51:37' )";
        Object[] params = new Object[]{userId, start, end, 0, userId};
        int[] argTypes = new int[]{Types.INTEGER, Types.DATE, Types.DATE, Types.INTEGER, Types.INTEGER};
        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql,
                "id desc", AccountDetail.class, params, argTypes);
    }

    /**
     * 获取时间段内所有的交易记录
     *
     * @param userId
     * @param start
     * @param end
     * @return
     */
    public List<AccountDetail> getTransactionRecord(int userId, String start, String end) {
        return accountDetailRepository.getTransactionRecordByTimePeriod(userId, start, end);
    }

    /**
     * 得到所有的快捷语列表
     *
     * @return
     */
    public List<QuickLanguage> getAllQuickLanguageList() {
        return quickLanguageRepository.getAllList();
    }

    /**
     * 删除医生排班表
     *
     * @param doctorId
     */
    public void delDoctorScheduleByDoctorId(int doctorId) {
        List<DoctorSchedule> doctorSchedules = doctorScheduleRepository.getDoctorScheduleByDoctorId(doctorId);
        if (doctorSchedules != null && doctorSchedules.size() > 0) {
            doctorSchedules.forEach(p -> {
                p.setDeleted(true);
                doctorScheduleRepository.save(p);
            });
        }
    }

    /**
     * 保存医生排班信息
     *
     * @param doctorId
     * @param clinicTime
     * @param morning
     * @param afternoon
     * @param night
     * @param province
     * @param city
     * @param area
     * @param provinceId
     * @param cityId
     * @param areaId
     * @param address
     * @param remark
     * @param amount
     * @param configId
     * @param type
     */
    public ServiceResult saveDoctorSchedule(int doctorId, long clinicTime, int morning, int afternoon, int night,
                                            String province, String city, String area, int provinceId, int cityId, int areaId, String address,
                                            String remark, int amount, int configId, int type) {
        ServiceResult serviceResult = new ServiceResult();
        //判断现在的type和之前的type是否相同,如果不相同，那么就先删除之前的
        List<DoctorSchedule> doctorScheduleList = doctorScheduleRepository.getDoctorScheduleByDoctorId(doctorId, 3 - type);
        int errCount = 0;
        if (doctorScheduleList != null && doctorScheduleList.size() > 0) {
            //先判断之前的订单是否有预约的
            for (DoctorSchedule d : doctorScheduleList) {
                int count = additionalRegistrationRepository.checkNumByScheduleId(d.getId());
                if (count > 0) {
                    errCount = 1;
                    break;
                }
            }
            //如果都没预约，那么则进行删除之前都
            if (errCount == 0) {
                for (DoctorSchedule d : doctorScheduleList) {
                    cancleDoctorSchedule(d);
                }
            } else {
                return serviceResult.failed("已存在患者预约信息，不允许修改当前页面，可停诊后再操作");
            }

        }

        //

        //先保存schedule_config表信息
        ScheduleConfig config = null;
        if (configId == 0) {
            config = new ScheduleConfig();
            configId = idGenerator.genScheduleConfigId();
            config.setCreateTime(new Date());
            config.setDeleted(false);
            config.setDoctorId(doctorId);
            config.setId(configId);
        } else {
            config = scheduleConfigRepository.findById(configId).orElse(null);
            if (Checker.isNone(config)) {
                return serviceResult.failed("参数错误");
            }
            // 这里新增一个判断，如果有数据改变，那就新增
            if (!(config.getAmount() == amount
                    && config.getAddress().equals(address.trim())
                    && config.getArea().equals(area)
                    && config.getAreaId() == areaId
                    && config.getCityId() == cityId
                    && config.getCity().equals(city)
                    && config.getProvinceId() == provinceId
                    && config.getProvince().equals(province)
                    && config.getRemark().equals(remark.trim())
            )) {
                config = new ScheduleConfig();
                configId = idGenerator.genScheduleConfigId();
                config.setCreateTime(new Date());
                config.setDeleted(false);
                config.setDoctorId(doctorId);
                config.setId(configId);
            }
        }
        config.setAddress(address.trim());
        config.setAmount(amount);
        config.setArea(area);
        config.setAreaId(areaId);
        config.setCity(city);
        config.setCityId(cityId);
        config.setProvince(province);
        config.setProvinceId(provinceId);
        config.setRemark(remark.trim());
        config.setUpdateTime(new Date());

        scheduleConfigRepository.save(config);

        //验证是否是新地址
        int count = addressRepository.checkAddress(doctorId, provinceId, cityId, areaId, address.trim());
        if (count == 0) {        // 此时表示是新增的数据
            Address addr = new Address();
            int addrId = idGenerator.genAddressId();
            addr.setType(1);
            addr.setUpdateTime(new Date());
            addr.setStatus(0);  // status   1-默认地址，0-非默认
            addr.setDeleted(false);
            addr.setAddress(address.trim());
            addr.setAppellation("");
            addr.setArea(area);
            addr.setAreaId(areaId);
            addr.setCity(city);
            addr.setCityId(cityId);
            addr.setContact("");
            addr.setCreateTime(new Date());
            addr.setId(addrId);
            addr.setUserId(doctorId);
            addr.setProvince(province);
            addr.setProvinceId(provinceId);
            addr.setMobile("");
            addressRepository.save(addr);
        }

        //保存doctor_schedule表信息
        String date = DateUtil.convertTimestampToDateString(clinicTime, "yyyy-MM-dd 00:00:00");
        DoctorSchedule schedule = doctorScheduleRepository.findSchedule(doctorId, date, morning, afternoon, night);

        int scheduleId = 0;
        if (!Checker.isNone(schedule)) {
            scheduleId = schedule.getId();
        } else {
            schedule = new DoctorSchedule();
            scheduleId = idGenerator.genDoctorScheduleId();
        }

        schedule.setId(scheduleId);
        schedule.setDeleted(false);
        schedule.setAfternoon(afternoon == 1);
        schedule.setMorning(morning == 1);
        schedule.setNight(night == 1);
        schedule.setClinicTime(DateUtil.stringToDate(date));
        schedule.setConfigId(configId);
        schedule.setRemark("");
        schedule.setCreateTime(new Date());
        schedule.setDoctorId(doctorId);
        schedule.setType(type);
        schedule.setUpdateTime(new Date());

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

    ;

    /**
     * 设置停诊
     *
     * @param doctorSchedule
     */
    private void cancleDoctorSchedule(DoctorSchedule doctorSchedule) {
        doctorSchedule.setUpdateTime(new Date());
        if (doctorSchedule.getMorning()) {
            doctorSchedule.setMorning(false);
        }
        if (doctorSchedule.getAfternoon()) {
            doctorSchedule.setAfternoon(false);
        }
        if (doctorSchedule.getNight()) {
            doctorSchedule.setNight(false);
        }
        doctorSchedule.setDeleted(true);
        doctorScheduleRepository.save(doctorSchedule);

        int count = additionalRegistrationRepository.checkNumByScheduleId(doctorSchedule.getId());
        if (count > 0) {
            List<AdditionalRegistration> addLst = additionalRegistrationRepository.findByScheduleId(doctorSchedule.getId());
            for (AdditionalRegistration a : addLst) {

                int status = -1;
                Map<String, Integer> map = orderService.getAdditionalRegistrationStatusName(a);
                for (Map.Entry<String, Integer> me : map.entrySet()) {
                    //根据键值对对象获得键和值
                    status = me.getValue();
                    if (status == 6) { //6-待接诊
                        a.setStatus(a.getStatus() & AdditionalRegistrationStatusEnum.Refuse.getValue());
                        a.setUpdateTime(new Date());
                        additionalRegistrationRepository.save(a);

                        //这里发送通知短信

                    }
                }

            }
        }
    }

    /**
     * 根据医生ID得到医生所有的排班信息
     *
     * @param doctorId
     * @return
     */
    public List<DoctorSchedule> getDoctorScheduleByDoctorId(int doctorId) {
        String date = DateUtil.convertToString(new Date(), "yyyy-MM-dd 00:00:00");
        return doctorScheduleRepository.getDoctorScheduleByDoctorId(doctorId, date);
    }

    /**
     * 根据配置ID得到配置对象
     *
     * @param configId
     * @return
     */
    public ScheduleConfig getScheduleConfigById(int configId) {
        return scheduleConfigRepository.findById(configId).orElse(null);
    }


    /**
     * 根据医生ID得到医生最近一周的排班信息
     *
     * @param doctorId
     * @return
     */
    public List<DoctorSchedule> getLatestWeekSchedule(int doctorId) {
        String startDate = DateUtil.convertToString(new Date(), "yyyy-MM-dd 00:00:00");
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, 6);
        String endDate = DateUtil.convertToString(calendar.getTime(), "yyyy-MM-dd 00:00:00");
        return doctorScheduleRepository.getLatestSchedule(doctorId, startDate, endDate);
    }

    /**
     * 根据医生ID得到医生最近时间的排班信息
     *
     * @param doctorId
     * @return
     */
    public List<DoctorSchedule> getLatestSchedule(int doctorId, String date) {
        String startDate = DateUtil.convertToString(new Date(), "yyyy-MM-dd 00:00:00");
        return doctorScheduleRepository.getLatestSchedule(doctorId, startDate, date);
    }

    /**
     * 设置停诊排班
     *
     * @param doctorId
     * @param scheduleIds
     * @return
     */
    public ServiceResult setCancelSchedule(int doctorId, String scheduleIds) {
        ServiceResult result = new ServiceResult();
        if (!Checker.isNone(scheduleIds)) {
            //  拆分
            String[] scheduleIdStr = scheduleIds.split(",");
            //  判断是否为空
            if (!Checker.isNone(scheduleIdStr)) {

                //  遍历
                for (String str : scheduleIdStr) {
                    //  判断是否唯恐
                    if (!Checker.isNone(str)) {

                        int scheduleId = Integer.parseInt(str);
                        DoctorSchedule doctorSchedule = doctorScheduleRepository.findById(scheduleId).orElse(null);
                        //  判断是否为空
                        if (!Checker.isNone(doctorSchedule) && doctorSchedule.getDoctorId() == doctorId) {
                            doctorSchedule.setUpdateTime(new Date());
//                            if (doctorSchedule.getMorning()) {
//                                doctorSchedule.setMorning( false );
//                            }
//                            if (doctorSchedule.getAfternoon()){
//                                doctorSchedule.setAfternoon( false );
//                            }
//                            if (doctorSchedule.getNight()){
//                                doctorSchedule.setNight( false );
//                            }
                            doctorSchedule.setDeleted(true);
                            doctorScheduleRepository.save(doctorSchedule);

                            int count = additionalRegistrationRepository.checkNumByScheduleId(scheduleId);
                            if (count > 0) {
                                List<AdditionalRegistration> addLst = additionalRegistrationRepository.findByScheduleId(scheduleId);
                                for (AdditionalRegistration a : addLst) {

                                    int status = -1;
                                    Map<String, Integer> map = orderService.getAdditionalRegistrationStatusName(a);
                                    for (Map.Entry<String, Integer> me : map.entrySet()) {
                                        //根据键值对对象获得键和值
                                        status = me.getValue();
                                        if (status == 6) { //6-待接诊
                                            a.setStatus(a.getStatus() | AdditionalRegistrationStatusEnum.Refuse.getValue());
                                            a.setUpdateTime(new Date());
                                            additionalRegistrationRepository.save(a);

                                            //这里发送通知短信

                                        }
                                    }

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

        }


        return result.failed("参数错误");
    }

    ;

    /**
     * 根据问诊排班ID得到对象
     *
     * @param scheduleId
     * @return
     */
    public DoctorSchedule getDoctorScheduleById(int scheduleId) {
        return doctorScheduleRepository.findById(scheduleId).orElse(null);
    }

    /**
     * 根据医生ID得到最近的排班配置信息
     *
     * @param doctorId
     * @return
     */
    public ScheduleConfig getLatestScheduleConfigByDoctorId(int doctorId) {
        return scheduleConfigRepository.getLatestScheduleConfigByDoctorId(doctorId);
    }

    /**
     * 判断当前排班的预约情况
     *
     * @param docotId
     * @return
     */
    public int checkScheduleStatus(int docotId) {
        int count = 0;
        String date = DateUtil.convertToString(new Date(), "yyyy-MM-dd 00:00:00");
        List<DoctorSchedule> doctorScheduleList = doctorScheduleRepository.getDoctorScheduleByDoctorId(docotId, date);

        if (doctorScheduleList != null && doctorScheduleList.size() > 0) {

            for (DoctorSchedule ds : doctorScheduleList) {

                //查看预约情况
                int scheduleCount = additionalRegistrationRepository.checkNumByScheduleId(ds.getId());
                if (scheduleCount > 0) {
                    count = 1;
                    break;
                }
            }
        }
        return count;
    }


    /**
     * 获取有加诊排班的医生列表
     *
     * @param hospitalIdArr
     * @param deptId
     * @param name
     * @return
     */
    public PagedList<ScheduleDoctorInfoView> getScheduleDoctorList(int[] hospitalIdArr, int deptId, String name, int pageIndex, int pageSize) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " 1=1 ";
        if (!StringHelper.isNullOrEmpty(name.trim())) {
            whereSql += " and doctor_name like ? ";
            paramList.add("%" + name.trim() + "%");
        }

        if (hospitalIdArr.length > 0) {
            if (hospitalIdArr[0] != 0 && hospitalIdArr[0] != -1) {
                whereSql += " and ( ";
                for (int i = 0, j = hospitalIdArr.length; i < j; i++) {
                    if (i == 0) {
                        whereSql += " hospital_ids like ? ";
                        paramList.add("%," + hospitalIdArr[i] + ",%");
                    } else {
                        whereSql += " or hospital_ids like ? ";
                        paramList.add("%," + hospitalIdArr[i] + ",%");
                    }
                }
                whereSql += " ) ";
            }
        }

        if (deptId > 0) {
            whereSql += " and dept_ids like ? ";
            paramList.add("%," + deptId + ",%");
        }

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

    /**
     * 医生端绑定信息
     * create by daiyihua
     *
     * @param unionId
     * @param mobile
     * @return
     */
    public ServiceResult doctorBindWxAppMobile(String unionId, String mobile) {
        ServiceResult serviceResult = new ServiceResult();
        SnsUserInfo snsUserInfo = snsUserInfoRepository.getSnsUserInfoByUnionId(unionId, TerminalEnum.DoctorWxOfficial.getValue());

        if (snsUserInfo == null) {
            return serviceResult.failed("unionId不存在");
        }

        User user = userRepository.getUserByMobile(mobile);

        if (user == null) {
            //如果不存在，那添加用户（此时为用户，只有等审核通过的时候才将患者的角色变为医生）

            user = new User();

            int userId = idGenerator.generateUserId();
            user.setId(userId);

            user.setUsername(((new Date()).getTime() + ""));
            user.setRealname(null);
            user.setIdcertificatetype(1);
            user.setIdcertificateno("");
            user.setMobile(mobile);
            user.setSex(SexEnum.Unknown.getValue());
            user.setAge(0);
            user.setAvatar(Constants.DOCTOR_AVATAR_URL);
            user.setBirthday("");
            user.setPassword("");
            user.setSalt("");
            user.setCreatetime(new Date());
            user.setRegister_ip("");
            user.setProvince("");
            user.setCity("");
            user.setArea("");
            user.setStatus(0);
            user.setDeleted(false);
            user.setUsertype(1);

            userRepository.save(user);

            String updateSql = String.format("update sns_user_info set user_id = %d, update_time = now() where union_id = '%s' and terminal = %d;", userId, unionId, TerminalEnum.DoctorWxOfficial.getValue());
            jdbcTemplate.execute(updateSql);

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

            serviceResult.setData(map);
            return serviceResult.succeed("关联成功");
        } else if (user.getUsertype() == 2) {
            Doctor doctor = doctorRepository.findById(user.getId()).orElse(null);
            if (doctor != null && doctor.getStatus() == 1) {
                return serviceResult.failed("该用户不存在");
            }
        }
        /*这里的经销商可以绑定医生工作站

        else if (user.getUsertype() == 4){
            return serviceResult.failed("经销商用户不能认证");
        }
        */

        if (user.getId().equals(snsUserInfo.getUserId())) {
//            return serviceResult.failed("该手机号与当前绑定的手机号相同");
            Map<String, Object> map = new HashMap<>();
            map.put("userId", user.getId());

            serviceResult.setData(map);
            return serviceResult.succeed("关联成功");
        }

        int userId = user.getId();
        String updateSql = String.format("update sns_user_info set user_id = %d, update_time = now() where union_id = '%s' and terminal = %d;", userId, unionId, TerminalEnum.DoctorWxOfficial.getValue());
        jdbcTemplate.execute(updateSql);

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

        serviceResult.setData(map);
        return serviceResult.succeed("关联成功");
    }

    /**
     * 医生端绑定信息
     *
     * @param openId
     * @param mobile
     * @param terminal
     * @return
     */
    public ServiceResult doctorBindWx(String openId, String mobile, String ip, int terminal) {
        ServiceResult serviceResult = new ServiceResult();
        SnsUserInfo snsUserInfo = snsUserInfoRepository.getSnsUserInfoByOpenId(openId, terminal);
        if (snsUserInfo == null) {
            return serviceResult.failed("社交账户信息不存在");
        }

        User user = userRepository.getUserByMobile(mobile);
        if (user == null) {
            //如果不存在，那添加用户（此时为用户，只有等审核通过的时候才将患者的角色变为医生）
            user = new User();
            int userId = idGenerator.generateUserId();
            user.setId(userId);
            user.setUsername(((new Date()).getTime() + ""));
            user.setRealname(null);
            user.setIdcertificatetype(1);
            user.setIdcertificateno("");
            user.setMobile(mobile);
            user.setSex(SexEnum.Unknown.getValue());
            user.setAge(0);
            user.setAvatar(Constants.DOCTOR_AVATAR_URL);
            user.setBirthday("");
            user.setPassword("");
            user.setSalt("");
            user.setCreatetime(new Date());
            user.setRegister_ip(ip);
            user.setProvince("");
            user.setCity("");
            user.setArea("");
            user.setStatus(0);
            user.setDeleted(false);
            user.setUsertype(1);
            user.setTerminal(terminal);
            userRepository.save(user);
        } else {
            if (user.getUsertype() == 2) {
                Doctor doctor = doctorRepository.findById(user.getId()).orElse(null);
                if (doctor != null && doctor.getStatus() == 1) {
                    return serviceResult.failed("该用户不存在");
                }
            }

            //判断手机号是否被同一终端其它用户绑定过
            String sql = String.format(
                    "select count(0) from sns_user_info where user_id = %d and terminal = %d and open_id != '%s'"
                    , user.getId(), terminal, openId);
            int count = jdbcTemplate.queryForObject(sql, Integer.class);
            if (count > 0) {
                return serviceResult.failed("该手机号已被其他用户使用");
            }
        }
        int userId = user.getId();
        String updateSql = String.format(
                "update sns_user_info set user_id = %d, update_time = now(), deleted = 0 " +
                        "where open_id = '%s' and terminal = %d;", userId, openId, terminal);
        jdbcTemplate.execute(updateSql);

        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        serviceResult.setData(map);
        return serviceResult.succeed("关联成功");
    }

    /**
     * 保存排班
     *
     * @param doctorId
     * @return
     */
    public DoctorInfoView getDoctorInfoViewByDoctorId(int doctorId) {
        return doctorInfoViewRepository.findById(doctorId).orElse(null);
    }

    public ServiceResult saveDoctorSchedule(int doctorId, List<com.ywt.gapi.doctor.DoctorSchedule> doctorScheduleList) {
        ServiceResult result = new ServiceResult();
        if (!Checker.isNone(doctorScheduleList)) {

            //判断现在的type和之前的type是否相同,如果不相同，那么就先删除之前的 (type 取第一个就好)
            List<DoctorSchedule> dSList = doctorScheduleRepository.getDoctorScheduleByDoctorId(doctorId, 3 - doctorScheduleList.get(0).getType());
            if (dSList != null && dSList.size() > 0) {
                for (DoctorSchedule ds : dSList) {
                    cancleDoctorSchedule(ds);
                }
            }

            //判断修改的有没有是预约的
            for (com.ywt.gapi.doctor.DoctorSchedule ds : doctorScheduleList) {
                //先删除掉之前
                if (ds.getScheduleId() != 0) {
                    // 判断之前有没有预约单
                    int count = additionalRegistrationRepository.checkNumByScheduleId(ds.getScheduleId());
                    if (count > 0) {
                        return result.failed("已存在患者预约信息，不允许修改当前页面，可停诊后再操作");
                    }
                }
            }

            //这里进行添加信息
            for (com.ywt.gapi.doctor.DoctorSchedule ds : doctorScheduleList) {

                //先保存schedule_config表信息
                ScheduleConfig config = null;
                int configId = ds.getConfigId();
                if (configId == 0) {
                    config = new ScheduleConfig();
                    configId = idGenerator.genScheduleConfigId();
                    config.setCreateTime(new Date());
                    config.setDeleted(false);
                    config.setDoctorId(doctorId);
                    config.setId(configId);
                } else {
                    config = scheduleConfigRepository.findById(configId).orElse(null);
                    if (Checker.isNone(config)) {
                        return result.failed("参数错误");
                    }
                    // 这里新增一个判断，如果有数据改变，那就新增
                    if (!(config.getAmount() == ds.getAmount()
                            && config.getAddress().equals(ds.getAddress().trim())
                            && config.getArea().equals(ds.getArea())
                            && config.getAreaId() == ds.getAreaId()
                            && config.getCityId() == ds.getCityId()
                            && config.getCity().equals(ds.getCity())
                            && config.getProvinceId() == ds.getProvinceId()
                            && config.getProvince().equals(ds.getProvince())
                            && config.getRemark().equals(ds.getRemark().trim())
                    )) {
                        config = new ScheduleConfig();
                        configId = idGenerator.genScheduleConfigId();
                        config.setCreateTime(new Date());
                        config.setDeleted(false);
                        config.setDoctorId(doctorId);
                        config.setId(configId);
                    }
                }
                config.setAddress(ds.getAddress().trim());
                config.setAmount(ds.getAmount());
                config.setArea(ds.getArea());
                config.setAreaId(ds.getAreaId());
                config.setCity(ds.getCity());
                config.setCityId(ds.getCityId());
                config.setProvince(ds.getProvince());
                config.setProvinceId(ds.getProvinceId());
                config.setRemark(ds.getRemark().trim());
                config.setUpdateTime(new Date());

                scheduleConfigRepository.save(config);

                //验证是否是新地址
                int count = addressRepository.checkAddress(doctorId, ds.getProvinceId(), ds.getCityId(), ds.getAreaId(), ds.getAddress().trim());
                if (count == 0) {        // 此时表示是新增的数据
                    Address addr = new Address();
                    int addrId = idGenerator.genAddressId();
                    addr.setType(1);
                    addr.setUpdateTime(new Date());
                    addr.setStatus(0);  // status   1-默认地址，0-非默认
                    addr.setDeleted(false);
                    addr.setAddress(ds.getAddress().trim());
                    addr.setAppellation("");
                    addr.setArea(ds.getArea());
                    addr.setAreaId(ds.getAreaId());
                    addr.setCity(ds.getCity());
                    addr.setCityId(ds.getCityId());
                    addr.setContact("");
                    addr.setCreateTime(new Date());
                    addr.setId(addrId);
                    addr.setUserId(doctorId);
                    addr.setProvince(ds.getProvince());
                    addr.setProvinceId(ds.getProvinceId());
                    addr.setMobile("");
                    addressRepository.save(addr);
                }

                //保存doctor_schedule表信息
                String date = DateUtil.convertTimestampToDateString(ds.getClinicTime(), "yyyy-MM-dd 00:00:00");
                DoctorSchedule schedule = doctorScheduleRepository.findSchedule(doctorId, date, ds.getMorning(), ds.getAfternoon(), ds.getNight());

                int scheduleId = 0;
                if (!Checker.isNone(schedule)) {
                    scheduleId = schedule.getId();
                } else {
                    schedule = new DoctorSchedule();
                    scheduleId = idGenerator.genDoctorScheduleId();
                }

                schedule.setId(scheduleId);
                schedule.setDeleted(false);
                schedule.setAfternoon(ds.getAfternoon() == 1);
                schedule.setMorning(ds.getMorning() == 1);
                schedule.setNight(ds.getNight() == 1);
                schedule.setClinicTime(DateUtil.stringToDate(date));
                schedule.setConfigId(configId);
                schedule.setRemark("");
                schedule.setCreateTime(new Date());
                schedule.setDoctorId(doctorId);
                schedule.setType(ds.getType());
                schedule.setUpdateTime(new Date());

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

    /**
     * 得到医生时间最大的排班
     *
     * @param doctorId
     */
    public List<DoctorSchedule> getThatDayDoctorScheduleList(int doctorId) {
        return doctorScheduleRepository.getThatDayDoctorScheduleList(doctorId);
    }

    ;


    /**
     * 保存团队信息
     * <p>
     * create by daiyihua
     *
     * @param doctorId
     * @param teamId
     * @param teamIntro
     * @param teamName
     * @param teamDoctorInfoList
     * @return
     */
    public ServiceResult saveTeam(int doctorId, int teamId, String teamIntro, String teamName, List<TeamDoctorInfo> teamDoctorInfoList) {
        ServiceResult result = new ServiceResult();
        Team team = null;
        if (teamId > 0) {
            team = teamRepository.findById(teamId).orElse(null);
            if (Checker.isNone(team)) {
                return result.failed("参数错误");
            }
        } else {
            team = new Team();
            teamId = idGenerator.genTeamId();
            team.setCreateTime(new Date());
            team.setDeleted(false);
            team.setDoctorId(doctorId);
            team.setId(teamId);
            team.setStatus(0);
        }

        team.setUpdateTime(new Date());
        team.setIntro(teamIntro);
        team.setName(teamName);
        teamRepository.save(team);

        // 将所有的医生ID都放入一个集合内
        List<Integer> intLst = new ArrayList<>();
        intLst.add(doctorId);

        if (!Checker.isNone(teamDoctorInfoList)) {
            for (TeamDoctorInfo info : teamDoctorInfoList) {
                if (!intLst.contains(info.getDoctorId())) {
                    intLst.add(info.getDoctorId());
                }
            }
        }

        // 得到之前已加入和未加入的团队成员
        List<TeamDoctor> teamDoctorList = teamDoctorRepository.getTeamDoctorByTeamId(teamId);
        if (!Checker.isNone(teamDoctorList)) {

            // 遍历已存在的团队成员信息
            for (TeamDoctor td : teamDoctorList) {

                // 如果传过来的医生ID不包含原来已存在的，则表示删除，如果包含原来的，则不做改变
                if (!intLst.contains(td.getDoctorId())) {
                    td.setUpdateTime(new Date());
                    td.setDeleted(true);
                    teamDoctorRepository.save(td);
                } else {
                    // 删除数据库中能够进行匹配的
                    intLst.remove(td.getDoctorId());
                }
            }

            if (!Checker.isNone(intLst)) {
                // 直接添加
                for (Integer docId : intLst) {
                    TeamDoctor teamDoctor = new TeamDoctor();
                    int teamDoctorId = idGenerator.genTeamDoctorId();
                    teamDoctor.setCreateTime(new Date());
                    teamDoctor.setDeleted(false);
                    teamDoctor.setDoctorId(docId);
                    teamDoctor.setId(teamDoctorId);
                    teamDoctor.setTeamId(teamId);
                    teamDoctor.setStatus(0);         //1-已加入 0-未加入，2-已拒绝
                    teamDoctor.setUpdateTime(new Date());
                    teamDoctor.setJoinTime(new Date());
                    teamDoctorRepository.save(teamDoctor);
                }
            }
        } else {
            // 直接添加
            for (Integer docId : intLst) {
                TeamDoctor teamDoctor = new TeamDoctor();
                int teamDoctorId = idGenerator.genTeamDoctorId();
                teamDoctor.setCreateTime(new Date());
                teamDoctor.setDeleted(false);
                teamDoctor.setDoctorId(docId);
                teamDoctor.setId(teamDoctorId);
                teamDoctor.setTeamId(teamId);
                if (docId == doctorId) {
                    teamDoctor.setStatus(1);         //1-已加入 0-未加入，2-已拒绝，如果是自己，则直接添加
                } else {
                    teamDoctor.setStatus(0);         //1-已加入 0-未加入，2-已拒绝
                }
                teamDoctor.setUpdateTime(new Date());
                teamDoctor.setJoinTime(new Date());
                teamDoctorRepository.save(teamDoctor);
            }
        }
        return result.succeed("处理成功");
    }

    /**
     * 删除团队中的医生
     *
     * @param doctorId
     * @param teamId
     * @return
     */
    public ServiceResult delTeamDoctor(int teamId, int doctorId) {
        ServiceResult result = new ServiceResult();
        TeamDoctor teamDoctor = teamDoctorRepository.getTeamDoctor(teamId, doctorId);
        if (Checker.isNone(teamDoctor)) {
            return result.failed("该团队中没有该医生");
        }
        teamDoctor.setDeleted(true);
        teamDoctor.setUpdateTime(new Date());
        teamDoctorRepository.save(teamDoctor);
        return result.succeed("处理成功");
    }

    /**
     * 获取所有符合条件的医生
     * <p>
     * create by daiyihua
     *
     * @param pageIndex     页码
     * @param pageSize      页大小
     * @param name          医生姓名
     * @param arrHospitalId 医院Id
     * @param deptId        科室Id
     * @return
     */
    public PagedList<DoctorInfoView> getAllDoctorInfoList(int pageIndex, int pageSize, String name, int[] arrHospitalId, int deptId) {
        List<Object> paramList = new ArrayList<>();
        List<Integer> typeList = new ArrayList<>();
        String whereSql = "";

        if (!Checker.isNone(name)) {
            whereSql += " real_name like ? and ";
            paramList.add("%" + name + "%");
            typeList.add(Types.VARCHAR);
        }

        if (arrHospitalId.length > 0) {
            String hospitalSql = "";

            for (int hospitalId : arrHospitalId) {
                if (hospitalId == 0) {
                    continue;
                }

                if ("".equals(hospitalSql)) {
                    hospitalSql += " hospital_ids like ? ";
                } else {
                    hospitalSql += " or hospital_ids like ? ";
                }
                paramList.add("%," + hospitalId + ",%");
                typeList.add(Types.VARCHAR);
            }

            if (!"".equals(hospitalSql)) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }


        if (deptId != 0) {
            whereSql += " dept_ids like ? and ";
            paramList.add("%," + deptId + ",%");
            typeList.add(Types.VARCHAR);
        }

        //过滤被禁用医院的医生（医院下有医生，若后台设置这家医院为禁用，这个医院下的所有医生也不显示在app列表中）
        String idSql = "select id from hospital where status = 1 or is_deleted = 1;";
        List<Integer> hospitalIds = jdbcTemplate.queryForList(idSql, Integer.class);

        if (hospitalIds != null && hospitalIds.size() > 0) {
            String hospitalSql = "";

            for (Integer hospitalId : hospitalIds) {
                if (hospitalId > 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids <> ? ";
                    } else {
                        hospitalSql += " and hospital_ids <> ? ";
                    }

                    paramList.add("," + hospitalId + ",");
                    typeList.add(Types.VARCHAR);
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }


        whereSql += " is_deleted = 0 and doctor_status = 0";
        int[] argTypes = typeList.stream().mapToInt(i -> i).toArray();

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

    /**
     * 判断该团队中是否含有该医生
     * <p>
     * create by daiyihua
     *
     * @param teamId
     * @param doctorId
     * @return
     */
    public int checkTeamDoctor(int teamId, int doctorId) {
        return teamDoctorRepository.checkTeamDoctor(teamId, doctorId);
    }

    /**
     * 得到医生已加入或创建的团队
     * <p>
     * create by daiyihua
     *
     * @param doctorId
     * @return
     */
    public List<TeamDoctor> getMyTeam(int doctorId) {
        return teamDoctorRepository.getMyTeam(doctorId);
    }

    ;

    /**
     * 根据团队ID得到团队对象
     * <p>
     * create by daiyihua
     *
     * @param teamId
     * @return
     */
    public Team getTeamById(int teamId) {
        return teamRepository.findById(teamId).orElse(null);
    }

    /**
     * 根据团队ID得到团队中所有待加入和已加入的成员
     * <p>
     * create by daiyihua
     *
     * @param teamId
     * @return
     */
    public List<TeamDoctor> getTeamDoctorByTeamId(int teamId) {
        return teamDoctorRepository.getTeamDoctorByTeamId(teamId);
    }

    ;

    /**
     * 删除团队
     * <p>
     * create by daiyihua
     *
     * @param doctorId
     * @param teamId
     * @return
     */
    public ServiceResult delTeam(int teamId, int doctorId) {
        ServiceResult result = new ServiceResult();

        Team team = teamRepository.findById(teamId).orElse(null);

        if (Checker.isNone(team)) {
            return result.failed("参数错误");
        }

        //如果团队的创建人就是传过来的医生ID，则表示删除的是自己创建的团队
        if (team.getDoctorId() == doctorId) {
            List<TeamDoctor> teamDoctorList = teamDoctorRepository.getAllTeamDoctorByTeamId(teamId);
            if (Checker.isNone(teamDoctorList)) {
                return result.failed("参数错误");
            }
            for (TeamDoctor teamDoctor : teamDoctorList) {
                teamDoctor.setUpdateTime(new Date());
                teamDoctor.setDeleted(true);
                teamDoctorRepository.save(teamDoctor);
            }
            //删除团队的同时，也要把team表中的记录删除
            team.setDeleted(true);
            team.setUpdateTime(new Date());
            teamRepository.save(team);
        }
        //反之，删除的是别人创建的团队，相当于自己退出那个团队
        else {
            TeamDoctor teamDoctor = teamDoctorRepository.getTeamDoctor(teamId, doctorId);
            if (Checker.isNone(teamDoctor)) {
                return result.failed("参数错误");
            }
            teamDoctor.setDeleted(true);
            teamDoctor.setUpdateTime(new Date());
            teamDoctorRepository.save(teamDoctor);
        }

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

    ;

    /**
     * 申请加入团队
     * <p>
     * create by daiyihua
     *
     * @param doctorId
     * @param teamId
     * @return
     */
    public ServiceResult applyToJoin(int teamId, int doctorId) {
        ServiceResult result = new ServiceResult();

        Team team = teamRepository.findById(teamId).orElse(null);

        if (Checker.isNone(team)) {
            return result.failed("参数错误");
        }

        //判断团队ID中是否存在该医生ID
        int count = teamDoctorRepository.checkTeamDoctor(teamId, doctorId);
        if (count > 0) {
            return result.failed("团队中已存在该成员");
        }

        //在团队中添加这个成员
        TeamDoctor teamDoctor = new TeamDoctor();
        int teamDoctorId = idGenerator.genTeamDoctorId();
        teamDoctor.setCreateTime(new Date());
        teamDoctor.setDeleted(false);
        teamDoctor.setDoctorId(doctorId);
        teamDoctor.setId(teamDoctorId);
        teamDoctor.setTeamId(teamId);
        teamDoctor.setStatus(0);         //1-已加入 0-未加入，2-已拒绝
        teamDoctor.setUpdateTime(new Date());
        teamDoctorRepository.save(teamDoctor);

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

    ;


    /**
     * 获取所有符合条件的团队
     * <p>
     * create by daiyihua
     *
     * @param pageIndex 页码
     * @param pageSize  页大小
     * @param name      医生姓名
     * @return
     */
    public PagedList<TeamDoctorInfoView> getTeamInfoList(int pageIndex, int pageSize, String name, int doctorId) {
        List<Object> paramList = new ArrayList<>();
        List<Integer> typeList = new ArrayList<>();
        String whereSql = " 1=1 ";

        if (!Checker.isNone(name)) {
            whereSql += " and doctor_name like ?  ";
            paramList.add("%" + name + "%");
            typeList.add(Types.VARCHAR);
        }

        whereSql += " and status = 0 and doctor_id != ? and invited_doctor_id = ? ";
        paramList.add(doctorId);
        typeList.add(Types.INTEGER);
        paramList.add(doctorId);
        typeList.add(Types.INTEGER);

        int[] argTypes = typeList.stream().mapToInt(i -> i).toArray();


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

    /**
     * 申请加入团队
     * <p>
     * create by daiyihua
     *
     * @param doctorId
     * @param teamId
     * @return
     */
    public ServiceResult dealWithInvitation(int teamId, int doctorId, int status) {
        ServiceResult result = new ServiceResult();

        Team team = teamRepository.findById(teamId).orElse(null);

        if (Checker.isNone(team)) {
            return result.failed("参数错误");
        }

        TeamDoctor teamDoctor = teamDoctorRepository.getTeamDoctor(teamId, doctorId);
        if (Checker.isNone(teamDoctor) || teamDoctor.getDeleted()) {
            return result.failed("参数错误");
        }

        if (teamDoctor.getStatus() != status) {
            teamDoctor.setUpdateTime(new Date());
            teamDoctor.setStatus(status);
            if (status == 1) {
                teamDoctor.setJoinTime(new Date());
            }
            teamDoctorRepository.save(teamDoctor);
        }

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

    ;

    /**
     * 根据医生ID得到该医生创建和加入的团队总数量
     * TODO: 这里需要筛选掉我加入的团队的创始人后面变为普通用户的情况
     *
     * @param doctorId
     * @return
     */
    public int getMyTeamCount(int doctorId) {
        int i = 0;
        List<TeamDoctor> tdList = teamDoctorRepository.getMyTeam(doctorId);
        if (!Checker.isNone(tdList)) {
            for (TeamDoctor td : tdList) {
                Team team = teamRepository.findById(td.getTeamId()).orElse(null);
                if (!Checker.isNone(team) && !team.getDeleted()) {
                    DoctorInfoView doctor = doctorInfoViewRepository.findById(team.getDoctorId()).orElse(null);
                    if (Checker.isNone(doctor) || doctor.getDoctorStatus() == 1) {
                        continue;
                    } else {
                        i++;
                    }
                }
            }
        }
        return i;
    }

    ;

    /**
     * 返回个人二维码被扫总数
     *
     * @param doctorId
     * @return
     */
    public int getScanQrCodePatientCount(int doctorId) {
        // @deprecated
        // return userUnionsRepository.getPatientAmount(doctorId);
        try {
            GetDoctorStatisticsTotalInfoRequest request = GetDoctorStatisticsTotalInfoRequest.newBuilder()
                    .setDoctorId(doctorId)
                    .build();
            GetDoctorStatisticsTotalInfoResponse response = doctorStatisticsServiceBlockingStub.getDoctorStatisticsTotalInfo(request);
            if (response.getCode() == ResultCode.SUCCEED.getNumber()) {
                // 返回个人二维码被扫总数
                return response.getInfo().getScanQrCodeCount();
            }
        } catch (Exception e) {
            logger.error("根据医生ID返回个人二维码被扫总数出错", e.getMessage(), e);
        }
        return 0;
    }

    /**
     * 获取单个医生的汇总统计信息
     *
     * @param doctorId
     * @return
     */
    public GetDoctorStatisticsTotalInfoResponse getDoctorStatisticsTotalInfo(int doctorId) {
        try {
            GetDoctorStatisticsTotalInfoRequest request = GetDoctorStatisticsTotalInfoRequest.newBuilder()
                    .setDoctorId(doctorId)
                    .build();
            return doctorStatisticsServiceBlockingStub.getDoctorStatisticsTotalInfo(request);
        } catch (Exception e) {
            logger.error("获取单个医生的汇总统计信息，getDoctorStatisticsTotalInfo(): {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取所有符合条件的医生
     * <p>
     * create by daiyihua
     *
     * @param pageIndex 页码
     * @param pageSize  页大小
     * @param deptId    科室Id
     * @return
     */
    public PagedList<DoctorInfoView> getDoctorInfoViewList(int pageIndex, int pageSize, int deptId) {
        List<Object> paramList = new ArrayList<>();
        List<Integer> typeList = new ArrayList<>();
        String whereSql = " 1 = 1 ";

        if (deptId != 0) {

            // 这里需要判断科室ID是不是最后一级
            Map<Integer, Department> deptMap = hospitalService.getDepartmentMap();
            Department dept = deptMap.get(deptId);
            //如果不为空，而且科室的父类为0，则表示是第一级
            if (!Checker.isNone(dept) && dept.getParentId() == 0) {
                List<Department> deptAllList = hospitalService.getDepartmentList();
                List<Department> deptList = deptAllList.stream().filter(p -> p.getParentId() == deptId).collect(Collectors.toList());
                if (!Checker.isNone(deptList)) {
                    whereSql += " and ( ";
                    for (Department dp : deptList) {
                        if (dp.getId() == deptList.get(0).getId()) {
                            whereSql += " dept_ids like ? ";
                        } else {
                            whereSql += " or dept_ids like ? ";
                        }
                        paramList.add("%," + dp.getId() + ",%");
                        typeList.add(Types.VARCHAR);
                    }
                    whereSql += " ) ";
                }
            } else {
                whereSql += " and  dept_ids like ?  ";
                paramList.add("%," + deptId + ",%");
                typeList.add(Types.VARCHAR);
            }
        }

        whereSql += " and is_deleted = 0 ";
        int[] argTypes = typeList.stream().mapToInt(i -> i).toArray();

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

    /**
     * 根据医生ID得到医生的排班数量
     *
     * @param doctorId
     * @return
     */
    public int getAdditionalCount(int doctorId) {
        String dateTime = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date());    // 表示查询的那一天
        String dayDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

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

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

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

        Date newDate = new Date();
        int morningCount = 0;
        int afternoonCount = 0;
        int nightCount = 0;

        //当天
        if (newDate.after(nightDate)) {                 // 当前时间为当天晚上10点后，不用计算数量

        } else if (newDate.after(afternoonDate)) {        //当前时间为当天下午点后，下午10点之前，则上午是下午已结束，晚上是待接诊
            morningCount = doctorScheduleRepository.getMorningCount(doctorId, dateTime);
        } else if (newDate.after(morningDate)) {         //当前时间为当天12点后，下午5点之前，则上午是已结束，下午，晚上是待接诊
            afternoonCount = doctorScheduleRepository.getAfternoonCount(doctorId, dateTime);
            nightCount = doctorScheduleRepository.getNightCount(doctorId, dateTime);
        } else {                                         //当前时间为当天12点之前，上午，下午，晚上是待接诊
            morningCount = doctorScheduleRepository.getMorningCount(doctorId, dateTime);
            afternoonCount = doctorScheduleRepository.getAfternoonCount(doctorId, dateTime);
            nightCount = doctorScheduleRepository.getNightCount(doctorId, dateTime);
        }

        //先得到后一天的数量
        int tomorrowCount = doctorScheduleRepository.getCount(doctorId);
        return morningCount + afternoonCount + nightCount + tomorrowCount;
    }

    ;

    /**
     * 根据医生ID和医院ID 得到 DoctorHisCode 对象
     *
     * @param doctorId
     * @param hospitalId
     * @return
     */
    public DoctorHisCode getDoctorHisCode(int doctorId, int hospitalId) {
        return doctorHisCodeRepository.getDoctorHisCode(doctorId, hospitalId);
    }

    /**
     * 判断医生是否已填写好基本信息(1-已认证，0-未认证)
     * 后台添加的医生没有认证一说（基本信息都是填好的）
     *
     * @return
     */
    public int checkBaseStatus(int doctorId) {

        int checkBaseStatus = 0;
        Doctor doctor = doctorRepository.findById(doctorId).orElse(null);
        if (!Checker.isNone(doctor)) {
            //如果是医生，则直接表示已认证（基本信息已填写）
            checkBaseStatus = 1;
            return checkBaseStatus;
        }

        User user = userRepository.findById(doctorId).orElse(null);
        DoctorInfoAudit info = doctorInfoAuditRepository.getDoctorInfoAudit(doctorId);

        if (!Checker.isNone(user) && !Checker.isNone(info)
                && !Checker.isNone(user.getRealname())
                && !Checker.isNone(info.getDeptIds())
                && !Checker.isNone(info.getTitle())) {
            checkBaseStatus = 1;
        }

        return checkBaseStatus;
    }

    /**
     * 根据ID得到药商对象
     *
     * @param providerId
     * @return
     */
    public DrugProvider getDrugProviderById(int providerId) {
        return drugProviderRepository.findById(providerId).orElse(null);
    }

    /**
     * 根据ID得到代表对象
     *
     * @param agentId
     * @return
     */
    public Agent getAgentById(int agentId) {
        return agentRepository.findById(agentId).orElse(null);
    }

    /**
     * 保存医生基本信息
     *
     * @param doctorId
     * @param name
     * @param hospitalId
     * @param hospitalName
     * @param deptId
     * @param title
     * @return
     */
    public ServiceResult saveBaseInfo(int doctorId, String name, int hospitalId,
                                      String hospitalName, int deptId, String title) {


        ServiceResult result = new ServiceResult();

        try {

            User user = userRepository.findById(doctorId).orElse(null);
            Doctor doctor = doctorRepository.findById(doctorId).orElse(null);
            if (Checker.isNone(user) || user.getIsDeleted()) {
                return result.failed("该账号不存在");
            } else if (Checker.isNone(doctor)) {
                //此时表示普通用户
                user.setRealname(name);
                userRepository.save(user);

                //当医院ID为0时，表示医院的信息是填写的
                DoctorInfoAudit audit = new DoctorInfoAudit();
                int auditId = idGenerator.genDoctorInfoAuditId();
                audit.setId(auditId);
                audit.setName(name);
                audit.setDeleted(false);
                audit.setUpdateTime(new Date());
                audit.setCreateTime(new Date());
                audit.setAuditType(1);
                audit.setDeptIds("," + deptId + ",");
                audit.setHospitalIds("," + hospitalId + ",");
                audit.setHospitalName(hospitalName.trim());
                audit.setDoctorId(doctorId);
                audit.setAuditStatus(0);
                audit.setTitle(title);

                doctorInfoAuditRepository.save(audit);

                // 生成未认证医生的二维码
                try {
                    createAuditQrCode(doctorId, auditId);
                } catch (Exception e) {
                    logger.error("/api/doctor/saveBaseInfo:{生成二维码出错}", e.getMessage());
                    e.printStackTrace();
                }

                // 填写好基本信息之后，处理user_unions表中base_status字段
                dealUserUnionBaseStatus(doctorId);
                return result.succeed("处理成功");
            }


            user.setRealname(name);

            userRepository.save(user);

            doctor.setTitle(title);
            doctor.setDeptIds("," + deptId + ",");
            doctor.setUpdateTime(new Date());
            if (hospitalId != 0) {
                doctor.setDeptIds("," + hospitalId + ",");
            }
            doctorRepository.save(doctor);

            //当医院ID为0时，表示医院的信息是填写的
            DoctorInfoAudit audit = new DoctorInfoAudit();
            int auditId = idGenerator.genDoctorInfoAuditId();
            audit.setId(auditId);
            audit.setName(name);
            audit.setDeleted(false);
            audit.setUpdateTime(new Date());
            audit.setCreateTime(new Date());
            audit.setAuditType(1);
            audit.setDeptIds("," + deptId + ",");
            audit.setHospitalIds("," + hospitalId + ",");
            audit.setHospitalName(hospitalName.trim());
            audit.setDoctorId(doctorId);
            audit.setAuditStatus(0);
            audit.setTitle(title);

            doctorInfoAuditRepository.save(audit);

            // 填写好基本信息之后，处理user_unions表中base_status字段
            dealUserUnionBaseStatus(doctorId);

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

        } catch (Exception e) {
            logger.error("/saveBaseInfo", e, e.getMessage());
            return result.failed("处理失败");
        }
    }

    /**
     * 处理user_unions表中base_status字段,将base_status的值变为1
     *
     * @param doctorId
     */
    private void dealUserUnionBaseStatus(int doctorId) {
        UserUnions userUnions = userUnionsRepository.getDoctorBaseStatus(doctorId);
        if (!Checker.isNone(userUnions) && userUnions.getBaseStatus() == 0) {
            userUnions.setBaseStatus(1);
            userUnionsRepository.save(userUnions);
        }
    }

    /**
     * 创建二维码（生成未认证医生的二维码）
     *
     * @param doctorId
     */
    public void createAuditQrCode(int doctorId, int auditId) {

        CreateQrCodeLimitStrSceneRequest req = CreateQrCodeLimitStrSceneRequest.newBuilder()
                .setSceneStr(DoctorWxOfficialSenceConstraint.DoctorTMPPrefix + doctorId)
                .setType(TerminalEnum.PatientWxOfficial.getValue())
                .build();
        CreateQrCodeLimitStrSceneResponse res = weChatServiceBlockingStub.createQrCodeLimitStrScene(req);

        if (res.getCode() == 0) {

            //上传图片
            String imgExt = "jpg";
            UploadImageRequest uploadImageRequest = UploadImageRequest.newBuilder()
                    .setFilename(String.format("%s.%s", Checksum.crc32(res.getQrData().toByteArray()), imgExt))
                    .setDatas(res.getQrData())
                    .setVpath("user/qrcode").build();
            UploadImageResponse uploadImageResponse = fileServiceBlockingStub.uploadImage(uploadImageRequest);
            if (uploadImageResponse.getCode() == 0) {
                DoctorInfoAudit audit = doctorInfoAuditRepository.findById(auditId).orElse(null);
                audit.setQrCodeUrl(uploadImageResponse.getRealityUrl());
                doctorInfoAuditRepository.save(audit);
            }
        }
    }


    /**
     * 得到身份证正反图片
     *
     * @param doctorId
     * @return
     */
    public List<MedicalRecordsImage> getDoctorIdNoImgList(int doctorId) {
        return medicalRecordsImageRepository.getDoctorIdNoImgList(doctorId);
    }

    /**
     * 医师资格证
     *
     * @param doctorId
     * @return
     */
    public List<MedicalRecordsImage> getDoctorQualificationImgList(int doctorId) {
        return medicalRecordsImageRepository.getDoctorQualificationImgList(doctorId);
    }

    /**
     * 医师专业技术资格证
     *
     * @param doctorId
     * @return
     */
    public List<MedicalRecordsImage> getDoctorProfessionalSkillImgList(int doctorId) {
        return medicalRecordsImageRepository.getDoctorProfessionalSkillImgList(doctorId);
    }

    /**
     * 根据用户ID得到用户对象
     *
     * @param userId
     * @return
     */
    public User getUserById(int userId) {
        return userRepository.findById(userId).orElse(null);
    }

    /**
     * 保存医生信息
     *
     * @param doctorId
     * @param name
     * @param sex
     * @param title
     * @param briefIntro
     * @param hospitalId
     * @param deptId
     * @param avatar
     * @param specialty
     * @param urls
     * @return
     */
    public ServiceResult updateDoctorInfoVerify(int doctorId, String name, int sex, String title, String briefIntro,
                                                int hospitalId, int deptId, String avatar, String specialty, List<String> urls, String hospitalName,
                                                String idNo, List<String> idNoUrls, List<String> qualificationUrls, List<String> professionalSkillUrls,
                                                int identity) {
        ServiceResult serviceResult = new ServiceResult();
        DoctorInfoAudit audit = doctorInfoAuditRepository.getDoctorInfoAudit(doctorId);

        /**
         * 下面有好几种情况
         * 1、此时不操作医生表
         * 2、当audit对象不为空时，判断是认证审核还是资料审核
         *      a、认证审核
         *          1）、审核通过，则新增的是资料审核记录
         *          2）、审核不通过：新增认证审核
         *          3）、审核中，修改信息
         *      b、资料审核
         *          1）、审核中，修改信息
         *          2）、审核通过、审核不通过：新增资料审核
         * 3、当audit对象为空时，新增认证审核
         *
         * 思路更改：
         * 1、先判断是不是医生，如果是医生（要么是从后台添加，要么是普通用户经过认证后成为医生），就是资料审核
         * 2、如果不是医生，那一定是认证审核
         *
         *
         * 备注：audit_type-审核类型：0-医生资料审核，1-医生认证审核
         */

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

        if (user.getUsertype() == UserTypeEnum.Merchant.getValue()) {
            return serviceResult.failed("经销商用户不能认证");
        }

        // 校验 title & identity
        List<String> doctorTitleList = getDoctorTitleListByType(identity).stream()
                .map(DoctorTitle::getName)
                .collect(Collectors.toList());
        if (!doctorTitleList.contains(title)) return serviceResult.failed("身份和职称不匹配");

        //此时是医生资料审核
        if ((user.getUsertype() & UserTypeEnum.Doctor.getValue()) == UserTypeEnum.Doctor.getValue()) {
            //资料审核
            if (!Checker.isNone(audit) && audit.getAuditStatus() == AuditStatusEnum.Pending.getValue()) {
                audit.setUpdateTime(new Date());
                audit.setAuditType(0);
            } else {

                audit = new DoctorInfoAudit();
                audit.setId(idGenerator.genDoctorInfoAuditId());
                audit.setCreateTime(new Date());
                audit.setUpdateTime(new Date());
                audit.setAuditStatus(AuditStatusEnum.Pending.getValue());
                audit.setAuditTime(null);
                audit.setAuditRemark(null);
                audit.setAuditType(0);
            }
        }

        //此时是患者，认证审核
        else {
            //认证审核
            if (audit != null) {
                //待审核
                if (audit.getAuditStatus() == AuditStatusEnum.Pending.getValue()) {
                    audit.setUpdateTime(new Date());
                    audit.setAuditType(1);
                }
                //审核不通过，认证审核
                else {
                    audit = new DoctorInfoAudit();
                    audit.setId(idGenerator.genDoctorInfoAuditId());
                    audit.setCreateTime(new Date());
                    audit.setUpdateTime(new Date());
                    audit.setAuditStatus(AuditStatusEnum.Pending.getValue());
                    audit.setAuditTime(null);
                    audit.setAuditRemark(null);
                    audit.setAuditType(1);
                }
            } else {
                audit = new DoctorInfoAudit();
                audit.setId(idGenerator.genDoctorInfoAuditId());
                audit.setCreateTime(new Date());
                audit.setUpdateTime(new Date());
                audit.setAuditStatus(AuditStatusEnum.Pending.getValue());
                audit.setAuditTime(null);
                audit.setAuditRemark(null);
                audit.setAuditType(1);
            }
        }

        //  提取公共部分
        audit.setName(name);
        audit.setSex(sex);
        audit.setTitle(title);
        audit.setBriefIntro(briefIntro);
        audit.setDoctorId(doctorId);
        audit.setDeleted(false);
        audit.setHospitalIds(String.format(",%d,", hospitalId));
        audit.setDeptIds(String.format(",%d,", deptId));
        audit.setAvatar(avatar);
        audit.setSpecialty(specialty);
        audit.setIdCertificateNo(idNo);
        audit.setIdentity(identity);
        if (hospitalId == 0) {
            audit.setHospitalName(hospitalName);
        }

        doctorInfoAuditRepository.save(audit);

        //生成未认证医生的二维码
        try {
            createAuditQrCode(doctorId, audit.getId());
        } catch (Exception e) {
            logger.error("/api/doctor/updateDoctorInfoVerify:{生成二维码出错}", e.getMessage());
            e.printStackTrace();
        }


        //处理证件照（执业证件）
        if (urls != null && urls.size() > 0) {
            List<MedicalRecordsImage> lst = new LinkedList<>();
            List<String> existedImages = new LinkedList<>();    //已存在的病历图片链接
            List<MedicalRecordsImage> images = medicalRecordsImageRepository.getDoctorPendingCertificateImageList(doctorId, MedicalRecordsImageTypeEnum.DoctorCertificate.getValue());

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

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

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

            for (String url : urls) {
                //本次新增的图片链接
                if (!existedImages.contains(url)) {
                    MedicalRecordsImage image = new MedicalRecordsImage();
                    image.setId(idGenerator.genMedicalRecordsImageId());
                    image.setDoctorId(doctorId);
                    image.setImageUrl(url);
                    image.setStatus(0);
                    image.setType(MedicalRecordsImageTypeEnum.DoctorCertificate.getValue());
                    image.setUserId(null);
                    image.setOrderId(null);
                    image.setMedicalRecordsId(null);
                    image.setPatientId(0);
                    image.setCreateTime(new Date());
                    image.setDeleted(false);
                    image.setUpdateTime(new Date());
                    image.setAuditId(audit.getId());
                    lst.add(image);
                }
            }

            medicalRecordsImageRepository.saveAll(lst);
        } else {
            //TODO: 删除全部审核中的图片
            List<MedicalRecordsImage> images = medicalRecordsImageRepository.getDoctorPendingCertificateImageList(doctorId, MedicalRecordsImageTypeEnum.DoctorCertificate.getValue());
            for (MedicalRecordsImage image : images) {
                //本次删除的图片
                image.setDeleted(true);
                medicalRecordsImageRepository.save(image);
            }
        }

        //处理身份证正反照片
        if (idNoUrls != null && idNoUrls.size() > 0) {
            List<MedicalRecordsImage> lst = new LinkedList<>();
            List<String> existedImages = new LinkedList<>();    //已存在的病历图片链接
            List<MedicalRecordsImage> images = medicalRecordsImageRepository.getDoctorPendingCertificateImageList(doctorId, MedicalRecordsImageTypeEnum.DoctorIdNoImg.getValue());

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

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

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

            for (String url : idNoUrls) {
                //本次新增的图片链接
                if (!existedImages.contains(url)) {
                    MedicalRecordsImage image = new MedicalRecordsImage();
                    image.setId(idGenerator.genMedicalRecordsImageId());
                    image.setDoctorId(doctorId);
                    image.setImageUrl(url);
                    image.setStatus(0);
                    image.setType(MedicalRecordsImageTypeEnum.DoctorIdNoImg.getValue());
                    image.setUserId(null);
                    image.setOrderId(null);
                    image.setMedicalRecordsId(null);
                    image.setPatientId(0);
                    image.setCreateTime(new Date());
                    image.setDeleted(false);
                    image.setUpdateTime(new Date());
                    image.setAuditId(audit.getId());

                    lst.add(image);
                }
            }

            medicalRecordsImageRepository.saveAll(lst);
        } else {
            //TODO: 删除全部审核中的图片
            List<MedicalRecordsImage> images = medicalRecordsImageRepository.getDoctorPendingCertificateImageList(doctorId, MedicalRecordsImageTypeEnum.DoctorIdNoImg.getValue());
            for (MedicalRecordsImage image : images) {
                //本次删除的图片
                image.setDeleted(true);
                medicalRecordsImageRepository.save(image);
            }
        }

        // 医师资格证
        if (qualificationUrls != null && qualificationUrls.size() > 0) {
            List<MedicalRecordsImage> lst = new LinkedList<>();
            List<String> existedImages = new LinkedList<>();    //已存在的病历图片链接
            List<MedicalRecordsImage> images = medicalRecordsImageRepository.getDoctorPendingCertificateImageList(doctorId, MedicalRecordsImageTypeEnum.DoctorQualificationImg.getValue());

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

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

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

            for (String url : qualificationUrls) {
                //本次新增的图片链接
                if (!existedImages.contains(url)) {
                    MedicalRecordsImage image = new MedicalRecordsImage();
                    image.setId(idGenerator.genMedicalRecordsImageId());
                    image.setDoctorId(doctorId);
                    image.setImageUrl(url);
                    image.setStatus(0);
                    image.setType(MedicalRecordsImageTypeEnum.DoctorQualificationImg.getValue());
                    image.setUserId(null);
                    image.setOrderId(null);
                    image.setMedicalRecordsId(null);
                    image.setPatientId(0);
                    image.setCreateTime(new Date());
                    image.setDeleted(false);
                    image.setUpdateTime(new Date());
                    image.setAuditId(audit.getId());

                    lst.add(image);
                }
            }

            medicalRecordsImageRepository.saveAll(lst);
        } else {
            //TODO: 删除全部审核中的图片
            List<MedicalRecordsImage> images = medicalRecordsImageRepository.getDoctorPendingCertificateImageList(doctorId, MedicalRecordsImageTypeEnum.DoctorQualificationImg.getValue());
            for (MedicalRecordsImage image : images) {
                //本次删除的图片
                image.setDeleted(true);
                medicalRecordsImageRepository.save(image);
            }
        }

        //医师专业技术资格证
        if (professionalSkillUrls != null && professionalSkillUrls.size() > 0) {
            List<MedicalRecordsImage> lst = new LinkedList<>();
            List<String> existedImages = new LinkedList<>();    //已存在的病历图片链接
            List<MedicalRecordsImage> images = medicalRecordsImageRepository.getDoctorPendingCertificateImageList(doctorId, MedicalRecordsImageTypeEnum.DoctorProfessionalSkillImg.getValue());

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

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

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

            for (String url : professionalSkillUrls) {
                //本次新增的图片链接
                if (!existedImages.contains(url)) {
                    MedicalRecordsImage image = new MedicalRecordsImage();
                    image.setId(idGenerator.genMedicalRecordsImageId());
                    image.setDoctorId(doctorId);
                    image.setImageUrl(url);
                    image.setStatus(0);
                    image.setType(MedicalRecordsImageTypeEnum.DoctorProfessionalSkillImg.getValue());
                    image.setUserId(null);
                    image.setOrderId(null);
                    image.setMedicalRecordsId(null);
                    image.setPatientId(0);
                    image.setCreateTime(new Date());
                    image.setDeleted(false);
                    image.setUpdateTime(new Date());
                    image.setAuditId(audit.getId());

                    lst.add(image);
                }
            }

            medicalRecordsImageRepository.saveAll(lst);
        } else {
            //TODO: 删除全部审核中的图片
            List<MedicalRecordsImage> images = medicalRecordsImageRepository.getDoctorPendingCertificateImageList(doctorId, MedicalRecordsImageTypeEnum.DoctorProfessionalSkillImg.getValue());
            for (MedicalRecordsImage image : images) {
                //本次删除的图片
                image.setDeleted(true);
                medicalRecordsImageRepository.save(image);
            }
        }

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

    /**
     * 根据医院ID和his编号得到相关信息
     *
     * @param hospitalId
     * @param hisCode
     * @return
     */
    public DoctorHisCode getDoctorByHisCode(int hospitalId, String hisCode) {
        return doctorHisCodeRepository.getDoctorByHisCode(hospitalId, hisCode);
    }

    /**
     * 通过HospitalIds得到医院名称
     *
     * @param hospitalIds
     * @return
     */
    public String getHospitalName(String hospitalIds) {
        String hospitalName = "";
        try {
            if (!StringHelper.isNullOrEmpty(hospitalIds)) {
                Map<Integer, Hospital> hospitalMap = hospitalService.getHospitalMap();
                String[] hospitalIdsStr = hospitalIds.split(",");
                for (String strHospitalId : hospitalIdsStr) {
                    if (!StringHelper.isNullOrEmpty(strHospitalId)) {
                        int hospitalId = Checker.parseInt(strHospitalId, 0);
                        if (hospitalId > 0) {
                            //医院id
                            Hospital hospital = hospitalMap.getOrDefault(hospitalId, null);
                            if (hospital != null && !hospital.isDeleted()) {
                                hospitalName = hospital.getName();
                                break;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
        }
        return hospitalName;
    }

    /**
     * 通过HospitalIds得到医院ID
     *
     * @param hospitalIds
     * @return
     */
    public int getHospitalId(String hospitalIds) {
        int backHospitalId = 0;
        if (!StringHelper.isNullOrEmpty(hospitalIds)) {
            String[] hospitalIdsStr = hospitalIds.split(",");
            Map<Integer, Hospital> hospitalMap = hospitalService.getHospitalMap();
            for (String strHospitalId : hospitalIdsStr) {
                if (!StringHelper.isNullOrEmpty(strHospitalId)) {
                    int hospitalId = Checker.parseInt(strHospitalId, 0);
                    if (hospitalId > 0) {
                        //医院id
                        Hospital hospital = hospitalMap.getOrDefault(hospitalId, null);

                        if (hospital != null && !hospital.isDeleted()) {
                            backHospitalId = hospital.getId();
                            break;
                        }
                    }
                }
            }
        }
        return backHospitalId;
    }

    public int getHospitalIdByDoctorId(int doctorId) {
        Doctor doctor = doctorRepository.findById(doctorId).orElse(null);
        return getHospitalId(doctor.getHospitalIds());
    }

    /**
     * 通过deptIds得到科室名称
     *
     * @param deptIds
     * @return
     */
    public String getDeptName(String deptIds) {
        String deptName = "";
        try {
            if (!StringHelper.isNullOrEmpty(deptIds)) {
                Map<Integer, Department> departmentMap = hospitalService.getDepartmentMap();
                String[] deptIdsStr = deptIds.split(",");
                for (String strDeptId : deptIdsStr) {
                    if (!StringHelper.isNullOrEmpty(strDeptId)) {
                        int deptId = Checker.parseInt(strDeptId, 0);
                        if (deptId > 0) {
                            //科室id
                            Department department = departmentMap.getOrDefault(deptId, null);
                            if (department != null && !department.isDeleted()) {
                                deptName = department.getName();
                                break;
                            }
                        }
                    }
                }

            }
        } catch (Exception e) {
        }
        return deptName;
    }

    /**
     * 通过deptIds得到科室id
     *
     * @param deptIds
     * @return
     */
    public int getDeptId(String deptIds) {
        int backDeptId = 0;
        if (!StringHelper.isNullOrEmpty(deptIds)) {
            Map<Integer, Department> departmentMap = hospitalService.getDepartmentMap();
            String[] deptIdsStr = deptIds.split(",");
            for (String strDeptId : deptIdsStr) {
                if (!StringHelper.isNullOrEmpty(strDeptId)) {
                    int deptId = Checker.parseInt(strDeptId, 0);
                    if (deptId > 0) {
                        //科室id
                        Department department = departmentMap.getOrDefault(deptId, null);
                        if (department != null && !department.isDeleted()) {
                            backDeptId = department.getId();
                            break;
                        }
                    }
                }
            }
        }
        return backDeptId;
    }

    /**
     * 得到最新的通过的审核
     *
     * @param doctorId
     * @return
     */
    public DoctorInfoAudit getLatestApprovedDoctorInfoAudit(int doctorId) {
        return doctorInfoAuditRepository.getLatestApprovedDoctorInfoAudit(doctorId);
    }

    /**
     * 得到医生的药事资讯
     *
     * @param userId
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public PagedList<ArticlesUnion> getDoctorArticles(int userId, int pageIndex, int pageSize) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = "obj_id =  ? and type = 1 and deleted = 0";
        paramList.add(userId);

        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "status , update_time desc", ArticlesUnion.class, paramList.toArray());
    }

    /**
     * 获取某个医生所有资讯设置
     *
     * @param userId user id
     * @return article union list
     */
    public List<ArticlesUnion> getDoctorAllArticles(int userId) {
        return articlesUnionRepository.getAllByDoctorId(userId);
    }

    /**
     * 根据资讯ID得到资讯对象
     *
     * @param artId
     * @return
     */
    public Articles getArticlesById(int artId) {
        return articlesRepository.findById(artId).orElse(null);
    }

    /**
     * 处理阅读
     *
     * @param artId
     * @param doctorId
     */
    public void dealArticlesUnionRead(int artId, int doctorId) {
        ArticlesUnion union = articlesUnionRepository.getArticlesUnion(artId, doctorId);
        if (!Checker.isNone(union)) {

            int status = union.getStatus() & ~ArticlesUnionStatusEnum.NoRead.getValue();
            status = status | ArticlesUnionStatusEnum.Read.getValue();
            union.setStatus(status);
            union.setUpdateTime(new Date());
            articlesUnionRepository.save(union);
        }
    }

    public int getArticlesNoReadCount(int doctorId) {
        return articlesUnionRepository.getArticlesNoReadCount(doctorId);
    }

    /**
     * 根据条件得到不通过的证书（type取值：4～7）
     *
     * @param doctorId
     * @param auditId
     * @param type
     * @return
     */
    public List<MedicalRecordsImage> getNoPassImageList(int doctorId, int auditId, int type) {
        return medicalRecordsImageRepository.getNoPassImageList(doctorId, auditId, type);
    }

    /**
     * 获取团队成员列表
     *
     * @param teamId 团队Id
     * @return
     */
    public List<TeamDoctorView> getTeamInfoList(int teamId) {
        return teamDoctorViewRepository.findByTeamId(teamId);
    }

    /**
     * 获取医生团队（展示状态）列表
     *
     * @param deptId
     * @return
     */
    public List<TeamCreatorInfoView> getTeamCreatorInfoList(int deptId) {
        final String sql = "select * from team_creator_info_view where team_status = 1 and dept_ids like ?;";
        final Object[] params = new Object[]{"%," + deptId + ",%"};
        final int[] types = new int[]{Types.VARCHAR};

        return jdbcTemplate.query(sql, params, types, new BeanPropertyRowMapper<>(TeamCreatorInfoView.class));
    }

    /**
     * 获取医生团队（展示状态）的科室Id列表
     *
     * @return
     */
    public List<String> getTeamDeptIdList() {
        final String sql = "select distinct(dept_ids) from team_creator_info_view where team_status = 1;";
        return jdbcTemplate.queryForList(sql, String.class);
    }

    /**
     * 判断患者是否关注医生
     * type: 1-药商代表关联，2-药商、代表和医生关联，3-医生和患者关联.4-用户关注患者
     * status: 0-启用，1-禁用
     *
     * @return
     */
    public int checkUserUnionDoctor(int userId, int doctorId) {
        return userUnionsRepository.checkUnion(userId, doctorId, 4, 0);
    }

    /**
     * 得到用户关注的医生列表
     * <p>
     * create by daiyihua
     *
     * @param pageIndex 页码
     * @param pageSize  页大小
     * @param userId    用户Id
     * @return
     */
    public PagedList<UserUnionsDoctorInfoView> generalGetAttentionDoctorList(int pageIndex, int pageSize, int userId, String name, int[] arrHospitalId, int deptId) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = "";

        if (!Checker.isNone(name)) {
            whereSql += " real_name like ? and ";
            paramList.add("%" + name + "%");
        }

        if (!Checker.isNone(userId)) {
            whereSql += " user_id = ? and ";
            paramList.add(userId);
        }

        if (arrHospitalId.length > 0) {
            String hospitalSql = "";
            for (int hospitalId : arrHospitalId) {
                if (hospitalId != 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids like ? ";
                    } else {
                        hospitalSql += " or hospital_ids like ? ";
                    }
                    paramList.add("%," + hospitalId + ",%");
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }

        if (deptId != 0) {
            whereSql += " dept_ids like ? and ";
            paramList.add("%," + deptId + ",%");
        }

        //过滤被禁用医院的医生（医院下有医生，若后台设置这家医院为禁用，这个医院下的所有医生也不显示在app列表中）
        String idSql = "select id from hospital where status = 1 or is_deleted = 1;";
        List<Integer> hospitalIds = jdbcTemplate.queryForList(idSql, Integer.class);

        if (hospitalIds != null && hospitalIds.size() > 0) {
            String hospitalSql = "";

            for (Integer hospitalId : hospitalIds) {
                if (hospitalId > 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids <> ? ";
                    } else {
                        hospitalSql += " and hospital_ids <> ? ";
                    }

                    paramList.add("," + hospitalId + ",");
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }

        whereSql += " doctor_status = 0 and union_status = 0 ";

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

    /**
     * 获取医生列表。其中我的医生置顶显示
     *
     * @param pageIndex     页码
     * @param pageSize      页大小
     * @param userId        患者id
     * @param name          医生姓名，筛选用
     * @param arrHospitalId 医院id，筛选用
     * @param deptId        科室id, 筛选用
     * @param filterType    过滤条件，0-不过滤；1-问诊医生
     * @param reqHospitalId 请求的医院 id，一般是从网关获取当前请求的小程序关联得到对应的医院
     * @return {@link PagedList}
     */
    public PagedList<ConsultDoctorInfo> getConsultDoctorsPagedList(int pageIndex, int pageSize, int userId, String name,
                                                                   int[] arrHospitalId, int deptId, int filterType,
                                                                   int identity, int reqHospitalId, int terminal) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = "";

        if (!Checker.isNone(name)) {
            whereSql += " real_name like ? and ";
            paramList.add("%" + name + "%");
        }

        if (arrHospitalId.length > 0) {
            String hospitalSql = "";
            for (int hospitalId : arrHospitalId) {
                if (hospitalId != 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids like ? ";
                    } else {
                        hospitalSql += " or hospital_ids like ? ";
                    }
                    paramList.add("%," + hospitalId + ",%");
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }

        if (deptId != 0) {
            whereSql += " dept_ids like ? and ";
            paramList.add("%," + deptId + ",%");
        }

        if (identity > 0) {
            whereSql += " identity = ? and ";
            paramList.add(identity);
        }

        if (terminal > 0) {
            whereSql += " `c`.`terminal` = ? and";
            paramList.add(terminal);
        }

        whereSql += " c.type = 2 and c.value = ? and";
        paramList.add("true");

        //过滤被禁用医院的医生（医院下有医生，若后台设置这家医院为禁用，这个医院下的所有医生也不显示在app列表中）
        String idSql = "select id from hospital where status = 1 or is_deleted = 1;";
        List<Integer> hospitalIds = jdbcTemplate.queryForList(idSql, Integer.class);

        if (hospitalIds != null && hospitalIds.size() > 0) {
            String hospitalSql = "";

            for (Integer hospitalId : hospitalIds) {
                if (hospitalId > 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids <> ? ";
                    } else {
                        hospitalSql += " and hospital_ids <> ? ";
                    }

                    paramList.add("," + hospitalId + ",");
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ")";
            }
        }

//        if (filterType == DoctorListFilterType.CONSULT.getType()) {
//            // 过滤开通问诊业务的医生
//            if (!StringHelper.isNullOrEmpty(whereSql)) {
//                whereSql += " and ";
//            }
//            whereSql += "schedule_status & 8 = 8";
//        }

        String fields4HospitalDoctorOrder = getFields4HospitalDoctorOrder(reqHospitalId);

        String fields = "`d`.`id` AS `id`,`d`.`title` AS `title`,`d`.`specialty` AS `specialty`,`d`.`brief_intro` AS `brief_intro`, " +
                "`d`.`create_time` AS `create_time`,`d`.`update_time` AS `update_time`, " +
                "`d`.`is_deleted` AS `is_deleted`,`d`.`dept_ids` AS `dept_ids`,`d`.`hospital_ids` AS `hospital_ids`, " +
                "`d`.`schedule_status` AS `schedule_status`,`d`.`status` AS `doctor_status`, `d`.`weight` as `weight`, `d`.`avatar2`, " +
                "`u`.`avatar` AS `avatar`, `u`.`real_name` AS `real_name`, `uu`.`user_id` AS `union_id`, " +
                "`uu`.update_time as `union_update_time`, `uu`.has_presc as `has_presc`, d.identity as identity, " +
                "d.neg_reception as neg_reception, d.neg_reception_hint as neg_reception_hint, c.terminal as terminal" +
                fields4HospitalDoctorOrder;

//        String from = "`ywt_center`.`doctor` `d` join `ywt_center`.`user` `u`" +
//                " on(`d`.`id` = `u`.`id`) and (`d`.`is_deleted` = 0) and (`u`.`is_deleted` = 0) and (`u`.`user_type` = 2) and (`d`.`status` = 0) and (`u`.`id` <> " + userId + ")" +
//                " left join `ywt_center`.`user_unions` `uu`" +
//                " on(`uu`.`union_user_id` = `u`.`id`) and (`uu`.`status` = 0) and (`uu`.`type` = 4) and (`uu`.`user_id` = " + userId + ")";
        String from = "`ywt_center`.`doctor` `d` join `ywt_center`.`user` `u`" +
                " on(`d`.`id` = `u`.`id`) and (`d`.`is_deleted` = 0) and (`u`.`is_deleted` = 0) and (`u`.`user_type` & 2 = 2) and (`d`.`status` = 0) " +
                " left join `ywt_center`.`user_unions` `uu`" +
                " on(`uu`.`union_user_id` = `u`.`id`)" +
                " and (`uu`.`status` = 0) and (`uu`.`type` = 4) and (`uu`.`user_id` = " + userId + ")" +
                "left join `ywt_center`.`common_doctor_setting` `c`" +
                "  on(`d`.`id` = `c`.`doctor_id`) ";

        String orderBy = "has_presc desc, union_update_time desc, " +
                (StringHelper.isNullOrEmpty(fields4HospitalDoctorOrder) ? "" : "hospital_weight desc, ") +
                " weight desc, update_time desc ";

        logger.info("fields {}", fields);
        logger.info("from {}", from);
        logger.info("whereSql {}", whereSql);
        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, fields, from, whereSql, orderBy,
                ConsultDoctorInfo.class, paramList.toArray());
    }

    public String getFields4HospitalDoctorOrder(int hospitalId) {
        StringBuilder stringBuilder = new StringBuilder();
        // 白云医院优先排列的逻辑为：我的医生-南方医科大学南方医院白云分院-南方医科大学南方医院-南方医院太和分院-其它医院
        // 太和医院优先排列的逻辑为：我的医生-南方医院太和分院-南方医科大学南方医院-南方医科大学南方医院白云分院-其它医院
        switch (hospitalId) {
            case Constants.TAIHE_HOSPITAL_ID:
                stringBuilder.append(", case " +
                        "when hospital_ids like '%,12,%' then 3 " +
                        "when hospital_ids like '%,1,%' then 2 " +
                        "when hospital_ids like '%,41,%' then 1 " +
                        "else 0 " +
                        "end as hospital_weight ");
                break;
            case Constants.NFYYBYFY_HOSPITAL_ID:
                stringBuilder.append(", case " +
                        "when hospital_ids like '%,41,%' then 3 " +
                        "when hospital_ids like '%,1,%' then 2 " +
                        "when hospital_ids like '%,12,%' then 1 " +
                        "else 0 " +
                        "end as hospital_weight ");
                break;
            default:
                break;

        }
        return stringBuilder.toString();
    }

    public List<DisplayTeam> getDisplayTeamListFromCache() {
        String json = redisTemplate.opsForValue().get(REDIS_KEY_DISPLAY_TEAM_LIST) + "";

        if (!StringHelper.isNullOrWhiteSpace(json)) {
            return JsonSerializer.from(json, new LinkedList<DisplayTeam>().getClass());
        }

        List<DisplayTeam> displayTeamList = getDisplayTeamList();

        if (displayTeamList != null && displayTeamList.size() > 0) {
            redisTemplate.opsForValue().set(REDIS_KEY_DISPLAY_TEAM_LIST, JsonSerializer.toJson(displayTeamList), Constant.REDIS_EXPIRE_TIME_TEN_MINUTES, TimeUnit.SECONDS);
            return displayTeamList;
        }

        return new LinkedList<>();
    }

    public List<DisplayTeam> getDisplayTeamList() {
        List<DisplayTeam> displayTeamList = new LinkedList<>();
        List<TeamDoctorView> teamDoctorViews = teamDoctorViewRepository.getDisplayTeamDoctorList();

        if (teamDoctorViews == null || teamDoctorViews.size() == 0) {
            return displayTeamList;
        }

        //领衔医生列表
        List<TeamDoctorView> leadDoctorList = teamDoctorViews.stream().filter(
                p -> p.getDoctorId().equals(p.getInvitedDoctorId()) && p.getDoctorStatus() == 0)
                .collect(Collectors.toList());

        //团队科室
        Map<String, List<Integer>> map = new HashMap<>();
        Department dept;
        String key;

        for (TeamDoctorView leader : leadDoctorList) {
            List<Department> deptList = hospitalService.getDepartmentListByIds(leader.getDeptIds());

            if (deptList == null || deptList.size() == 0) {
                continue;
            }

            key = "";
            dept = deptList.get(0);

            for (String deptName : map.keySet()) {
                if (deptName.equals(dept.getName())) {
                    key = deptName;
                    break;
                }
            }

            List<Integer> teamIds = "".equals(key) ? new LinkedList<>() : map.get(dept.getName());

            teamIds.add(leader.getTeamId());
            map.put(dept.getName(), teamIds);
        }

        for (String deptName : map.keySet()) {
            DisplayTeam displayTeam = new DisplayTeam();
            displayTeam.setDeptId(0);
            displayTeam.setDeptName(deptName);
            List<DisplayTeam.TeamInfo> teamList = new LinkedList<>();

            for (int teamId : map.get(deptName)) {
                String teamName = "";
                String teamIntro = "";

                List<DisplayTeam.DoctorInfo> doctorList = new LinkedList<>();
                List<TeamDoctorView> views = teamDoctorViews.stream().filter(p -> p.getTeamId().equals(teamId)).collect(Collectors.toList());

                for (TeamDoctorView doctorView : views) {
                    teamName = doctorView.getTeamName();
                    teamIntro = doctorView.getTeamIntro();

                    DisplayTeam.DoctorInfo doctorInfo = displayTeam.new DoctorInfo();
                    doctorInfo.setDoctorId(doctorView.getInvitedDoctorId());
                    doctorInfo.setDoctorName(doctorView.getDoctorName());
                    doctorInfo.setTitle(doctorView.getTitle());
                    doctorInfo.setAvatar(doctorView.getAvatar());
                    doctorInfo.setHospitalName(hospitalService.getHospitalNamesByHospitalIds(doctorView.getHospitalIds()));
                    doctorInfo.setDeptName(hospitalService.getDeptNamesByDeptIds(doctorView.getDeptIds()));
                    doctorInfo.setSpecialty(doctorView.getSpecialty());
                    doctorInfo.setIntro(doctorView.getBriefIntro());
                    doctorInfo.setScheduleList(getScheduleList(doctorView.getInvitedDoctorId()));

                    if (doctorView.getInvitedDoctorId().equals(doctorView.getDoctorId())) {
                        doctorList.add(0, doctorInfo);
                    } else {
                        doctorList.add(doctorInfo);
                    }
                }

                DisplayTeam.TeamInfo teamInfo = displayTeam.new TeamInfo();
                teamInfo.setTeamId(teamId);
                teamInfo.setTeamName(teamName);
                teamInfo.setTeamIntro(teamIntro);
                teamInfo.setDoctorList(doctorList);

                teamList.add(teamInfo);
            }

            displayTeam.setTeamList(teamList);
            displayTeamList.add(displayTeam);
        }

//        String ls = JsonSerializer.toJson(displayTeamList);
//        String a = ls;
//        logger.info(a);

        return displayTeamList;
    }

    /**
     * 获取展示团队的医生排班信息
     *
     * @param doctorId
     * @return
     */
    private List<DisplayTeam.ScheduleInfo> getScheduleList(int doctorId) {
        List<DisplayTeam.ScheduleInfo> lst = new LinkedList<>();

        //TODO 先从缓存读取
        String key = String.format("RPC.DisplayTeam_%d", doctorId);
        String value = redisTemplate.opsForValue().get(key)+"";

        if (!StringHelper.isNullOrWhiteSpace(value)) {
            Gson gson = new Gson();
            Type founderListType = new TypeToken<ArrayList<DisplayTeam.ScheduleInfo>>() {
            }.getType();
            lst = gson.fromJson(value, founderListType);
            return lst;
        }

        List<DoctorHisCode> doctorHisCodeList = doctorHisCodeRepository.getListByDoctorId(doctorId);

        if (doctorHisCodeList == null || doctorHisCodeList.size() == 0) {
            return lst;
        }

        DoctorHisCode doctorHisCode = doctorHisCodeList.get(0);
        DisplayTeam.ScheduleInfo scheduleInfo;
        Calendar calendar = Calendar.getInstance();
//        int morning = DatePeriodEnum.Morning.getValue();
//        int afternoon = DatePeriodEnum.Afternoon.getValue();

        String serviceDate;
        List<Schedule> scheduleList;
        List<com.ywt.gapi.nfyy.Schedule> nfyyScheduleList;

        for (int offset = 0; offset < 7; offset++) {
            serviceDate = DateUtil.convertToString(calendar.getTime(), "yyyy-MM-dd");
            scheduleInfo = new DisplayTeam().new ScheduleInfo();

            scheduleInfo.setDate(DateUtil.convertToString(calendar.getTime(), "MM-dd"));
            scheduleInfo.setWeek(DateUtil.getDayOfWeekMiddle(calendar));

            //
            scheduleInfo.setForenoon("");
            scheduleInfo.setAfternoon("");

//            for (DoctorHisCode doctorHisCode : doctorHisCodeList) {
            if (doctorHisCode.getHospitalId() == Constants.NFYY_HOSPITAL_ID) {
                nfyyScheduleList = nfyyProvider.getScheduleList(
                        doctorHisCode.getDeptCode(), doctorHisCode.getHisCode(), serviceDate, "");
                if (nfyyScheduleList == null || nfyyScheduleList.size() == 0) {

                } else {
                    for (com.ywt.gapi.nfyy.Schedule schedule : nfyyScheduleList) {
                        switch (schedule.getSessionCode()) {
                            case "S":
                                scheduleInfo.setForenoon("太和");
                                break;
                            case "X":
                                scheduleInfo.setAfternoon("太和");
                                break;
                        }
                    }
                }

//                    if (nfyyProvider.hasScheduling(serviceDate, morning, doctorHisCode.getHisCode(), doctorHisCode.getDeptCode())) {
//                        scheduleInfo.setForenoon("本部");
//                    } else {
//                        scheduleInfo.setForenoon("");
//                    }

                break;
            } else if (doctorHisCode.getHospitalId() == Constants.TAIHE_HOSPITAL_ID) {
//                    if (taiheProvider.hasScheduling(serviceDate, morning, doctorHisCode.getHisCode(), doctorHisCode.getDeptCode())) {
//                        scheduleInfo.setAfternoon("太和");
//                    } else {
//                        scheduleInfo.setAfternoon("");
//                    }


                scheduleList = taiheProvider.getScheduleList(
                        doctorHisCode.getDeptCode(), doctorHisCode.getHisCode(), serviceDate, doctorHisCode.getHospitalId());
                if (scheduleList == null || scheduleList.size() == 0) {

                } else {
                    for (Schedule schedule : scheduleList) {
                        switch (schedule.getDatePeriodName()) {
                            case "上午":
                                scheduleInfo.setForenoon("太和");
                                break;
                            case "下午":
                                scheduleInfo.setAfternoon("太和");
                                break;
                        }
                    }
                }
            }
//            }

//            //上午排班情况：
//            for (DoctorHisCode doctorHisCode : doctorHisCodeList) {
//                if (doctorHisCode.getHospitalId() == Constants.NFYY_HOSPITAL_ID) {
//                    if (nfyyProvider.hasScheduling(serviceDate, morning, doctorHisCode.getHisCode(), doctorHisCode.getDeptCode())) {
//                        scheduleInfo.setAfternoon("本部");
//                    } else {
//                        scheduleInfo.setAfternoon("");
//                    }
//
//                    break;
//                } else if (doctorHisCode.getHospitalId() == Constants.TAIHE_HOSPITAL_ID) {
//                    if (taiheProvider.hasScheduling(serviceDate, morning, doctorHisCode.getHisCode(), doctorHisCode.getDeptCode())) {
//                        scheduleInfo.setAfternoon("太和");
//                    } else {
//                        scheduleInfo.setAfternoon("");
//                    }
//
//                }
//            }
//
//            //下午排班情况
//            for (DoctorHisCode doctorHisCode : doctorHisCodeList) {
//                if (doctorHisCode.getHospitalId() == Constants.NFYY_HOSPITAL_ID) {
//                    if (nfyyProvider.hasScheduling(serviceDate, afternoon, doctorHisCode.getHisCode(), doctorHisCode.getDeptCode())) {
//                        scheduleInfo.setAfternoon("本部");
//                    } else {
//                        scheduleInfo.setForenoon("");
//                    }
//
//                    break;
//                } else if (doctorHisCode.getHospitalId() == Constants.TAIHE_HOSPITAL_ID) {
//                    if (taiheProvider.hasScheduling(serviceDate, afternoon, doctorHisCode.getHisCode(), doctorHisCode.getDeptCode())) {
//                        scheduleInfo.setForenoon("太和");
//                    } else {
//                        scheduleInfo.setForenoon("");
//                    }
//
//                    break;
//                }
//            }

            lst.add(scheduleInfo);
            calendar.add(Calendar.DATE, 1);
        }
        // 60分钟后过期
        redisTemplate.opsForValue().set(key, JsonSerializer.toJson(lst), (System.currentTimeMillis() / 1000) + Constant.REDIS_EXPIRE_TIME_ONE_HOUR, TimeUnit.SECONDS);
        return lst;
    }


    /**
     * 得到认证通过的医生列表
     *
     * @return
     */
    public List<DoctorInfoView> getDoctorInfoViewList() {
        return doctorInfoViewRepository.findAll();
    }

    /**
     * 得到正在认证审核当中的医生列表
     *
     * @return
     */
    public List<DoctorInfoAuditView> getDoctorInfoAuditingList() {
        return doctorInfoAuditViewRepository.findAllDoctorInfoAuditing();
    }

    /**
     * 得到认证通过的和正在认证的医生
     *
     * @return
     */
    public List<DoctorInfoView> getAllDoctorList() {
        try {
            List<DoctorInfoView> doctorInfoViews = getDoctorInfoViewList();
            List<DoctorInfoAuditView> doctorInfoAudits = getDoctorInfoAuditingList();
            Map<Integer, DoctorInfoView> doctorMap = CollectionUtil.toMap(doctorInfoViews, d -> d.getId());
            for (DoctorInfoAuditView infoAudit : doctorInfoAudits) {
                if (doctorMap.containsKey(infoAudit.getDoctorId())) {
                    continue;
                }
                DoctorInfoView doctorInfoView = new DoctorInfoView();
                doctorInfoView.setId(infoAudit.getDoctorId());
                doctorInfoView.setTitle(infoAudit.getTitle());
                doctorInfoView.setSpecialty(infoAudit.getSpecialty());
                doctorInfoView.setBirthday(infoAudit.getBirthday());
                doctorInfoView.setCreateTime(infoAudit.getCreateTime());
                doctorInfoView.setUpdateTime(infoAudit.getUpdateTime());
                doctorInfoView.setIsDeleted(infoAudit.getIsDeleted());
                doctorInfoView.setDeptIds(infoAudit.getDeptIds());
                doctorInfoView.setHospitalIds(infoAudit.getHospitalIds());
                doctorInfoView.setAvatar(infoAudit.getAvatar());
                doctorInfoView.setSex(infoAudit.getSex());
                doctorInfoView.setMobile(infoAudit.getMobile());
                doctorInfoView.setAge(infoAudit.getAge());
                doctorInfoView.setUserName(infoAudit.getUserName());
                doctorInfoView.setRealName(infoAudit.getRealName());
                doctorInfoView.setCity(infoAudit.getCity());
                doctorInfoView.setBirthday(infoAudit.getBirthday());
                doctorInfoView.setArea(infoAudit.getArea());
                doctorInfoView.setProvince(infoAudit.getProvince());
                doctorInfoView.setIdCertificateType(infoAudit.getIdCertificateType());
                doctorInfoView.setIdCertificateNo(infoAudit.getIdCertificateNo());
                doctorInfoView.setStatus(infoAudit.getStatus());
                doctorInfoView.setDoctorStatus(infoAudit.getStatus());
                doctorInfoViews.add(doctorInfoView);
                doctorMap.put(doctorInfoView.getId(), doctorInfoView);
            }
            return doctorInfoViews;
        } catch (Exception e) {

        }
        return new LinkedList<>();
    }

    /**
     * 获取所有医生信息（包括正在认证的）
     *
     * @return
     */
    public List<DoctorInfoView> getAllDoctorsHigh() {
        try {
            return (List<DoctorInfoView>) CacheUtil.getInstance().get(ALL_DOCTOR_LIST, () -> getAllDoctorList());
        } catch (Exception e) {
            logger.error("DoctorService#getAllDoctorsHigh():\n {}", e.getMessage(), e);
        }
        return new LinkedList<>();
    }

    /**
     * 获取所有医生信息映射（包括正在认证的）
     *
     * @return
     */
    public Map<Integer, DoctorInfoView> getAllDoctorsMap() {
        try {
            return (Map<Integer, DoctorInfoView>) CacheUtil.getInstance().get(ALL_DOCTOR_MAP,
                    () -> CollectionUtil.toMap(getAllDoctorsHigh(), DoctorInfoView::getId));
        } catch (Exception e) {
            logger.error("DoctorService#getAllDoctorsMap():\n {}", e.getMessage(), e);
        }
        return new HashMap<>();
    }

    /**
     * 通知医生信息审核通过
     *
     * @param userId user id
     * @return service result
     */
    public ServiceResult notifyDoctorVerificationPass(int userId, String mobile, String password) {
        ServiceResult result = new ServiceResult();
        try {
            //互联网医院v1.0.4，“我的工作站”原来的，“问诊”、“处方”、“远程会诊”、“双向转诊”、“药事快讯“微信模板消息去掉。2018-11-15
//            wxProvider.notifyDoctorVerityPassDoctor(userId);

            String first = "您好，您的医生认证已通过。";
            String remark = "您现在已经可以使用公众号内所有功能了！网页版（https://doc.ywtinfo.com/user/login）的账号密码为：" + mobile + "   " + password + "（随机密码）";
            String keyword1 = "医生认证";
            String keyword2 = "认证成功";
            String keyword3 = DateUtil.convertToString(new Date(), "yyyy-MM-dd HH:mm");
            String url = bizConfigurer.getYwtHttpsMsiteDomain() + "/thnetdocwe/";
            weChatMsgProvider.sendByTpl1032(userId, "", url, first, remark, keyword1, keyword2, keyword3);

            // 白云公众号
            String urlBy = bizConfigurer.getYwtHttpsMsiteDomain() + "/nfyybyfydocwe/";
            weChatMsgProvider.sendByTpl2017(userId, "", urlBy, first, remark, keyword1, keyword2, keyword3);
            return result.succeed();
        } catch (Exception e) {
            logger.error("notifyDoctorVerificationPass: {}", e.getMessage(), e);
            return result.error(e.getMessage());
        }
    }

    /**
     * 通知医生信息审核不通过
     *
     * @param userId      user id
     * @param auditRemark 审核备注
     * @return service result
     */
    public ServiceResult notifyDoctorVerificationNotPass(int userId, String auditRemark) {
        ServiceResult result = new ServiceResult();
        try {
            //互联网医院v1.0.4，“我的工作站”原来的，“问诊”、“处方”、“远程会诊”、“双向转诊”、“药事快讯“微信模板消息去掉。2018-11-15
//            wxProvider.notifyDoctorVerityNoPassDoctor(userId, auditRemark);

            String first = "您好，您的医生认证未能被通过。";
            String remark = "请根据提示内容修改并重新认证。";
            String keyword1 = DateUtil.convertToString(new Date(), "yyyy-MM-dd HH:mm");
            String keyword2 = "医生认证不通过";
            String url = bizConfigurer.getYwtHttpsMsiteDomain() + "/thnetdocwe/me/editInfo?msg=1";
            weChatMsgProvider.sendByTpl1033(userId, "", url, first, remark, keyword1, keyword2, auditRemark);

            // 白云公众号
            String urlBy = bizConfigurer.getYwtHttpsMsiteDomain() + "/nfyybyfydocwe/me/editInfo?msg=1";
            weChatMsgProvider.sendByTpl2018(userId, "", urlBy, first, remark, keyword1, keyword2, auditRemark);

            return result.succeed();
        } catch (Exception e) {
            logger.error("notifyDoctorVerificationNotPass: {}", e.getMessage(), e);
            return result.error(e.getMessage());
        }
    }


    /**
     * 通过扫码医生团队码 加入该医生团队
     * create by daiyihua
     *
     * @param doctorId
     * @param teamId
     * @return
     */
    public ServiceResult scanQrCodeJoinTeamDoctor(int teamId, int doctorId) {
        ServiceResult result = new ServiceResult();

        Team team = teamRepository.findById(teamId).orElse(null);
        if (Checker.isNone(team) || team.getDeleted()) {
            return result.failed("医生团队不存在");
        }
        Doctor doctor = doctorRepository.findById(doctorId).orElse(null);
        if (Checker.isNone(doctor) || doctor.isDeleted()) {
            return result.failed("该用户还不是医生");
        }

        // 如果已经存在，不管之前是什么状态，都变为已同意
        TeamDoctor td = teamDoctorRepository.getTeamDoctor(teamId, doctorId);
        if (!Checker.isNone(td)) {
            td.setUpdateTime(new Date());
            td.setStatus(1);
            td.setJoinTime(new Date());
            teamDoctorRepository.save(td);
            return result.succeed("处理成功");
        }

        //在团队中添加这个成员
        TeamDoctor teamDoctor = new TeamDoctor();
        int teamDoctorId = idGenerator.genTeamDoctorId();
        teamDoctor.setCreateTime(new Date());
        teamDoctor.setDeleted(false);
        teamDoctor.setDoctorId(doctorId);
        teamDoctor.setId(teamDoctorId);
        teamDoctor.setTeamId(teamId);
        teamDoctor.setStatus(1);         //1-已加入 0-未加入，2-已拒绝
        teamDoctor.setUpdateTime(new Date());
        teamDoctor.setJoinTime(new Date());
        teamDoctorRepository.save(teamDoctor);

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

    public int getInvitationPatientCount(int doctorId) {
        return userUnionsRepository.getPatientAmount(doctorId);
    }

    public Doctor getNormalDoctorById(int id) {
        return doctorRepository.findNormalDoctorById(id);
    }

    public String getDoctorAvatarUrl(int doctorId, String defaultAvatarUrl) {
        String avatar = StringHelper.isNullOrEmpty(defaultAvatarUrl) ? "" : defaultAvatarUrl;
        User user = userRepository.getNormalUserById(doctorId);
        if (user != null && !StringHelper.isNullOrEmpty(user.getAvatar())) {
            avatar = user.getAvatar();
        }
        return avatar;
    }

    public List<DoctorTitle> getDoctorTitleList() {
        return hospitalService.getDoctorTitleListHigh();
    }

    public List<DoctorTitle> getDoctorTitleListByType(int type) {
        return hospitalService.getDoctorTitleListByType(type);
    }


    /**
     * 判断用户是否是审核通过的医生
     *
     * @param userId 用户id
     * @return auditStatus: {@link AuditStatusEnum}
     */
    public int isUserAnAuditPassDoctor(int userId) {
        int auditStatus = AuditStatusEnum.Pending.getValue();
        Doctor doctor = doctorRepository.findNotDeletedDoctorById(userId);
        if (doctor == null) {
            DoctorInfoAudit audit = doctorInfoAuditRepository.getDoctorInfoAudit(userId);
            if (audit != null) {
                auditStatus = audit.getAuditStatus();
            }
        } else if (doctor.getStatus() == 1) {
            //医生已被禁用
            auditStatus = AuditStatusEnum.Banned.getValue();
        } else {
            auditStatus = AuditStatusEnum.Approved.getValue();
        }
        return auditStatus;
    }

    /**
     * 从缓存中得到医生信息
     *
     * @param doctorId
     * @return
     */
    public DoctorInfo getDoctorInfoCacheById(int doctorId) {
        Map<Integer, DoctorInfoView> map = getAllDoctorsMap();
        DoctorInfoView view = map.get(doctorId);

        if (view == null) {
            //用户不存在或用户不是医生类型
            return null;
        }

        DoctorInfo info = new DoctorInfo();
        info.setDoctorId(view.getId());
        info.setName(view.getRealName());
        info.setAvatar(view.getAvatar());
        info.setCity(view.getCity());
        info.setStatus(view.getStatus());
        info.setMobile(view.getMobile());
        info.setSex(view.getSex());

        info.setAvatar2(view.getAvatar2());
        info.setSpecialty(view.getSpecialty());
        info.setBriefIntro(view.getBriefIntro());
        info.setTitle(view.getTitle());
        info.setScheduleStatus(view.getScheduleStatus());
        info.setDoctorStatus(view.getStatus());

        /*  相对于getDoctorInfoById  缺少的数据

        info.setQrCodeUrl(view.getQrCodeUrl());
        info.setAuthType(view.getAuthType());
        info.setRpContent(view.getRpContent());
        info.setRpUrl(view.getRpUrl());
        info.setRpContentPc(view.getRpContentPc());
        info.setRpUrlPc(view.getRpUrlPc());
        info.setPharmacyId(view.getPharmacyId());

        if (view.getConsultFee() == null) {
            info.setConsultAmount(configServiceProvider.getConsultFee());
        } else {
            info.setConsultAmount(view.getConsultFee());
        }
        */

        String[] hospitalIds = view.getHospitalIds().split(",");
        for (String strHospitalId : hospitalIds) {
            if (!StringHelper.isNullOrEmpty(strHospitalId)) {
                int hospitalId = Checker.parseInt(strHospitalId, 0);
                if (hospitalId > 0) {
                    //从缓存读取
                    Hospital hospital = hospitalService.getHospital(hospitalId);
                    if (!Checker.isNone(hospital) && !hospital.isDeleted()) {
                        info.setHospitalId(hospital.getId());
                        info.setHospitalName(hospital.getName());
                        break;
                    }
                }
            }
        }

        String[] deptIds = view.getDeptIds().split(",");
        for (String strDeptId : deptIds) {
            if (!StringHelper.isNullOrEmpty(strDeptId)) {
                int deptId = Checker.parseInt(strDeptId, 0);
                if (deptId > 0) {
                    // 从缓存读取
                    Department department = hospitalService.getDepartment(deptId);
                    if (department != null && !department.isDeleted()) {
                        info.setDeptId(department.getId());
                        info.setDeptName(department.getName());
                        break;
                    }
                }
            }
        }

        return info;
    }

    public ServiceResult updatePatientInfo(int patientId, String idCardNo, String mobile, String name, int sex) {
        Patient patient = patientRepository.findById(patientId).orElse(null);
        ServiceResult serviceResult = new ServiceResult();
        if (patient == null || patient.getDeleted()) {
            return serviceResult.failed("患者不存在");
        } else {
            if (!StringHelper.isNullOrWhiteSpace(idCardNo)) {
                patient.setIdCardNo(idCardNo);
            }
            if (!StringHelper.isNullOrWhiteSpace(mobile)) {
                patient.setMobile(mobile);
            }
            if (!StringHelper.isNullOrWhiteSpace(name)) {
                patient.setRealName(name);
            }
            if (sex > 0) {
                patient.setSex(sex);
            }
            patientRepository.save(patient);
            return serviceResult.succeed();
        }
    }

    /**
     * 获取正在使用的医生定点医院
     *
     * @param doctorId 医生ID
     * @return 定点医院列表
     */
    public List<DoctorFixedPoint> getUsingFixedPointListByDoctorId(int doctorId) {
        // status:状态，0-正常，1-禁用
        return doctorFixedPointRepository.getFixedPointListByDoctorId(doctorId, 0);
    }

    public TeamInfo getTeamInfo(int teamId) {
        TeamInfo info = new TeamInfo();
        Team team = teamRepository.findById(teamId).orElse(null);
        if (team != null) {
            info.setLeadingDoctorId(Checker.getIntegerValue(team.getDoctorId()));
        }
        info.setMembers(teamDoctorRepository.getAllTeamDoctorIdByTeamId(teamId));
        info.setId(teamId);
        return info;
    }

    public List<Integer> getTeamDoctorIds(int teamId) {
        return teamDoctorRepository.getAllTeamDoctorIdByTeamId(teamId);
    }

    public PagedList<TeamListItemObj> getTeamList(int type, int pageIndex, int pageSize, String keyword, int terminal) {
        List<Object> paramList = new ArrayList<>();
        String where = " t.deleted = 0 ";
        if (!StringHelper.isNullOrEmpty(keyword)) {
            where += " and t.name like ? ";
            paramList.add("%" + keyword + "%");
        }
        if (type == GetTeamListTypeEnum.MP_HOME_PAGE.getValue()) {
            where += " and dd.other_show_status = 1 and dd.line_number > 0 ";
        }
        if (type == GetTeamListTypeEnum.MP_LIST_PAGE.getValue()) {
            where += " and (dd.other_show_status = 1 and (dd.line_number = 0 or dd.line_number is null)) ";
        }
        where += String.format(" and dd.type = 3 and dd.terminal = %d ", terminal);

        String fields = "t.id as id, t.name as name, t.intro as `desc`, t.doctor_id as leading_doctor_id, " +
                "d.dept_ids as dept, d.avatar2 as avatar, dd.line_number as line_num, dd.weight as weight";
        String from = "ywt_center.team as t left join ywt_center.doctor as d on t.doctor_id = d.id " +
                " left join ywt_center.display_design as dd on dd.obj_id = t.id ";
        String orderBy = "dd.weight desc, t.create_time desc";
        logger.info("DoctorService#getTeamList:sql: select {} from {} where {} order by {}", fields, from, where, orderBy);
        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, fields, from, where, orderBy, TeamListItemObj.class,
                paramList.toArray());
    }

    public SearchDoctorListByNameResponse searchDoctorListByName(SearchDoctorListByNameRequest request) {
        int hospitalId = request.getHospitalId();
        String doctorName = request.getDoctorName();
        SearchDoctorListByNameResponse.Builder response = SearchDoctorListByNameResponse.newBuilder()
                .setCode(ResultCode.SUCCEED_VALUE).setInfo("处理成功");
        if (hospitalId <= 0 || Checker.isNull(doctorName)) {
            response.setCode(ResultCode.PARAMETER_ERROR_VALUE).setInfo("参数有误");
            return response.build();
        }
        List<com.ywt.gapi.system.Doctor> returnDoctorList = new ArrayList<>();

        List<DoctorHisCode> doctorHisCodeList = findDoctorHisCodeListByDeptCodes(hospitalId, doctorName);
        if (!Checker.isNone(doctorHisCodeList)) {
            for (DoctorHisCode d : doctorHisCodeList) {
                DoctorInfo cacheDoctor = getDoctorInfoCacheById(d.getDoctorId());
                if (Checker.isNone(cacheDoctor)) {
                    continue;
                }
                com.ywt.gapi.system.Doctor doctor = com.ywt.gapi.system.Doctor.newBuilder()
                        .setDoctorId(d.getDoctorId())
                        .setDoctorName(Checker.getStringValue(cacheDoctor.getName()))
                        .setDoctorTitle(Checker.getStringValue(cacheDoctor.getTitle()))
                        .setDoctorSpeciality(Checker.getStringValue(cacheDoctor.getSpecialty()))
                        .setDoctorIntro(Checker.getStringValue(cacheDoctor.getBriefIntro()))
                        .setDoctorAvatar(Checker.getStringValue(cacheDoctor.getAvatar()))
                        .setDoctorDept(Checker.getStringValue(cacheDoctor.getDeptName()))
                        .build();
                returnDoctorList.add(doctor);
            }
        }
        response.addAllDoctor(returnDoctorList);
        return response.build();
    }

    /**
     * 根据医院 id（支持一级二级）和医生姓名查找维护在 doctor_his_code 表里面的医生
     */
    public SearchDoctorListByNameResponse searchDoctorByNameFromMultiHosp(SearchDoctorByNameFromMultiHospRequest request) {
        List<Integer> hospitalIds = request.getHospitalIdList();
        String doctorName = request.getDoctorName();
        SearchDoctorListByNameResponse.Builder response = SearchDoctorListByNameResponse.newBuilder();
        List<com.ywt.gapi.system.Doctor> returnDoctorList = new ArrayList<>();

        List<DoctorHisCode> doctorHisCodeList = findDoctorHisCodeListByMultiHospital(hospitalIds, doctorName);
        for (DoctorHisCode d : doctorHisCodeList) {
            DoctorInfo cacheDoctor = getDoctorInfoCacheById(d.getDoctorId());
            if (Checker.isNone(cacheDoctor)) {
                continue;
            }
            com.ywt.gapi.system.Doctor doctor = com.ywt.gapi.system.Doctor.newBuilder()
                    .setDoctorId(d.getDoctorId())
                    .setDoctorName(Checker.getStringValue(cacheDoctor.getName()))
                    .setDoctorTitle(Checker.getStringValue(cacheDoctor.getTitle()))
                    .setDoctorSpeciality(Checker.getStringValue(cacheDoctor.getSpecialty()))
                    .setDoctorIntro(Checker.getStringValue(cacheDoctor.getBriefIntro()))
                    .setDoctorAvatar(Checker.getStringValue(cacheDoctor.getAvatar()))
                    .setDoctorDept(Checker.getStringValue(cacheDoctor.getDeptName()))
                    .build();
            returnDoctorList.add(doctor);
        }
        response.addAllDoctor(returnDoctorList);
        return response.build();
    }

    private List<DoctorHisCode> findDoctorHisCodeListByDeptCodes(int hospitalId, String doctorName) {
        Hospital hospital = hospitalRepository.findHospitalById(hospitalId);
        int parentId = hospitalId;
        if (!Checker.isNone(hospital) && !Checker.isNone(doctorName)) {
            if (hospital.getParentId() > 0) {
                parentId = hospital.getParentId();
            }
            ArrayList<Object> params = new ArrayList<>();
            String sql = "select * from doctor_his_code where hospital_id = ? and deleted = 0 and doctor_name like ? and dept_code in ( select code from department where sub_hospital_id = ? and is_deleted = 0 ) ";
            params.add(parentId);
            params.add("%" + doctorName.trim() + "%");
            params.add(hospitalId);
            return jdbcTemplate.query(sql, params.toArray(), new BeanPropertyRowMapper<>(DoctorHisCode.class));
        }
        return new ArrayList<>();
    }

    /**
     * 根据医院 id（支持一级二级）和医生姓名查找维护在 doctor_his_code 表里面的医生
     * <p>
     * 基于性能考虑，如果不指定医院或医生姓名，默认返回空列表
     */
    private List<DoctorHisCode> findDoctorHisCodeListByMultiHospital(List<Integer> hospitalIds, String doctorName) {
        if (Checker.isNone(hospitalIds)) return new ArrayList<>();
        if (StringHelper.isNullOrEmpty(doctorName)) return new ArrayList<>();
        List<Hospital> hospitalList = hospitalRepository.getAllHospitalsByIds(hospitalIds);
        List<Hospital> pHospitalList = hospitalList.stream().filter(h -> Checker.getIntegerValue(h.getParentId()) <= 0).collect(Collectors.toList());
        List<Hospital> cHospitalList = hospitalList.stream().filter(h -> Checker.getIntegerValue(h.getParentId()) > 0).collect(Collectors.toList());
        // 二级医院所指向的一级医院 ids
        Set<Integer> relatedParentHospIds = cHospitalList.stream().map(p -> Checker.getIntegerValue(p.getParentId())).collect(Collectors.toSet());
        List<Integer> pHospIds = pHospitalList.stream().map(Hospital::getId).collect(Collectors.toList());
        pHospIds.addAll(relatedParentHospIds);
        String pCase = "";
        String cCase = "";
        String selectDeptCodeSql = "select code from department where is_deleted = 0 ";
        if (!Checker.isNone(pHospitalList)) {
            pCase = String.format(" hospital_id in (%s) ", pHospitalList.stream().map(h -> String.valueOf(h.getId())).collect(Collectors.joining(",")));
        }
        if (!Checker.isNone(cHospitalList)) {
            cCase = String.format(" sub_hospital_id in (%s) ", cHospitalList.stream().map(h -> String.valueOf(h.getId())).collect(Collectors.joining(",")));
        }
        if (!StringHelper.isNullOrEmpty(pCase) && !StringHelper.isNullOrEmpty(cCase)) {
            cCase = " or " + cCase;
        }

        String wCase = pCase + cCase;
        if (!StringHelper.isNullOrEmpty(wCase)) {
            selectDeptCodeSql += String.format(" and (%s) ", wCase);
        }
        String sql = String.format("select * from doctor_his_code where hospital_id in (%s) and deleted = 0 and doctor_name like '%%%s%%' and dept_code in ( %s ) ",
                pHospIds.stream().map(String::valueOf).collect(Collectors.joining(",")), doctorName.trim(), selectDeptCodeSql);
        logger.info("DoctorService#findDoctorHisCodeListByMultiHospital(): sql={}", sql);
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(DoctorHisCode.class));

    }

    public final int CREATE_QR_CODE_TYPE_QR_CODE_URL = 0;
    public final int CREATE_QR_CODE_TYPE_RP_URL = 1;
    public final int CREATE_QR_CODE_TYPE_RP_URL_PC = 2;

    public List<DoctorQrCodeUrl> getDoctorQrCodeUrlListByDoctorId(int doctorId, int hospitalId) {
        return doctorQrCodeUrlRepository.getDoctorQrCodeUrlListByDoctorId(doctorId, hospitalId);
    }

    public String getDoctorQrCodeUrlByTypeNew(List<DoctorQrCodeUrl> list, int type) {
        DoctorQrCodeUrl r = list.stream().filter(i -> Checker.getIntegerValue(i.getType()) == type).findFirst().orElse(null);
        return r == null ? "" : Checker.getStringValue(r.getQrCodeUrl());
    }

    public String getDoctorQrCodeContentByTypeNew(List<DoctorQrCodeUrl> list, int type) {
        DoctorQrCodeUrl r = list.stream().filter(i -> Checker.getIntegerValue(i.getType()) == type).findFirst().orElse(null);
        return r == null ? "" : Checker.getStringValue(r.getQrCodeContent());
    }

    public int getHospitalIdCacheByDoctorId(int doctorId) {
        Map<Integer, DoctorInfoView> map = getAllDoctorsMap();
        DoctorInfoView view = map.get(doctorId);
        if (view == null) {
            //用户不存在或用户不是医生类型
            return 0;
        }
        String[] hospitalIds = Checker.getStringValue(view.getHospitalIds()).split(",");
        for (String strHospitalId : hospitalIds) {
            if (!StringHelper.isNullOrEmpty(strHospitalId)) {
                int hospitalId = Checker.parseInt(strHospitalId, 0);
                if (hospitalId > 0) {
                    return hospitalId;
                }
            }
        }
        return 0;
    }

    public List<String> getGeneralGetAttentionDoctorListHospitalIdsList(int userId, int[] arrHospitalId) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = "";
        if (!Checker.isNone(userId)) {
            whereSql += " user_id = ? and ";
            paramList.add(userId);
        }
        if (arrHospitalId.length > 0) {
            String hospitalSql = "";
            for (int hospitalId : arrHospitalId) {
                if (hospitalId != 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids like ? ";
                    } else {
                        hospitalSql += " or hospital_ids like ? ";
                    }
                    paramList.add("%," + hospitalId + ",%");
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }

        //过滤被禁用医院的医生（医院下有医生，若后台设置这家医院为禁用，这个医院下的所有医生也不显示在app列表中）
        String idSql = "select id from hospital where status = 1 or is_deleted = 1;";
        List<Integer> hospitalIds = jdbcTemplate.queryForList(idSql, Integer.class);

        if (hospitalIds != null && hospitalIds.size() > 0) {
            String hospitalSql = "";

            for (Integer hospitalId : hospitalIds) {
                if (hospitalId > 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids <> ? ";
                    } else {
                        hospitalSql += " and hospital_ids <> ? ";
                    }
                    paramList.add("," + hospitalId + ",");
                }
            }
            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }
        whereSql += " doctor_status = 0 and union_status = 0 ";
        String sql = new StringBuilder("select hospital_ids from user_unions_doctor_info_view where ").append(whereSql).append(" group by  hospital_ids; ").toString();
        return jdbcTemplate.queryForList(sql, paramList.toArray(), String.class);
    }

    public List<String> getDoctorListNewHospitalIdsList(int userId, int[] arrHospitalId, int terminal) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = "";
        if (arrHospitalId.length > 0) {
            String hospitalSql = "";
            for (int hospitalId : arrHospitalId) {
                if (hospitalId != 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids like ? ";
                    } else {
                        hospitalSql += " or hospital_ids like ? ";
                    }
                    paramList.add("%," + hospitalId + ",%");
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }
        //过滤被禁用医院的医生（医院下有医生，若后台设置这家医院为禁用，这个医院下的所有医生也不显示在app列表中）
        String idSql = "select id from hospital where status = 1 or is_deleted = 1;";
        List<Integer> hospitalIds = jdbcTemplate.queryForList(idSql, Integer.class);

        if (hospitalIds != null && hospitalIds.size() > 0) {
            String hospitalSql = "";

            for (Integer hospitalId : hospitalIds) {
                if (hospitalId > 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids <> ? ";
                    } else {
                        hospitalSql += " and hospital_ids <> ? ";
                    }

                    paramList.add("," + hospitalId + ",");
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ")";
            }
        }
        // 过滤开通问诊业务的医生
        if (!StringHelper.isNullOrEmpty(whereSql)) {
            whereSql += " and ";
        }
        whereSql += "schedule_status & 8 = 8";

        // 如果终端是白云的话，那就只显示白云相关的医院，以及当前用户关注的医生
        if (terminal == TerminalEnum.NFYYBYFY_WXAPP.getValue()) {
            // 该查找不理解的话，可以参考：wapapi 项目的 /doctor/getDoctorListNew 方法
            whereSql += " and ( hospital_ids like ?  or user_id > 0 ) ";
            paramList.add("%," + Constants.NFYYBYFY_HOSPITAL_ID + ",%");
        }

        String from = "`ywt_center`.`doctor` `d` join `ywt_center`.`user` `u`" +
                " on(`d`.`id` = `u`.`id`) and (`d`.`is_deleted` = 0) and (`u`.`is_deleted` = 0) and (`u`.`user_type` & 2 = 2) and (`d`.`status` = 0) " +
                " left join `ywt_center`.`user_unions` `uu`" +
                " on(`uu`.`union_user_id` = `u`.`id`) and (`uu`.`status` = 0) and (`uu`.`type` = 4) and (`uu`.`user_id` = " + userId + ")";

        String sql = new StringBuilder("select `d`.`hospital_ids` AS `hospital_ids` from ").append(from).append(" where ").append(whereSql).append(" group by hospital_ids; ").toString();
        return jdbcTemplate.queryForList(sql, paramList.toArray(), String.class);
    }

    public List<Integer> getMyDoctorId(int userId) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = "";
        if (!Checker.isNone(userId)) {
            whereSql += " user_id = ? and ";
            paramList.add(userId);
        }

        whereSql += " union_status = 0 ";
        String sql = new StringBuilder("select union_user_id from user_unions_doctor_info_view where ").append(whereSql).toString();
        return jdbcTemplate.queryForList(sql, paramList.toArray(), Integer.class);
    }


    public List<Integer> getMyDoctorHospId(int userId, int terminal, List<Integer> getAreaHospitalIdList) {
        List<Integer> doctorIdList = getMyDoctorId(userId);
        List<Integer> hospIdList = new ArrayList<>();
        List<Integer> finalHospIdList = new ArrayList<>();
        if (!Checker.isNone(doctorIdList) && doctorIdList.size() > 0) {
            String value = "true";
            hospIdList = commonDoctorSettingRepository.findDoctorHospId(doctorIdList, terminal, value);
            if (!Checker.isNone(hospIdList) && hospIdList.size() > 0) {
                for (int i = 0; i < hospIdList.size(); i++) {
                    if (!finalHospIdList.contains(hospIdList.get(i))) {
                        finalHospIdList.add((hospIdList.get(i)));
                    }
                }
                finalHospIdList = getFinalList(finalHospIdList, getAreaHospitalIdList);
//                return finalHospIdList;
            }
        }
        return finalHospIdList;
    }

    //获取医生所属医院与可用医院的交集
    public List<Integer> getFinalList(List<Integer> doctorHospIdList, List<Integer> getAreaHospitalIdList) {
        List<Integer> list = new ArrayList<>();
        for (Integer areaHospId : getAreaHospitalIdList) {
            for (Integer docHospId : doctorHospIdList) {
                if (docHospId.equals(areaHospId)) {
                    list.add(docHospId);
                }
            }
        }
        return list;
    }


    public List<Integer> getDoctorListNewHospitalIdsLs(int userId, int terminal) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = "";

        // 过滤开通问诊业务的医生
        if (!StringHelper.isNullOrEmpty(whereSql)) {
            whereSql += " and ";
        }
        whereSql += "schedule_status & 8 = 8 and";

        // 如果终端是白云的话，那就只显示白云相关的医院，以及当前用户关注的医生
//        if (terminal == TerminalEnum.NFYYBYFY_WXAPP.getValue()) {
//            // 该查找不理解的话，可以参考：wapapi 项目的 /doctor/getDoctorListNew 方法
//            whereSql += " and ( d.hospital_ids like ?  or user_id > 0 ) ";
//            paramList.add("%," + Constants.NFYYBYFY_HOSPITAL_ID + ",%");
//        }


        whereSql += " `c`.`terminal` = ? and";
        paramList.add(terminal);


        whereSql += " c.type = 2 and c.value = ? ";
        paramList.add("true");

        String from = "`ywt_center`.`doctor` `d` join `ywt_center`.`user` `u`" +
                " on(`d`.`id` = `u`.`id`)" +
                "and (`d`.`is_deleted` = 0) and (`u`.`is_deleted` = 0) and (`u`.`user_type` & 2 = 2) and (`d`.`status` = 0) " +
                " left join `ywt_center`.`user_unions` `uu`" +
                " on(`uu`.`union_user_id` = `u`.`id`) and (`uu`.`status` = 0) and (`uu`.`type` = 4) and (`uu`.`user_id` = " + userId + ")" +
                " left join `ywt_center`.`common_doctor_setting` `c`" +
                " on(`d`.`id` = `c`.`doctor_id`)";

        String sql = new StringBuilder("select `d`.`id` AS `id` from ").append(from).append(" where ").append(whereSql).toString();
        return jdbcTemplate.queryForList(sql, paramList.toArray(), Integer.class);
    }

    public List<Integer> getNewMyDoctorHospId(int userId, int terminal, List<Integer> getAreaHospitalIdList) {
        List<Integer> doctorIdList = getDoctorListNewHospitalIdsLs(userId, terminal);
        List<Integer> hospIdList = new ArrayList<>();
        List<Integer> finalHospIdList = new ArrayList<>();
        if (!Checker.isNone(doctorIdList) && doctorIdList.size() > 0) {
            String status = "true";
            hospIdList = commonDoctorSettingRepository.findDoctorHospId(doctorIdList, terminal, status);
            if (!Checker.isNone(hospIdList) && hospIdList.size() > 0) {
                for (int i = 0; i < hospIdList.size(); i++) {
                    if (!finalHospIdList.contains(hospIdList.get(i))) {
                        finalHospIdList.add((hospIdList.get(i)));
                    }
                }
                finalHospIdList = getFinalList(finalHospIdList, getAreaHospitalIdList);
//                return finalHospIdList;
            }
        }
        return finalHospIdList;
    }

    /**
     * 得到用户关注的医生列表
     * <p>
     * create by daiyihua
     *
     * @param pageIndex 页码
     * @param pageSize  页大小
     * @param userId    用户Id
     * @return
     */
    public PagedList<AttentionDoctorInfo> generalGetNewAttentionDoctorList(int pageIndex, int pageSize, int userId, String name, int[] arrHospitalId, int deptId, int terminal) {

        List<Object> paramList = new ArrayList<>();
        String whereSql = "";

        whereSql += "((`t`.`deleted` = 0) and (`u`.`is_deleted` = 0) and (`d`.`is_deleted` = 0) and (`t`.`type` = 4)) and ";

        whereSql += " `d`.`status` = 0 and `t`.status = 0 and";

        if (!Checker.isNone(name)) {
            whereSql += " real_name like ? and ";
            paramList.add("%" + name + "%");
        }

        if (!Checker.isNone(userId)) {
            whereSql += " user_id = ? and ";
            paramList.add(userId);
        }

        if (arrHospitalId.length > 0) {
            String hospitalSql = "";
            for (int hospitalId : arrHospitalId) {
                if (hospitalId != 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids like ? ";
                    } else {
                        hospitalSql += " or hospital_ids like ? ";
                    }
                    paramList.add("%," + hospitalId + ",%");
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ") and ";
            }
        }

        if (deptId != 0) {
            whereSql += " dept_ids like ? and ";
            paramList.add("%," + deptId + ",%");
        }


        if (terminal > 0) {
            whereSql += " `c`.`terminal` = ? and";
            paramList.add(terminal);
        }


        whereSql += " c.type = 2 and c.value = ? and";
        paramList.add("true");

        whereSql += " t.status = 0 and ";

        //过滤被禁用医院的医生（医院下有医生，若后台设置这家医院为禁用，这个医院下的所有医生也不显示在app列表中）
        String idSql = "select id from hospital where status = 1 or is_deleted = 1;";
        List<Integer> hospitalIds = jdbcTemplate.queryForList(idSql, Integer.class);

        if (hospitalIds != null && hospitalIds.size() > 0) {
            String hospitalSql = "";

            for (Integer hospitalId : hospitalIds) {
                if (hospitalId > 0) {
                    if ("".equals(hospitalSql)) {
                        hospitalSql += " hospital_ids <> ? ";
                    } else {
                        hospitalSql += " and hospital_ids <> ? ";
                    }

                    paramList.add("," + hospitalId + ",");
                }
            }

            if (!"".equals((hospitalSql))) {
                whereSql += "(" + hospitalSql + ")";
            }
        }


        String fields = "`t`.`id` AS `id`,`t`.`user_id` AS `user_id`,`t`.`union_user_id` AS `union_user_id`,`u`.`real_name` AS `real_name`,`u`.`mobile` AS `mobile`," +
                "`u`.`user_type` AS `user_type`,`u`.`sex` AS `sex`,`u`.`avatar` AS `avatar`,`u`.`city` AS `city`," +
                "`d`.`hospital_ids` AS `hospital_ids`,`d`.`dept_ids` AS `dept_ids`,`d`.`status` AS `doctor_status`," +
                "`d`.`title` AS `title`,`d`.`specialty` AS `specialty`,`d`.`avatar2` AS `avatar2`," +
                "`c`.`value` AS `schedule_status`, `c`.`terminal` AS `terminal`," +
                "`t`.`type` AS `union_type`,`t`.`status` AS `union_status`,`t`.`create_time` AS `create_time`,`t`.`update_time` AS `update_time`";

//        String from = "`ywt_center`.`doctor` `d` join `ywt_center`.`user` `u`" +
//                " on(`d`.`id` = `u`.`id`) and (`d`.`is_deleted` = 0) and (`u`.`is_deleted` = 0) and (`u`.`user_type` = 2) and (`d`.`status` = 0) and (`u`.`id` <> " + userId + ")" +
//                " left join `ywt_center`.`user_unions` `uu`" +
//                " on(`uu`.`union_user_id` = `u`.`id`) and (`uu`.`status` = 0) and (`uu`.`type` = 4) and (`uu`.`user_id` = " + userId + ")";
        String from = "`ywt_center`.`user_unions` `t` left join `ywt_center`.`user` `u` on(`t`.`union_user_id` = `u`.`id`)left join `doctor` `d` on(`u`.`id` = `d`.`id`) " +
                " left join `ywt_center`.`common_doctor_setting` `c`" +
                "on(`d`.`id` = `c`.`doctor_id`)";


        logger.info("fields {}", fields);
        logger.info("from {}", from);
        logger.info("whereSql {}", whereSql);
        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, fields, from, whereSql, "create_time desc",
                AttentionDoctorInfo.class, paramList.toArray());

    }

    public SaveDoctorHisCodeListResponse saveDoctorHisCodeList(SaveDoctorHisCodeListRequest request) {
        SaveDoctorHisCodeListResponse.Builder builder = SaveDoctorHisCodeListResponse.newBuilder();
        Result.Builder result = Result.newBuilder();
        result.setCode(ResultCode.SUCCEED);
        result.setInfo("处理成功");
        try {
            List<com.ywt.gapi.doctor.DoctorHisCode> doctorHisCodeList = request.getDoctorHisCodeList();
            if (!Checker.isNone(doctorHisCodeList)) {
                List<DoctorHisCode> newDoctorHisCodeList = new ArrayList<>();
                for (com.ywt.gapi.doctor.DoctorHisCode hisCode : doctorHisCodeList) {
                    List<DoctorHisCode> entryList = doctorHisCodeRepository.getAllDoctorByHisCode(hisCode.getHospitalId(), hisCode.getDoctorCode());
                    if (!Checker.isNone(entryList)) {
                        // 如果存在科室一样的，那么就跳过
                        DoctorHisCode isExist = entryList.stream().filter(p -> p.getDeptCode().equals(hisCode.getDeptCode())).findFirst().orElse(null);
                        if (!Checker.isNone(isExist)) {
                            continue;
                        }
                        // 科室不一样，但需要获取一些公共的信息，所以取第一条记录
                        isExist = entryList.get(0);
                        // 添加的条件，1、之前已经有写入到doctor_his_code表的记录，2、写入的是不同的科室
                        DoctorHisCode doctorHisCode = new DoctorHisCode();
                        doctorHisCode.setDoctorId(isExist.getDoctorId());
                        doctorHisCode.setHospitalId(hisCode.getHospitalId());
                        doctorHisCode.setDeptCode(hisCode.getDeptCode());
                        doctorHisCode.setHisCode(hisCode.getDoctorCode());
                        doctorHisCode.setDoctorName(hisCode.getDoctorName());
                        doctorHisCode.setDeleted(false);
                        doctorHisCode.setDoctorJobNum(Checker.getStringValue(isExist.getDoctorJobNum()));
                        newDoctorHisCodeList.add(doctorHisCode);
                    }
                }
                if (!Checker.isNone(newDoctorHisCodeList)) {
                    doctorHisCodeRepository.saveAll(newDoctorHisCodeList);
                }
            }
        } catch (Exception e) {
            result.setCode(ResultCode.APP_ERROR).setInfo("系统异常：" + Checker.getStringValue(e.getMessage()));
            logger.error("DoctorService#saveDoctorHisCodeList(): {}", e.getMessage(), e);
        }
        return builder.setResult(result.build()).build();
    }
}
