package com.ywt.outpatient.service.rpc;

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.paycenter.WeChatCorpPayToWalletResponse;
import com.ywt.gapi.user.AccountBalanceResponse;
import com.ywt.gapi.user.CheckHasCardRequest;
import com.ywt.gapi.user.GetCommonWxPushRequest;
import com.ywt.gapi.user.GetCommonWxPushResponse;
import com.ywt.outpatient.core.BaseResponse;
import com.ywt.outpatient.core.PagedList;
import com.ywt.outpatient.core.SqlHelper;
import com.ywt.outpatient.core.utils.Checksum;
import com.ywt.outpatient.core.utils.IdCardUtil;
import com.ywt.outpatient.core.utils.MoneyUtil;
import com.ywt.outpatient.domain.entity.center.*;
import com.ywt.outpatient.domain.models.enums.*;
import com.ywt.outpatient.service.rpc.common.PayCenterProvider;
import com.ywt.outpatient.service.rpc.common.ServiceResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
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.sql.Types;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by huangguoping.
 */
@Service
public class  UserService {
    private static Logger logger = LoggerFactory.getLogger(UserService.class);

    @Autowired
    UserRepository userRepository;

    @Autowired
    private PatientRepository patientRepository;

    @Autowired
    private SequenceRepository sequenceRepository;

    @Autowired
    private IdGenerator idGenerator;

    @Autowired
    private UnionDoctorRepository unionDoctorRepository;

    @Autowired
    private SqlHelper sqlHelperYwtCenter;

    @Autowired
    private BankCardRepository bankCardRepository;

    @Autowired
    private AccountRepository accountRepository;

    @Autowired
    private AccountDetailRepository accountDetailRepository;

    @Autowired
    private WithdrawApplicationRepository withdrawApplicationRepository;

    @Autowired
    private FeedbackRepository feedbackRepository;

    @Autowired
    private SnsUserRepository snsUserRepository;

    @Autowired
    private WxappUserSessionRepository wxappUserSessionRepository;

    @Autowired
    private MedicalCardRepository medicalCardRepository;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private MedicalRecordsRepository medicalRecordsRepository;

    @Autowired
    private LoginLogRepository loginLogRepository;

    @Autowired
    private SnsUserInfoRepository snsUserInfoRepository;

    @Autowired
    private WithdrawOrderRepository withdrawOrderRepository;

    @Autowired
    private PayCenterProvider payCenterProvider;

    @Autowired
    private UserUnionsRepository userUnionsRepository;

    @Autowired
    private AgentRepository agentRepository;

    @Autowired
    private DrugProviderRepository drugProviderRepository;

    @Autowired
    private HospitalRepository hospitalRepository;

    @Autowired
    private AttentionRepository attentionRepository;

    @Autowired
    EntityManager entityManager;

    @Autowired
    private UserPatientRepository userPatientRepository;

    @Autowired
    private MedRecordSettingRepository medRecordSettingRepository;

    @Autowired
    private UserSignRepository userSignRepository;

    @Autowired
    private CommonWxPushRepository commonWxPushRepository;

    /**
     * 根据手机号查找用户
     *
     * @param mobile
     * @return
     */
    public User findByMobile(String mobile) {
        if (!Checker.isNone(mobile)) {
            return userRepository.findByMobile(mobile);
        }
        return null;
    }

    public void saveUser(User user) {
        userRepository.save(user);
    }

    public User getUser(int userId, String mobile, String username) {
        String sql = "";
        List<Object> args = new LinkedList<>();
        List<Integer> types = new LinkedList<>();

        if (userId > 0) {
            sql += "user_id = ? ";
            args.add(userId);
            types.add(Types.INTEGER);
        }

        if (!StringHelper.isNullOrWhiteSpace(mobile)) {
            if (!"".equals(sql)) {
                sql += "and ";
            }

            sql += "mobile = ? ";
            args.add(mobile);
            types.add(Types.VARCHAR);
        }

        if (!StringHelper.isNullOrWhiteSpace(username)) {
            if (!"".equals(sql)) {
                sql += "and ";
            }

            sql += "user_name = ? ";
            args.add(username);
            types.add(Types.VARCHAR);
        }

        if ("".equals(sql)) {
            return null;
        }

        sql = "select * from user where " + sql + "limit 1;";
        return jdbcTemplate.queryForObject(sql, args.toArray(), types.stream().mapToInt(i -> i).toArray(), User.class);
    }

    /**
     * 根据手机号查找用户，如果用户不存在，根据参数 registerIfNotExist 来判断是否需要自动注册
     *
     * @param mobile
     * @param registerIfNotExist
     * @param ip
     * @return
     */
    public User getUser(String mobile, boolean registerIfNotExist, String ip) {
        User user = userRepository.getUserByMobile(mobile);

        if (user == null && registerIfNotExist) {
            user = registerByMobile(mobile, ip);
        }

        return user;
    }


    /**
     * 根据手机号自动注册（普通用户）
     *
     * @param mobile
     * @return
     */
    public User registerByMobile(String mobile, String ip) {
        int userId = idGenerator.generateUserId();
        User user = new User();
        user.setId(userId);
        user.setUsername(getRandomUserName());
        user.setRealname(null);
        user.setIdcertificatetype(null);
        user.setIdcertificateno(null);
        user.setMobile(mobile);
        user.setSex(SexEnum.Unknown.getValue());
        user.setAge(null);
        user.setAvatar(null);
        user.setBirthday(null);
        user.setPassword("");
        user.setSalt("");
        user.setCreatetime(new Date());
        user.setRegister_ip(ip);
        user.setProvince(null);
        user.setCity(null);
        user.setArea(null);
        user.setStatus(UserStatusEnum.Normal.getValue());
        user.setDeleted(false);
        user.setUsertype(UserTypeEnum.General.getValue());

        userRepository.save(user);
        return user;
    }

    /**
     * 添加银行卡
     * 备注：1、暂时只能添加一张银行卡，所以添加的时候需要做判断
     *
     * @param name
     * @param cardno
     * @param bankName
     * @param cardType
     * @param userId
     * @return
     */
    public ServiceResult addBankCard(String name, String cardno, String bankName, int cardType, int userId, String mobile) {
        ServiceResult result = new ServiceResult();
        if (name == null || "".equals(name.trim())) {
            return result.failed("姓名不能为空");
        }
        if (cardno == null || "".equals(cardno.trim()) || cardno.length() > 19 || cardno.length() < 16) {
            return result.failed("银行卡号位数不对");
        }
        if (bankName == null || "".equals(bankName.trim())) {
            return result.failed("开户行不能为空");
        }
        if (!PhoneNumChecker.isPhoneNum(mobile)) {
            return result.failed("手机号码错误");
        }

        //根据用户id得到手机号
        User user = userRepository.findById(userId).orElse(null);

        if (user != null) {

            //判断是否已经添加银行卡，如果添加了银行卡，那就不能再添加了
            int count = bankCardRepository.getBankCardCountByUserId(userId);
            if (count > 0)
                return result.failed("只能添加一张银行卡");

            int id = idGenerator.generateBankCardId();
            BankCard bankCard = new BankCard();
            bankCard.setId(id);
            bankCard.setCardNo(cardno.trim());
            bankCard.setBankName(bankName.trim());
            bankCard.setBranchName("");
            bankCard.setCreateTime(new Date());
            bankCard.setDeleted(false);
            bankCard.setMobile(mobile.trim());
            bankCard.setRealName(name.trim());
            bankCard.setUserId(user.getId());
            bankCard.setCardType(BankCardEnum.valueOf(1).getValue());

            //保存银行卡信息
            bankCardRepository.save(bankCard);

            Map<String, Object> map = new HashMap<>();
            map.put("cardId", id);
            map.put("cardNo", cardno);

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

    /**
     * 获取银行卡列表
     *
     * @param userId
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public PagedList<BankCard> getBankCardList(int userId, int pageIndex, int pageSize) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = "";

        if (!StringHelper.isNullOrEmpty(userId + "")) {
            whereSql = " user_id = ? ";
            paramList.add(userId);
        }
        whereSql += " and is_deleted = 0 ";
        PagedList<BankCard> pagedList = sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, " create_time desc", BankCard.class, paramList.toArray());

        return pagedList;
    }

    /**
     * 根据用户id查看账户余额
     *
     * @param userId
     * @return
     */
    public double getBalanceByUserId(int userId) {
        List<Account> accountList = accountRepository.findByUserId(userId);
        Account account = null;
        if (accountList != null && accountList.size() > 0)
            account = accountList.get(0);

        return (account != null) ? account.getBalance() / 100d : 0d;
    }

    /**
     * 根据用户id获取账户余额，返回总额和可提现余额
     *
     * @param userId 用户id
     * @return
     */
    public AccountBalanceResponse getBalanceByUserIdNew(int userId) {
//        List<Account> accountList = accountRepository.findByUserId(userId);
//        Account account = null;
//        if (accountList != null && accountList.size() > 0)
//            account = accountList.get(0);
//        double balance = 0d;
//        double withdrawableBalance = 0d;
//        if (account != null) {
//            // 数据库的金额以“分”为单位
//            balance = account.getBalance() / 100d;
//            long DAY_IN_MS = 1000 * 60 * 60 * 24;
//            Date aWeekAgo = new Date(System.currentTimeMillis() - (7 * DAY_IN_MS));
//            List<AccountDetail> details = accountDetailRepository.getTransactionRecordAfterDate(userId, DateUtil.convertToString(aWeekAgo));
//            if (details != null && !details.isEmpty()) {
//                int lastWeekAmount = 0;
//                for (AccountDetail detail : details) {
//                    if (detail.getAmount() > 0) {
//                        lastWeekAmount += detail.getAmount();
//                        System.out.println("amount " + detail.getAmount());
//                    }
//                }
//                withdrawableBalance = balance - lastWeekAmount / 100d;
//                if (withdrawableBalance < 0) withdrawableBalance = 0d;
//            } else {
//                withdrawableBalance = balance;
//            }
//        }
        long DAY_IN_MS = 1000 * 60 * 60 * 24;
        Date aWeekAgo = new Date(System.currentTimeMillis() - (7 * DAY_IN_MS));
        StoredProcedureQuery storedProcedureQuery = entityManager.createStoredProcedureQuery("get_user_balance")
                .registerStoredProcedureParameter("user_id", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("withdrawable_not_include", Date.class, ParameterMode.IN)
                .registerStoredProcedureParameter("total_balance", Integer.class, ParameterMode.OUT)
                .registerStoredProcedureParameter("withdrawable_balance", Integer.class, ParameterMode.OUT)
                .setParameter("user_id", userId)
                .setParameter("withdrawable_not_include", aWeekAgo);
        storedProcedureQuery.execute();
        double balance = (Integer) storedProcedureQuery.getOutputParameterValue("total_balance") / 100d;
        double withdrawableBalance = (Integer) storedProcedureQuery.getOutputParameterValue("withdrawable_balance") / 100d;
        Result result = Result.newBuilder().setCode(ResultCode.SUCCEED).setInfo("处理成功").build();
        return AccountBalanceResponse.newBuilder()
                .setResult(result)
                .setTotalBalance(balance)
                .setWithdrawableBalance(withdrawableBalance)
                .build();
    }

    /**
     * 创建微信提现订单
     *
     * @param userId 用户id
     * @param amount 金额
     * @param openId openId
     * @param ipAddr ip地址
     * @return ServiceResult
     */
    public ServiceResult createWithdrawOrder(int userId, int amount, String openId, String ipAddr) {
        ServiceResult result = new ServiceResult();
        int minAmount = 100;
        if (amount < minAmount) {
            return result.failed("提现金额必须大于等于1元");
        }
        // todo: 南方医科大学南方医院白云分院v1.7.7（优化提现提示），对总金额和当天提现次数做限制
        // todo: 互联网医院v4.5.6（医生提现优化），对总金额和当天提现次数做限制
        int maxAmountInt = 50000;
        if (amount > maxAmountInt) {
            return result.failed("每日提现金额不能超过500元");
        }
        // 得到当天的开始时间
        Date date = DateUtil.stringToDate(DateUtil.formatDate(new Date(), DateUtil.DADE_FROMAT_YMD), DateUtil.DADE_FROMAT_YMD);
        // 判断总金额，每日最多5百
        int hasWithdrawAmount = withdrawOrderRepository.hasWithdrawAmount(userId, date);
        if ((hasWithdrawAmount + amount) > maxAmountInt) {
            return result.failed("每日提现金额不能超过500元");
        }
        // 判断次数，每日10次
        int maxCount = 10;
        int count = withdrawOrderRepository.checkCount(userId, date);
        logger.error("createWithdrawOrder:userId:{},\t date:{}, \t count:{}", userId, date, count);
        if (count > maxCount) {
            return result.failed("每日最多提现10次");
        }
        AccountBalanceResponse response = getBalanceByUserIdNew(userId);
        if (amount > MoneyUtil.yuan2Cent(response.getWithdrawableBalance())) {
            return result.failed("提现金额不能大于用户可提现的余额");
        }
        // 生成提现订单
        String orderNo = idGenerator.generateOrderNo("");
        WithdrawOrder order = new WithdrawOrder();
        order.setAmount(amount);
        order.setCreateTime(new Date());
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setId(idGenerator.genWithdrawOrderId());
        order.setOpenId(openId);
        order.setIpAddress(ipAddr);
        order.setStatus(0);
        withdrawOrderRepository.save(order);
        Map<String, Object> data = new HashMap<>();
        data.put("orderNo", orderNo);
        return result.succeed("处理成功", data);
    }

    /**
     * 发起提现订单支付
     *
     * @param orderNo 订单号
     * @return
     */
    public ServiceResult withdrawOrderPay(String orderNo, String openId) {
        ServiceResult result = new ServiceResult();

        WithdrawOrder order = withdrawOrderRepository.findByOrderNo(orderNo);
        if (order == null) {
            return result.failed("找不到该订单记录！");
        }
        String ipAddr = order.getIpAddress();
        int amount = order.getAmount();// 以分为单位
        int userId = order.getUserId();
        // 调用企业支付
        WeChatCorpPayToWalletResponse payResponse = payCenterProvider.withdrawToWeChat(orderNo, openId, amount, ipAddr);
        if (payResponse == null || payResponse.getCode() > 0) {
            return result.failed("处理失败");
        }
        // 支付成功更新提现订单
        order.setStatus(1);
        order.setOpenId(openId);
        order.setInternalPayNo(payResponse.getInternalPayNo());
        order.setMchId(payResponse.getMchId());
        order.setPaymentNo(payResponse.getPaymentNo());
        withdrawOrderRepository.save(order);
        // 更新账户余额
//        Account account = accountRepository.getByUserId(userId);
//        if (account == null) {
//            account = new Account();
//            account.setId(idGenerator.genAccountId());
//            account.setCreateTime(new Date());
//            account.setStatus(AccountStatusEnum.Normal.getValue());
//            account.setUserId(userId);
//            account.setDeleted(false);
//        }
//        account.setBalance(account.getBalance() - amount);
//        //记录明细
//        AccountDetail detail = new AccountDetail();
//        detail.setId(idGenerator.genAccountDetailId());
//        detail.setCreateTime(new Date());
//        detail.setStatus(1);
//        detail.setType(AccountDetailTypeEnum.Withdraw.getValue());
//        detail.setDeleted(false);
//        detail.setBalance(account.getBalance());
//        detail.setAmount(-amount);
//        detail.setUserId(userId);
//        detail.setAccountId(account.getId());
//        detail.setTitle(AccountDetailTypeEnum.Withdraw.getDisplayName());
//        detail.setRemark("");
//        detail.setObjectId(String.valueOf(order.getId()));// 记录提现订单ID
//        accountDetailRepository.save(detail);
//        accountRepository.save(account);

        StoredProcedureQuery storedProcedureQuery = entityManager.createStoredProcedureQuery("add_user_account_detail")
                .registerStoredProcedureParameter("user_id", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("type", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("amount", Integer.class, ParameterMode.IN)
                .registerStoredProcedureParameter("title", String.class, ParameterMode.IN)
                .registerStoredProcedureParameter("remark", String.class, ParameterMode.IN)
                .registerStoredProcedureParameter("object_id", String.class, ParameterMode.IN)
                .registerStoredProcedureParameter("result_code", Integer.class, ParameterMode.OUT)
                .registerStoredProcedureParameter("total_balance", Integer.class, ParameterMode.OUT)
                .setParameter("user_id", userId)
                .setParameter("type", AccountDetailTypeEnum.Withdraw.getValue())
                .setParameter("amount", -amount)
                .setParameter("title", AccountDetailTypeEnum.Withdraw.getDisplayName())
                .setParameter("remark", "")
                .setParameter("object_id", String.valueOf(order.getId()));
        storedProcedureQuery.execute();
        Integer resultCode = (Integer) storedProcedureQuery.getOutputParameterValue("result_code");
        Integer totalBalance = (Integer) storedProcedureQuery.getOutputParameterValue("total_balance");
        if (resultCode == 0) {
            return result.succeed("操作成功");
        } else {
            return result.failed("处理失败");
        }
    }

    /**
     * 账户明细列表(根据)
     *
     * @param userId
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public PagedList<AccountDetail> getAccountDetailList(int userId, int pageIndex, int pageSize) {

        List<Object> paramList = new ArrayList<>();
        String whereSql = "";
        if (!StringHelper.isNullOrEmpty(userId + "")) {
            whereSql = " user_id = ? ";
            paramList.add(userId);
        }
        whereSql += " and deleted = 0 ";
        PagedList<AccountDetail> pagedList = sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, " create_time desc", AccountDetail.class, paramList.toArray());
        return pagedList;
    }

    /**
     * 用户发起提现申请
     * 思路：1、添加之前需要对金额做判断（大于0，不能大于账号余额）；
     *
     * @param userId
     * @param amount
     * @param cardId
     * @return
     */
    public ServiceResult withdraw(int userId, double amount, int cardId) {
        ServiceResult result = new ServiceResult();
        //先做判断
        if (amount <= 0) {
            return result.failed("提现金额必须大于0");
        }
        List<Account> accountList = accountRepository.findByUserId(userId);
        Account account = null;
        if (accountList != null && accountList.size() > 0) {
            account = accountList.get(0);
            if (account != null) {
                if (amount > (double) account.getBalance()) {
                    return result.failed("提现金额不能大于用户余额");
                }
                //往提现表里面添加记录
                WithdrawApplication withdrawApplication = new WithdrawApplication();
                withdrawApplication.setCreateTime(new Date());
                //状态（1-待审核，2-审核通过，3-审核不通过）
                withdrawApplication.setAuditStatus(1);
                //提现状态（1-待处理，2-处理中，3-提现失败，4-提现成功）
                withdrawApplication.setStatus(1);
                withdrawApplication.setAmount(-amount);
                withdrawApplication.setUserId(userId);
                withdrawApplication.setRemark("");
                withdrawApplication.setDeleted(false);
                withdrawApplication.setId(idGenerator.generateWithdrawApplicationId());
                withdrawApplication.setCardId(cardId);
                //保存到数据库
                withdrawApplicationRepository.save(withdrawApplication);
            } else
                return result.failed("处理失败");
        } else
            return result.failed("处理失败");

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

    /**
     * 添加反馈
     *
     * @param userId
     * @param content
     * @param origin
     * @return
     */
    public ServiceResult addFeedback(int userId, String content, int origin) {
        ServiceResult result = new ServiceResult();
//        //根据userId找到用户对象，并判断用户对象是否为空
//        User user = userRepository.findById(userId).orElse(null);
//
//        if (user != null) {
        // 添加反馈
        Feedback feedback = new Feedback();
        feedback.setContent(content.trim());
        feedback.setCreateTime(new Date());
        feedback.setDeleted(false);
        feedback.setId(idGenerator.generateFeedbackId());
        feedback.setOrigin(origin);
        feedback.setRemark("");
        feedback.setStatus(1);
        feedback.setUserId(userId);
        feedbackRepository.save(feedback);
        return result.succeed("处理成功");
//        }
//
//        return result.failed("处理失败");
    }

    public List<WithdrawApplication> getWithdrawApplication(int userId, int pageIndex, int pageSize) {

        List<Object> paramList = new ArrayList<>();
        String whereSql = "";
        if (!StringHelper.isNullOrEmpty(userId + "")) {
            whereSql = " user_id = ? ";
            paramList.add(userId);
        }
        whereSql += " and is_deleted = 0 ";
        PagedList<WithdrawApplication> pagedList = sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, " create_time desc", WithdrawApplication.class, paramList.toArray());
        List<WithdrawApplication> list = pagedList.getItems();
        return list;
    }

    /**
     * 删除银行卡
     *
     * @param userId
     * @param cardId
     * @return
     */
    public ServiceResult delBankcard(int userId, int cardId) {

        ServiceResult result = new ServiceResult();
        BankCard bankCard = bankCardRepository.findById(cardId).orElse(null);
        if (!Checker.isNone(bankCard) && bankCard.getUserId() == userId) {
            bankCard.setDeleted(true);
            bankCardRepository.save(bankCard);
            return result.succeed("处理成功");
        }
        return result.failed("处理失败");
    }


    public ServiceResult getWxAppToken(
            String openId, String nickName, int gender, String language, String city,
            String province, String country, String avatarUrl, String sessionKey,
            String unionId, int expiresIn) {
        ServiceResult serviceResult = new ServiceResult();

        Calendar calendar = Calendar.getInstance();
        Date currentDate = calendar.getTime();

        calendar.add(Calendar.SECOND, expiresIn);
        Date expiresDate = calendar.getTime();

//        SnsUser snsUser = snsUserRepository.getSnsUserByOpenId(openId);
        SnsUserInfo snsUserInfo = new SnsUserInfo();
        snsUserInfo.setUnionId(unionId);
        snsUserInfo.setOpenId(openId);
        snsUserInfo.setNickname(StringHelper.filterEmoji(nickName));
        snsUserInfo.setSex(gender);
        snsUserInfo.setProvince(province);
        snsUserInfo.setCity(city);
        snsUserInfo.setCountry(country);
        snsUserInfo.setAvatar(avatarUrl);
        snsUserInfo.setLanguage(language);
        snsUserInfo.setSnsType(SnsTypeEnum.WeChat.getValue());
        snsUserInfo.setAccessToken("");
        snsUserInfo.setRefreshToken("");
        snsUserInfo.setStatus(1);
        snsUserInfo.setPrivilege("");
        snsUserInfo.setExpiresIn(expiresDate);
        snsUserInfo.setTerminal(TerminalEnum.PatientWxApp.getValue());
        snsUserInfo.setDeleted(false);
        snsUserInfo.setUpdateTime(null);
        snsUserInfo.setCreateTime(currentDate);

        snsUserInfo = upsertSnsUserInfo(snsUserInfo);

//        if (snsUser == null) {
//            //不存在，新增
//            snsUser = new SnsUser();
//            snsUser.setId(idGenerator.generateSnsUserId());
//            snsUser.setOpenId(openId);
//            snsUser.setUnionId(unionid);
//            snsUser.setUserId(0);
////            snsUser.setNickname(nickName);
//            snsUser.setNickname("");    //暂时不存昵称
//            snsUser.setSex(gender);
//            snsUser.setProvince(province);
//            snsUser.setCity(city);
//            snsUser.setCountry(country);
//            snsUser.setAvatar(avatarUrl);
//            snsUser.setLanguage(language);
//            snsUser.setSnsType(SnsTypeEnum.WeChat.getValue());
//            snsUser.setAccessToken("");
//            snsUser.setRefreshToken("");
//            snsUser.setStatus(1);
//            snsUser.setDeleted(false);
//            snsUser.setCreateTime(currentDate);
//            snsUser.setUpdateTime(currentDate);
//            snsUser.setExpiresIn(expiresDate);
//        } else {
//            //存在，更新字段
//            snsUser.setNickname(nickName);
//            snsUser.setSex(gender);
//            snsUser.setProvince(province);
//            snsUser.setCity(city);
//            snsUser.setCountry(country);
//            snsUser.setAvatar(avatarUrl);
//            snsUser.setLanguage(language);
//            snsUser.setOpenId(openId);
//            snsUser.setUnionId(unionid);
//            snsUser.setExpiresIn(expiresDate);
//            snsUser.setUpdateTime(currentDate);
//        }
//
//        snsUserRepository.save(snsUser);
//
//        int userId = Checker.getIntegerValue(snsUser.getUserId(), 0);
////        String openId = "";
////
////        if(userId == 0){
////            //未关联
////            openId = UUID.randomUUID().toString();
////        }
//
        WxappUserSession session = wxappUserSessionRepository.getWxappUserSessionByOpenId(openId);

        if (session == null) {
            session = new WxappUserSession();
            session.setId(idGenerator.generateWxappUserSessionId());
            session.setSessionKey(sessionKey);
            session.setExpiresIn(expiresIn);
            session.setOpenId(openId);
//            session.setToken(sessionId);
            session.setCreateTime(currentDate);
            session.setUpdateTime(expiresDate);
        } else {
            session.setSessionKey(sessionKey);
            session.setExpiresIn(expiresIn);
//            session.setToken(sessionId);
            session.setUpdateTime(expiresDate);
        }

        wxappUserSessionRepository.save(session);

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

        serviceResult.setData(map);

        return serviceResult.succeed();
    }

    public ServiceResult bindWxAppMobile(String openId, String mobile, String ip) {
        ServiceResult serviceResult = new ServiceResult();
        SnsUser snsUser = snsUserRepository.getSnsUserByOpenId(openId);

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

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

        if (user == null) {
            userId = idGenerator.generateUserId();
            user = new User();
            user.setId(userId);
            user.setUsername(getRandomUserName());
            user.setRealname(null);
            user.setIdcertificatetype(null);
            user.setIdcertificateno(null);
            user.setMobile(mobile);
            user.setSex(SexEnum.Unknown.getValue());
            user.setAge(null);
            user.setAvatar(null);
            user.setBirthday(null);
            user.setPassword("");
            user.setSalt("");
            user.setCreatetime(new Date());
            user.setRegister_ip(ip);
            user.setProvince(null);
            user.setCity(null);
            user.setArea(null);
//            user.setTerminal();
            user.setStatus(UserStatusEnum.Normal.getValue());
            user.setDeleted(false);
            user.setUsertype(UserTypeEnum.General.getValue());

            userRepository.save(user);
        } else {
            userId = user.getId();
            String sql = "select count(0) from sns_user where user_id = ? and open_id != ? and status = 1 and deleted = 0";
            Object[] params = new Object[]{userId, openId};
            int count = jdbcTemplate.queryForObject(sql, params, Integer.class);

            if (count > 0) {
                return serviceResult.failed("手机号已被其他微信用户注册");
            }

//            if (user.getId().equals(snsUser.getUserId())) {
//                return serviceResult.failed("该手机号与当前绑定的手机号相同");
//            }
        }

        snsUser.setUserId(userId);
        snsUser.setUpdateTime(new Date());

        snsUserRepository.save(snsUser);

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

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


    public String getRandomUserName() {
        String prefix = "u";
        long digit = Checksum.crc32(UUID.randomUUID().toString().getBytes());

        return prefix + digit;
    }

    public SnsUser getSnsUserByUnionId(String unionId) {
        return snsUserRepository.getSnsUserByUnionId(unionId);
    }

    public SnsUser getSnsUserByOpenId(String openId) {
        return snsUserRepository.getSnsUserByOpenId(openId);
    }

    public SnsUser getSnsUserByUserId(int userId) {
        return snsUserRepository.getSnsUserByUserId(userId);
    }

    public User getUserById(int id) {
        return userRepository.findById(id).orElse(null);
    }

    public ServiceResult saveMedicalCard(
            int userId, int hospitalId, String cardNo, String cardType, String name, String mobile,
            String patientId, String patientType, int sex, String birthday, String address, String telephoneNo, String documentId,
            int balance, String idTypeCode, String idTypeDesc, String idNo, String insureCardNo, String accInfo) {
        ServiceResult serviceResult = new ServiceResult();
        int id = idGenerator.genMedicalCard();

        MedicalCard medicalCard = new MedicalCard();
        medicalCard.setId(id);
        medicalCard.setUserId(userId);
        medicalCard.setHospitalId(hospitalId);
        medicalCard.setCardNo(cardNo);
        medicalCard.setCardType(cardType);
        medicalCard.setPatientName(name);
        medicalCard.setMobile(mobile);
        medicalCard.setHisPatientId(patientId);
        medicalCard.setPatientType(patientType);
        medicalCard.setSex(sex);
        medicalCard.setBirthday(birthday);
        medicalCard.setAddress(address);
        medicalCard.setTelephoneNo(telephoneNo);
        medicalCard.setDocumentId(documentId);
        medicalCard.setBalance(balance);
        medicalCard.setIdTypeCode(idTypeCode);
        medicalCard.setIdTypeDesc(idTypeDesc);
        medicalCard.setIdNo(idNo);
        medicalCard.setInsureCardNo(insureCardNo);
        medicalCard.setAccInfo(accInfo);
        medicalCard.setStatus(MedicalCardStatusEnum.NORMAL.getValue());
        medicalCard.setUpdateTime(null);
        medicalCard.setCreateTime(new Date());

        medicalCardRepository.save(medicalCard);
        Map<String, Object> map = new HashMap<>();
        map.put("id", id);
        serviceResult.setData(map);

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

    public MedicalCard getMedicalCardById(int id) {
        return medicalCardRepository.findById(id).orElse(null);
    }

    /**
     * 兼容一卡绑定多账号
     */
    public MedicalCard getMedicalCardByIdAndUserId(int id, int userId) {
        return medicalCardRepository.getByIdAndUserId(id, userId);
    }

    public MedicalCard getMedicalCard(int userId, String cardNo, int hospitalId) {
        return medicalCardRepository.getMedicalCard(userId, cardNo, hospitalId);
    }

    public MedicalCard getMedicalCardByHisPatientId(int userId, String hisPatientId, int hospitalId) {
        return medicalCardRepository.getMedicalCardByHisPatientId(userId, hisPatientId, hospitalId);
    }

    public void saveMedicalCard(MedicalCard medicalCard) {
        int id = idGenerator.genMedicalCard();
        medicalCard.setId(id);
        medicalCard.setStatus(MedicalCardStatusEnum.NORMAL.getValue());
        medicalCard.setUpdateTime(null);
        medicalCard.setCreateTime(new Date());
        // 首次添加诊疗卡，将创建时间当作是同步 HIS 时间
        medicalCard.setHisSyncTime(new Date());
        medicalCardRepository.save(medicalCard);
    }

    public List<MedicalCard> getMedicalCardListByUserId(int userId) {
        return medicalCardRepository.getCardByUserId(userId);
    }

    public List<MedicalCard> getMedicalCardList(int userId, int hospitalId) {
        String sql = "select * from medical_card where user_id = ?";

        if (hospitalId > 0) {
            sql += " and hospital_id = ?";
        }

        sql += " and status = ?";

        Object[] params = hospitalId > 0 ?
                new Object[]{userId, hospitalId, MedicalCardStatusEnum.NORMAL.getValue()} :
                new Object[]{userId, MedicalCardStatusEnum.NORMAL.getValue()};

        int[] argTypes = hospitalId > 0 ?
                new int[]{Types.INTEGER, Types.INTEGER, Types.INTEGER} :
                new int[]{Types.INTEGER, Types.INTEGER};

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

    public int getMedicalCardCount(int userId, int hospitalId) {
        String sql = "select count(0) from medical_card where user_id = ?";

        if (hospitalId > 0) {
            sql += " and hospital_id = ?";
        }

        sql += " and status = ?";

        Object[] params = hospitalId > 0 ?
                new Object[]{userId, hospitalId, MedicalCardStatusEnum.NORMAL.getValue()} :
                new Object[]{userId, MedicalCardStatusEnum.NORMAL.getValue()};

        return jdbcTemplate.queryForObject(sql, params, Integer.class);
    }

    /**
     * 删除诊疗卡
     *
     * @param userId 用户Id
     * @param cardId 诊疗卡Id
     * @return
     */
    public ServiceResult deleteMedicalCard(int userId, int cardId) {
        ServiceResult serviceResult = new ServiceResult();

        if (userId < 1 || cardId < 1) {
            return serviceResult.failed("非法请求");
        }

        MedicalCard card = medicalCardRepository.findById(cardId).orElse(null);

        if (card == null || card.getStatus() == MedicalCardStatusEnum.DELETED.getValue()) {
            return serviceResult.failed("诊疗卡不存在");
        }

        if (card.getUserId() != userId) {
            return serviceResult.failed("非法操作");
        }

        card.setStatus(MedicalCardStatusEnum.DELETED.getValue());
        medicalCardRepository.save(card);

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


    public SnsUser addSnsUser(SnsUser snsUser) {
        SnsUser user = snsUserRepository.getSnsUserByUnionId(snsUser.getUnionId());

        if (user == null) {
            //不存在，新增
            snsUser.setId(idGenerator.generateSnsUserId());
            snsUser.setUserId(0);
            snsUserRepository.save(snsUser);

            return snsUser;
        } else {
            //存在，更新字段
            user.setNickname(snsUser.getNickname());
            user.setSex(snsUser.getSex());
            user.setProvince(snsUser.getProvince());
            user.setCity(snsUser.getCity());
            user.setCountry(snsUser.getCountry());
            user.setAvatar(snsUser.getAvatar());
            user.setLanguage(snsUser.getLanguage());
            user.setExpiresIn(snsUser.getExpiresIn());
            user.setUpdateTime(snsUser.getUpdateTime());
            user.setOfficialOpenId(snsUser.getOfficialOpenId());
            user.setAccessToken(snsUser.getAccessToken());
            user.setRefreshToken(snsUser.getRefreshToken());

            snsUserRepository.save(user);
            return user;
        }
    }

    /**
     * 绑定微信体系账号，兼容unionId为空的情况
     *
     * @param unionId  unionId
     * @param openId   openId
     * @param mobile   手机
     * @param ip       ip地址
     * @param terminal 终端
     * @param name     姓名
     * @param idNo     身份证号
     * @return {@link ServiceResult}
     */
    public ServiceResult bindWxNew(String unionId, String openId, String mobile, String ip, int terminal, String name, String idNo) {
        ServiceResult serviceResult = new ServiceResult();
        List<SnsUserInfo> list = null;

        if (terminal == TerminalEnum.TAI_HE_INTERNET_HOSPITAL_PATIENT_MINI_PROGRAM.getValue()) {
            //医务通互联网医院小程序
            if (!StringHelper.isNullOrWhiteSpace(unionId)) {
                //手机号未被其他用户注册，则关联至用户表（通过unionId注册用户，绑定手机号码）
                User userByUnionId = userRepository.getByUnionIdAndIsDeletedFalse(unionId);
                if (userByUnionId != null && StringHelper.isNullOrWhiteSpace(userByUnionId.getMobile())) {
                    User user = userRepository.getUserByMobile(mobile);
                    if (user == null) {
                        userByUnionId.setMobile(mobile);
                        userRepository.save(userByUnionId);
                    }
                }
            }

            SnsUserInfo snsUserInfoTmp = snsUserInfoRepository.getSnsUserInfoByOpenId(openId, terminal);

            if (snsUserInfoTmp != null) {
                if (snsUserInfoTmp.getUserId() > 0) {

                    User u = userRepository.findById(snsUserInfoTmp.getUserId()).orElse(null);
                    int userId = u.getId();
                    if (StringHelper.isNullOrWhiteSpace(u.getMobile())) {
                        //判断手机号是否被注册
                        User user = userRepository.getUserByMobile(mobile);

                        if (user == null) {
                            u.setMobile(mobile);
                            userRepository.save(u);
                        } else {
                            // 如果手机号被注册，那么就将最新的union_id 赋值到旧数据里面去
                            userId = user.getId();
                            user.setUnionId(snsUserInfoTmp.getUnionId());
                            userRepository.save(user);

                            // 限定openId和terminal匹配的数据才update
                            snsUserInfoTmp.setUserId(userId);
                            snsUserInfoTmp.setUpdateTime(new Date());
                            snsUserInfoRepository.save(snsUserInfoTmp);
                        }
                    } else if (!u.getMobile().equals(mobile)) {
                        return serviceResult.failed("手机号码产生冲突，请联系管理员");
                    }
                    Map<String, Object> map = new HashMap<>();
                    map.put("userId", userId);
                    serviceResult.setData(map);
                    return serviceResult.succeed("成功");
                } else {
                    User user = userRepository.getUserByMobile(mobile);
                    if (user == null) {
                        user = registerByMobile(mobile, ip);
                    }
                    // 限定openId和terminal匹配的数据才update
                    snsUserInfoTmp.setUserId(user.getId());
                    snsUserInfoTmp.setUpdateTime(new Date());
                    snsUserInfoRepository.save(snsUserInfoTmp);

                    Map<String, Object> map = new HashMap<>();
                    map.put("userId", user.getId());
                    serviceResult.setData(map);
                    return serviceResult.succeed("关联成功");
                }
            } else {
                //数据异常
                logger.error("bindWxNew-异常数据，{}, {}, {}, {}, {}, {}, {}", unionId, openId, mobile, ip, terminal, name, idNo);
                return serviceResult.failed("异常数据");
            }
        }

        if (!Checker.isNone(unionId)) {
            list = snsUserInfoRepository.getSnsUserInfoListByUnionId(unionId);
            if (list == null || list.size() == 0) {
                return serviceResult.failed("unionId不存在");
            }
        } else {
            SnsUserInfo snsUserInfoTmp = snsUserInfoRepository.getSnsUserInfoByOpenId(openId, terminal);
            if (snsUserInfoTmp != null) {
                list = new LinkedList<>();
                list.add(snsUserInfoTmp);
            }
        }

        int userId;
        User user = userRepository.getUserByMobile(mobile);

        if (user == null) {
            userId = idGenerator.generateUserId();
            user = new User();
            user.setId(userId);
            user.setUsername(getRandomUserName());
            user.setRealname(name);
            user.setIdcertificatetype(1);
            user.setIdcertificateno(idNo);
            user.setMobile(mobile);
            user.setSex(SexEnum.Unknown.getValue());
            user.setAge(null);
            user.setAvatar(null);
            user.setBirthday(null);
            user.setPassword("");
            user.setSalt("");
            user.setCreatetime(new Date());
            user.setRegister_ip(ip);
            user.setProvince(null);
            user.setCity(null);
            user.setArea(null);
            user.setStatus(UserStatusEnum.Normal.getValue());
            user.setDeleted(false);
            user.setUsertype(UserTypeEnum.General.getValue());
            user.setTerminal(terminal);
            userRepository.save(user);
        } else {
            userId = user.getId();
            // UnionId为空不执行
            if (!Checker.isNone(unionId)) {
                String sql = "select count(0) from sns_user_info where user_id = ? and union_id != ? and status = 1 and deleted = 0;";
                Object[] params = new Object[]{userId, unionId};
                int count = jdbcTemplate.queryForObject(sql, params, Integer.class);

                if (count > 0) {
                    logger.error("bindWxNew: 手机号已被其他微信用户注册 userId {}, unionId {}", userId, unionId);
                    return serviceResult.failed("手机号已被其他微信用户注册");
                }
            }

            SnsUserInfo snsUser = null;

            for (SnsUserInfo info : list) {
                if (userId == 0 && info.getUserId() > 0) {
                    userId = info.getUserId();
                }

                if (snsUser == null && info.getTerminal().equals(terminal)) {
                    snsUser = info;
                }
            }

            if (snsUser == null) {
                return serviceResult.failed("社交账户不存在");
            }

            if (user.getId().equals(snsUser.getUserId())) {
                return serviceResult.failed("该手机号与当前绑定的手机号相同");
            }
        }

        // 限定openId和terminal匹配的数据才update
        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("关联成功");
    }


    public ServiceResult bindWx(String unionId, String mobile, String ip, int terminal, String name, String idNo) {
        ServiceResult serviceResult = new ServiceResult();
        List<SnsUserInfo> list = snsUserInfoRepository.getSnsUserInfoListByUnionId(unionId);

        if (list == null || list.size() == 0) {
            return serviceResult.failed("unionId不存在");
        }

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

        if (user == null) {
            userId = idGenerator.generateUserId();
            user = new User();
            user.setId(userId);
            user.setUsername(getRandomUserName());
            user.setRealname(name);
            user.setIdcertificatetype(1);
            user.setIdcertificateno(idNo);
            user.setMobile(mobile);
            user.setSex(SexEnum.Unknown.getValue());
            user.setAge(null);
            user.setAvatar(null);
            user.setBirthday(null);
            user.setPassword("");
            user.setSalt("");
            user.setCreatetime(new Date());
            user.setRegister_ip(ip);
            user.setProvince(null);
            user.setCity(null);
            user.setArea(null);
            user.setStatus(UserStatusEnum.Normal.getValue());
            user.setDeleted(false);
            user.setUsertype(UserTypeEnum.General.getValue());
            user.setTerminal(terminal);
            userRepository.save(user);
        } else {
            userId = user.getId();
            String sql = "select count(0) from sns_user_info where user_id = ? and union_id != ? and union_id != '' and union_id is not null and status = 1 and deleted = 0;";
            Object[] params = new Object[]{userId, unionId};
            int count = jdbcTemplate.queryForObject(sql, params, Integer.class);

            if (count > 0) {
                return serviceResult.failed("手机号已被其他微信用户注册");
            }

            SnsUserInfo snsUser = null;

            for (SnsUserInfo info : list) {
                if (userId == 0 && info.getUserId() > 0) {
                    userId = info.getUserId();
                }

                if (snsUser == null && info.getTerminal().equals(terminal)) {
                    snsUser = info;
                }
            }

            if (snsUser == null) {
                return serviceResult.failed("社交账户不存在");
            }

            if (user.getId().equals(snsUser.getUserId())) {
                return serviceResult.failed("该手机号与当前绑定的手机号相同");
            }
        }

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

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

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

    /**
     * 更换手机号码
     *
     * @param userId 用户Id
     * @param mobile 手机号码
     * @return
     */
    public ServiceResult changeMobile(int userId, String mobile) {
        ServiceResult serviceResult = new ServiceResult();

        if (!PhoneNumChecker.isPhoneNum(mobile)) {
            return serviceResult.failed("手机号码不正确");
        }

        User mobileUser = findByMobile(mobile);

        if (mobileUser != null) {
            return serviceResult.failed("手机号已被其他用户注册");
        }

        User user = getUserById(userId);

        if (user == null || user.getIsDeleted()) {
            return serviceResult.failed("用户不存在");
        }

        if (user.getMobile().equals(mobile)) {
            return serviceResult.failed("该手机号与当前绑定的手机号相同");
        }

        user.setMobile(mobile);
        userRepository.save(user);

        return serviceResult.succeed("更换成功");
    }

    /**
     * 获取门诊病历列表
     *
     * @param userId
     * @param medicalCardId
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public PagedList<MedicalRecords> getOutpatientServiceRecordsList(int userId, int medicalCardId, int pageIndex, int pageSize) {
        String whereSql = " user_id = ? and medical_card_id = ? and type = ? and deleted = 0";
        Object[] params = new Object[]{userId, medicalCardId, MedicalRecordsTypeEnum.OutpatientService.getValue()};
        int[] argTypes = new int[]{Types.INTEGER, Types.INTEGER, Types.INTEGER};

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

    /**
     * 根据就诊流水号获取门诊病历
     *
     * @param clinicCode 就诊流水号
     * @return
     */
    public MedicalRecords getOutpatientServiceRecord(String clinicCode) {
        return medicalRecordsRepository.getOutpatientServiceRecord(clinicCode);
    }

    /**
     * 通过用户名和手机号得到用户对象
     *
     * @param username
     * @param password
     * @return
     */
    public User getUserByUsernameAndPsd(String username, String password) {
        return userRepository.getUserByUsernameAndPsd(username, password);
    }

    /**
     * 更新密码
     *
     * @param user
     * @param password
     */
    public void updateUserPassword(User user, String password) {
        String salt = RandomUtil.getRandomCode(8, 3);
        String md5Pwd = StringHelper.md5(password + salt);

        user.setSalt(salt);
        user.setPassword(md5Pwd);
        userRepository.save(user);
    }

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


    /**
     * 登录日志
     *
     * @param userId
     * @param type
     */
    public void addLoginLog(int userId, int type, String ip) {
        LoginLog log = new LoginLog();
        int id = idGenerator.genLoginLogId();
        log.setId(id);

        log.setIp(ip);
        log.setUserId(userId);
        log.setType(type);
        log.setCreatetime(new Date());
        loginLogRepository.save(log);
    }

    public int checkIsFirstLogin(int userId, int type) {
        return loginLogRepository.checkIsFirstLogin(userId, type);
    }

    public SnsUserInfo upsertSnsUserInfo(SnsUserInfo snsUserInfo) {
        List<SnsUserInfo> list = null;
        if (!Checker.isNone(snsUserInfo.getUnionId())) {
            list = snsUserInfoRepository.getSnsUserInfoListByUnionId(snsUserInfo.getUnionId());
        } else {
            SnsUserInfo snsUserInfoTmp = snsUserInfoRepository.getSnsUserInfoByOpenId(snsUserInfo.getOpenId(), snsUserInfo.getTerminal());
            if (snsUserInfoTmp != null) {
                list = new LinkedList<>();
                list.add(snsUserInfoTmp);
            }
        }

        if (list == null || list.size() == 0) {
            //不存在，新增
            snsUserInfo.setId(idGenerator.genSnsUserInfoId());
            snsUserInfo.setUserId(0);

            snsUserInfoRepository.save(snsUserInfo);
            return snsUserInfo;
        } else {
            int userId = 0;
            SnsUserInfo user = null;

            int terminal = Checker.getIntegerValue(snsUserInfo.getTerminal());
            if (terminal == TerminalEnum.DoctorWxOfficial.getValue() ||
                    terminal == TerminalEnum.TAI_HE_INTERNET_HOSPITAL_DOCTOR_WX_OFFICIAL.getValue() ||
                    terminal == TerminalEnum.PRESCRIPTION_SYSTEM_PC.getValue()) {
                //取当前terminal的SnsUserInfo, 判断userId是否大于0
                SnsUserInfo currentTerminalSnsUserInfo = list.stream().filter(info -> info.getTerminal() == terminal).findFirst().orElse(null);
                if (currentTerminalSnsUserInfo == null || currentTerminalSnsUserInfo.getUserId() <= 0) {
                    //尝试找一个同用户的医生账户的非0 userId
                    List<SnsUserInfo> tmpList = list.stream()
                            .filter(p -> (p.getTerminal() == TerminalEnum.DoctorWxOfficial.getValue() ||
                                    p.getTerminal() == TerminalEnum.TAI_HE_INTERNET_HOSPITAL_DOCTOR_WX_OFFICIAL.getValue() ||
                                    p.getTerminal() == TerminalEnum.PRESCRIPTION_SYSTEM_PC.getValue()) && p.getUserId() > 0)
                            .collect(Collectors.toList());

                    if (tmpList.size() > 0) {
                        userId = tmpList.get(0).getUserId();
                    }
                } else {
                    user = currentTerminalSnsUserInfo;
                }
            } else {
                for (SnsUserInfo info : list) {
                    if (userId == 0 && info.getUserId() > 0) {
                        userId = info.getUserId();
                    }

                    if (user == null && info.getTerminal().equals(snsUserInfo.getTerminal())) {
                        user = info;
                    }
                }
            }

            if (user != null) {
                //存在，更新字段
                user.setNickname(snsUserInfo.getNickname());
                user.setSex(snsUserInfo.getSex());
                user.setProvince(snsUserInfo.getProvince());
                user.setCity(snsUserInfo.getCity());
                user.setCountry(snsUserInfo.getCountry());
                user.setAvatar(snsUserInfo.getAvatar());
                user.setLanguage(snsUserInfo.getLanguage());
                user.setExpiresIn(snsUserInfo.getExpiresIn());
                user.setUpdateTime(snsUserInfo.getUpdateTime());
                user.setAccessToken(snsUserInfo.getAccessToken());
                user.setRefreshToken(snsUserInfo.getRefreshToken());
                if (user.getUserId() == 0) {
                    user.setUserId(userId);
                }

                snsUserInfoRepository.save(user);
                return user;
            } else {
                //不存在，新增
                snsUserInfo.setId(idGenerator.genSnsUserInfoId());
                snsUserInfo.setUserId(userId);
                snsUserInfoRepository.save(snsUserInfo);
                return snsUserInfo;
            }
        }
    }

    /**
     * 医务通互联网医院小程序（修BUG）
     *
     * @param snsUserInfo
     * @return
     */
    public SnsUserInfo upsertSnsUserInfoTmp(SnsUserInfo snsUserInfo) {
        SnsUserInfo user = snsUserInfoRepository.getSnsUserInfoByOpenId(snsUserInfo.getOpenId(), snsUserInfo.getTerminal());

        if (user == null) {
            //不存在，新增
            snsUserInfo.setId(idGenerator.genSnsUserInfoId());
            snsUserInfo.setUserId(0);
            snsUserInfoRepository.save(snsUserInfo);
            return snsUserInfo;
        }

        //存在，更新字段
        if (!StringHelper.isNullOrWhiteSpace(snsUserInfo.getNickname())) {
            user.setNickname(snsUserInfo.getNickname());
        }
        user.setSex(snsUserInfo.getSex());
        if (!StringHelper.isNullOrWhiteSpace(snsUserInfo.getProvince())) {
            user.setProvince(snsUserInfo.getProvince());
        }
        if (!StringHelper.isNullOrWhiteSpace(snsUserInfo.getCity())) {
            user.setCity(snsUserInfo.getCity());
        }
        if (!StringHelper.isNullOrWhiteSpace(snsUserInfo.getCountry())) {
            user.setCountry(snsUserInfo.getCountry());
        }
        if (!StringHelper.isNullOrWhiteSpace(snsUserInfo.getAvatar())) {
            user.setAvatar(snsUserInfo.getAvatar());
        }
        if (!StringHelper.isNullOrWhiteSpace(snsUserInfo.getLanguage())) {
            user.setLanguage(snsUserInfo.getLanguage());
        }
        user.setExpiresIn(snsUserInfo.getExpiresIn());
        user.setUpdateTime(snsUserInfo.getUpdateTime());
        user.setAccessToken(snsUserInfo.getAccessToken());
        user.setRefreshToken(snsUserInfo.getRefreshToken());

        //unionid不为空
        if (!StringHelper.isNullOrEmpty(snsUserInfo.getUnionId())) {
            int userId = 0;
            List<SnsUserInfo> lst = snsUserInfoRepository.getSnsUserInfoListByUnionId(snsUserInfo.getUnionId());

            if (lst != null) {
                for (SnsUserInfo info : lst) {
                    if (info.getUserId() > 0 && !TerminalEnum.isDoctorTerminal(info.getTerminal())) {
                        userId = info.getUserId();
                        break;
                    }
                }
            }
            if (StringHelper.isNullOrEmpty(user.getUnionId())) {
                user.setUnionId(snsUserInfo.getUnionId());
            }
            if (user.getUserId() == 0) {
                user.setUserId(userId);
            }
        }
        snsUserInfoRepository.save(user);
        return user;
    }

    /**
     * 用户新建就诊人
     *
     * @param userId
     * @param age
     * @param sex
     * @param mobile
     * @param name
     * @return
     */
    public ServiceResult createMedicalRecord(int userId, int recordId, int age, int sex, String mobile, String name, String idNo) {
        ServiceResult serviceResult = new ServiceResult();
        MedicalRecords record = null;
        if (recordId == 0) {
            recordId = idGenerator.genMedicalRecordsId();
            record = new MedicalRecords();
            record.setId(recordId);
            record.setCreateTime(new Date());
            record.setDeleted(false);
            record.setPatientId(0);
            record.setDoctorId(0);
            record.setUserId(userId);
            record.setIdNo(idNo);
            record.setType(MedicalRecordsTypeEnum.PatientInfo.getValue());
        } else {
            record = medicalRecordsRepository.findById(recordId).orElse(null);
            if (record == null) {
                return serviceResult.failed("病历ID有误");
            }
        }
        record.setMobile(mobile);
        record.setSex(sex);
        record.setAge(age);
        record.setUpdateTime(new Date());
        record.setPatientName(name);
        record.setIdNo(idNo);

        medicalRecordsRepository.save(record);
        Map<String, Object> map = new HashMap<>();
        map.put("recordId", recordId);
        serviceResult.setData(map);

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

    public SnsUserInfo getSnsUserInfo(String unionId, String openId, int terminal) {
        if (StringHelper.isNullOrWhiteSpace(unionId) && StringHelper.isNullOrWhiteSpace(openId)) {
            return null;
        }

        List<Object> args = new LinkedList<>();
        List<Integer> types = new LinkedList<>();
        String whereSql = "terminal = ?";
        args.add(terminal);
        types.add(Types.INTEGER);

        if (!StringHelper.isNullOrWhiteSpace(unionId)) {
            whereSql += " and union_id = ?";
            args.add(unionId);
            types.add(Types.VARCHAR);
        }
        if (!StringHelper.isNullOrWhiteSpace(openId)) {
            whereSql += " and open_id = ?";
            args.add(openId);
            types.add(Types.VARCHAR);
        }

        whereSql += " and deleted = 0";
        String sql = "select * from sns_user_info where " + whereSql + " limit 1;";
        int[] argTypes = types.stream().mapToInt(i -> i).toArray();
        List<SnsUserInfo> lst = jdbcTemplate.query(sql, args.toArray(), argTypes, new BeanPropertyRowMapper<>(SnsUserInfo.class));
        if (lst != null && lst.size() > 0) {
            return lst.get(0);
        }
        return null;
    }

    /**
     * 用户扫描关注医生
     *
     * @param user
     * @param doctor
     */
    public ServiceResult userAttentionDoctor(User user, User doctor) {

        ServiceResult result = new ServiceResult();

        int check = userUnionsRepository.checkUnion(doctor.getId(), user.getId(), 3);
        if (check > 0) {
            return result.failed("已添加");
        }

        UserUnions unions = new UserUnions();
        int unionsId = idGenerator.genUserUnionsId();
        unions.setCreateTime(new Date());
        unions.setUpdateTime(new Date());
        unions.setDeleted(false);
        unions.setId(unionsId);
        unions.setStatus(0);
        unions.setType(3);
        unions.setUserId(doctor.getId());
        unions.setUnionUserId(user.getId());
        userUnionsRepository.save(unions);

        return result.succeed("添加成功");
    }

    /**
     * 根据代理的ID得到关系对象
     *
     * @param agentId
     * @return
     */
    public UserUnions getUserUnionByAgentId(int agentId) {
        return userUnionsRepository.getUserUnionByAgent(agentId);
    }

    public Agent getAgentById(int id) {
        return agentRepository.findById(id).orElse(null);
    }

    public DrugProvider getDrugProviderById(int id) {
        return drugProviderRepository.findById(id).orElse(null);
    }


    /**
     * 用户点击关注医生
     *
     * @param user
     * @param doctor
     */
    public ServiceResult saveAttentionDoctorStatus(User user, User doctor) {

        ServiceResult result = new ServiceResult();

        UserUnions unions = userUnionsRepository.getUnion(user.getId(), doctor.getId(), 4);

        if (!Checker.isNone(unions)) {
            unions.setStatus(1 - unions.getStatus());
            unions.setUpdateTime(new Date());
            userUnionsRepository.save(unions);
            return result.succeed("处理成功");
        } else {
            //从来没关注过时，则新增记录
            unions = new UserUnions();
            int unionsId = idGenerator.genUserUnionsId();
            unions.setCreateTime(new Date());
            unions.setUpdateTime(new Date());
            unions.setDeleted(false);
            unions.setId(unionsId);
            unions.setStatus(0);    // 0-启用，1-禁用(此时表示0-关注，1-不关注)
            unions.setType(4);
            unions.setUserId(user.getId());
            unions.setUnionUserId(doctor.getId());
            userUnionsRepository.save(unions);
        }
        return result.succeed("添加成功");
    }

    public ServiceResult updateFollowedStatus(int userId, int doctorId, int status) {
        ServiceResult result = new ServiceResult();
        User user = userRepository.findById(userId).orElse(null);
        if (user == null || user.getIsDeleted()) {
            return result.failed("用户不存在");
        }

        User doctor = userRepository.findById(doctorId).orElse(null);
        if (doctor == null || doctor.getIsDeleted()) {
            return result.failed("医生不存在");
        }

        UserUnions unions = userUnionsRepository.getUnion(userId, doctorId, 4);
        if (!Checker.isNone(unions)) {
            unions.setStatus(status);
            unions.setUpdateTime(new Date());
        } else {
            //从来没关注过时，则新增记录
            unions = new UserUnions();
            int unionsId = idGenerator.genUserUnionsId();
            unions.setCreateTime(new Date());
            unions.setUpdateTime(new Date());
            unions.setDeleted(false);
            unions.setId(unionsId);
            unions.setStatus(0);    // 0-启用，1-禁用(此时表示0-关注，1-不关注)
            unions.setType(4);
            unions.setUserId(user.getId());
            unions.setUnionUserId(doctor.getId());
        }

        userUnionsRepository.save(unions);
        return result.succeed("添加成功");
    }


    /**
     * 根据id得到对象
     *
     * @param hospitalId 医院ID
     * @return
     */
    public Hospital findHospitalById(int hospitalId) {
        return hospitalRepository.findHospitalById(hospitalId);
    }

    /**
     * 用户点击关注医院
     *
     * @param user
     * @param hospital
     */
    public ServiceResult saveAttentionHospitalStatus(User user, Hospital hospital) {

        ServiceResult result = new ServiceResult();

        Attention attention = attentionRepository.getAttention(user.getId(), hospital.getId(), 1);

        if (!Checker.isNone(attention)) {
            attention.setDeleted(true);
            attention.setUpdateTime(new Date());
            attentionRepository.save(attention);
            return result.succeed("处理成功");
        } else {
            //从来没关注过时，则新增记录
            attention = new Attention();
            int id = idGenerator.genAttentionId();
            attention.setCreateTime(new Date());
            attention.setUpdateTime(new Date());
            attention.setDeleted(false);
            attention.setId(id);
            attention.setType(1);
            attention.setUserId(user.getId());
            attention.setAttentionId(hospital.getId());
            attentionRepository.save(attention);
        }
        return result.succeed("添加成功");
    }

    /**
     * 关注医生
     *
     * @param userId
     * @param doctorId
     * @return
     */
    public ServiceResult followDoctor(int userId, int doctorId) {
        ServiceResult result = new ServiceResult();
        UserUnions unions = userUnionsRepository.getUnion(userId, doctorId, 4);

        if (unions != null) {
            if (unions.getStatus() == 0) {
                return result.succeed("已关注");
            }

            unions.setStatus(0);
        } else {
            unions = new UserUnions();
            int unionsId = idGenerator.genUserUnionsId();
            unions.setCreateTime(new Date());
            unions.setUpdateTime(new Date());
            unions.setDeleted(false);
            unions.setId(unionsId);
            unions.setStatus(0);    // 0-启用，1-禁用(此时表示0-关注，1-不关注)
            unions.setType(4);
            unions.setUserId(userId);
            unions.setUnionUserId(doctorId);
        }

        userUnionsRepository.save(unions);
        return result.succeed("关注成功");
    }

    /**
     * 发生处方业务后关注医生
     *
     * @param userId   患者id
     * @param doctorId 医生id
     * @return {@link ServiceResult}
     */
    public ServiceResult followDoctorAfterCreatingPrescription(int userId, int doctorId) {
        ServiceResult result = new ServiceResult();
        UserUnions unions = userUnionsRepository.getUnion(userId, doctorId, 4);

        if (unions != null) {
            if (unions.getStatus() == 0) {
                // 此前已关注，则更新updateTime并保存
                userUnionsRepository.save(unions);
                return result.succeed("已关注");
            }
        } else {
            unions = new UserUnions();
            int unionsId = idGenerator.genUserUnionsId();
            unions.setCreateTime(new Date());
            unions.setDeleted(false);
            unions.setId(unionsId);
            unions.setType(4);
            unions.setUserId(userId);
            unions.setUnionUserId(doctorId);
        }
        // update updateTime, status & hasPresc
        unions.setUpdateTime(new Date());
        unions.setStatus(0);    // 0-启用，1-禁用(此时表示0-关注，1-不关注)
        unions.setHasPresc(1);
        userUnionsRepository.save(unions);
        return result.succeed("关注成功");
    }

    /**
     * 获取用户个人资料列表
     *
     * @param userId
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public PagedList<UserPatient> getUserPatientList(int userId, int pageIndex, int pageSize) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " deleted = 0 and user_id = ? ";
        paramList.add(userId);
        return sqlHelperYwtCenter.getPagedList(pageIndex, pageSize, "*", whereSql, "relationship asc, create_time desc", UserPatient.class, paramList.toArray());
    }


    /**
     * 编辑用户的单个个人资料
     *
     * @param userPatientId
     * @param userId
     * @param sex
     * @param mobile
     * @param name
     * @param idNo
     * @param parentName
     * @return
     */
    public ServiceResult updateUserPatientInfo(int userPatientId, int userId, int sex, String mobile, String name,
                                               String idNo, String parentName, int relationship, String address) {
        ServiceResult serviceResult = new ServiceResult();
        UserPatient up = null;
        if (userPatientId == 0) {

            if (userId == 0) {
                return serviceResult.failed("userId不能为空");
            }
            // 编辑的时候不允许修改身份证，所以只需在新增的地方做下判断
            int check = userPatientRepository.checkUserPatientExist(userId, idNo);
            if (check > 0) {
                return serviceResult.failed("该身份证号已经添加！");
            }

            userPatientId = idGenerator.genUserPatientId();
            up = new UserPatient();
            up.setId(userPatientId);
            up.setCreateTime(new Date());
            up.setDeleted(false);
            up.setUserId(userId);
        } else {
            up = userPatientRepository.findById(userPatientId).orElse(null);
            if (up == null || up.getDeleted()) {
                return serviceResult.failed("个人资料ID有误");
            }
            if (up.getUserId() != userId) {
                return serviceResult.failed("无权修改该资料");
            }
        }

        if (relationship == RelationshipEnum.MYSELF.getValue()) {
            //判断是否已经添加了 本人 的个人资料
            String sql;
            Object[] args;
            int[] types;
            int count;

            if (userPatientId > 0) {
                sql = "select count(0) from user_patient where user_id = ? and relationship = ? and id <> ? and deleted = 0;";
                args = new Object[]{userId, relationship, userPatientId};
                types = new int[]{Types.INTEGER, Types.INTEGER, Types.INTEGER};

            } else {
                sql = "select count(0) from user_patient where user_id = ? and relationship = ? and deleted = 0;";
                args = new Object[]{userId, relationship};
                types = new int[]{Types.INTEGER, Types.INTEGER};
            }

            count = jdbcTemplate.queryForObject(sql, args, types, Integer.class);
            if (count > 0) {
                return serviceResult.failed("您已添加了本人的个人资料，不能重复添加！");
            }
        }

        up.setMobile(mobile);
        up.setSex(sex);
        up.setUpdateTime(new Date());
        up.setName(name);
        up.setIdNo(idNo);
        up.setParentName(parentName);
        up.setRelationship(relationship);
        up.setAddress(address);
        userPatientRepository.save(up);

        if (relationship == RelationshipEnum.MYSELF.getValue()) {
            //同步实名信息
            String sql = "update user set id_certificate_type = 1, real_name = ?, id_certificate_no = ? where id = ?;";
            Object[] args = new Object[]{name, idNo, userId};
            int[] types = new int[]{Types.VARCHAR, Types.VARCHAR, Types.INTEGER};
            jdbcTemplate.update(sql, args, types);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("userPatientId", userPatientId);
        serviceResult.setData(map);
        return serviceResult.succeed("处理成功");
    }


    /**
     * 根据ID得到对象
     *
     * @param userPatientId
     * @return
     */
    public UserPatient getUserPatientByUserPatientId(int userPatientId) {
        return userPatientRepository.findById(userPatientId).orElse(null);
    }


    /**
     * 判断用户是否已添加个人资料（以 user_id 和 id_no 为准）
     *
     * @param userId
     * @param idNo
     * @return
     */
    public int checkUserPatientExist(int userId, String idNo) {
        return userPatientRepository.checkUserPatientExist(userId, idNo);
    }

    /**
     * 删除个人资料
     *
     * @param userPatientId
     * @return
     */
    public ServiceResult delUserPatient(int userPatientId, int userId) {
        ServiceResult serviceResult = new ServiceResult();
        UserPatient patient = userPatientRepository.findById(userPatientId).orElse(null);
        if (Checker.isNone(patient)) {
            return serviceResult.failed("该记录不存在");
        }
        if (patient.getUserId() != userId) {
            return serviceResult.failed("没有权限删除该资料");
        }
        patient.setDeleted(true);
        patient.setUpdateTime(new Date());
        userPatientRepository.save(patient);
        return serviceResult.succeed("处理成功");
    }

    /**
     * 获取用户姓名，判断是否有realName，若有则返回realName,若无则判断是否有userName,若有返回userName,若无则返回空字符串。
     *
     * @param userId 用户id
     * @return 用户名
     */
    public String getUserNameById(int userId) {
        User user = userRepository.findById(userId).orElse(null);
        if (user == null) return "";
        if (StringHelper.isNullOrEmpty(user.getRealname()))
            return StringHelper.isNullOrEmpty(user.getUsername()) ? "" : user.getUsername();
        return user.getRealname();
    }

    public User getNormalUserById(int id) {
        return userRepository.getNormalUserById(id);
    }

    /**
     * 根据unionId自动注册（普通用户）
     *
     * @param unionId
     * @return
     */
    public User registerByUnionId(String unionId, String ip) {
        int userId = idGenerator.generateUserId();
        String sql = String.format(
                "INSERT INTO USER ( id, user_name, mobile, sex, salt, create_time, register_ip, STATUS, is_deleted, user_type, union_id ) SELECT " +
                        "%d," +
                        "'%s'," +
                        "'%s'," +
                        "%d," +
                        "'%s'," +
                        "now( )," +
                        "'%s'," +
                        "%d," +
                        "0," +
                        "%d," +
                        "'%s' " +
                        "FROM " +
                        "DUAL " +
                        "WHERE " +
                        "NOT EXISTS ( SELECT union_id FROM USER WHERE union_id = '%s' AND is_deleted = 0 );"
                , userId
                , getRandomUserName()
                , ""
                , SexEnum.Unknown.getValue()
                , RandomUtil.getRandomCode(6, 3)
                , ip
                , UserStatusEnum.Normal.getValue()
                , UserTypeEnum.General.getValue()
                , unionId
                , unionId
        );
        jdbcTemplate.execute(sql);
        return userRepository.getByUnionIdAndIsDeletedFalse(unionId);
//        User user = new User();
//        user.setId(userId);
//        user.setUsername(getRandomUserName());
//        user.setRealname(null);
//        user.setIdcertificatetype(null);
//        user.setIdcertificateno(null);
//        user.setMobile("");
//        user.setSex(SexEnum.Unknown.getValue());
//        user.setAge(null);
//        user.setAvatar(null);
//        user.setBirthday(null);
//        user.setPassword("");
//        user.setSalt("");
//        user.setCreatetime(new Date());
//        user.setRegister_ip(ip);
//        user.setProvince(null);
//        user.setCity(null);
//        user.setArea(null);
//        user.setStatus(UserStatusEnum.Normal.getValue());
//        user.setDeleted(false);
//        user.setUsertype(UserTypeEnum.General.getValue());
//        user.setUnionId(unionId);
//
//        userRepository.save(user);
//        return user;
    }

    /**
     * 实名认证
     *
     * @param userId
     * @param realName
     * @param idCardNo
     * @return
     */
    public ServiceResult authenticate(int userId, String realName, String idCardNo) {
        ServiceResult serviceResult = new ServiceResult();
        if (userId <= 0) {
            return serviceResult.failed("userId不存在");
        }
        if (StringHelper.isNullOrWhiteSpace(realName)) {
            return serviceResult.failed("姓名不能为空");
        }
        if (StringHelper.isNullOrWhiteSpace(idCardNo)) {
            return serviceResult.failed("请填写身份证号");
        }
        if (!IdCardUtil.verify(idCardNo)) {
            return serviceResult.failed("身份证号码不正确");
        }

        String sql =
                "update user set id_certificate_type = 1, real_name = ?, id_certificate_no = ? " +
                        "where id = ? and (real_name is null || real_name = ''); ";
        Object[] args = new Object[]{realName, idCardNo, userId};
        int[] types = new int[]{Types.VARCHAR, Types.VARCHAR, Types.INTEGER};
        int count = jdbcTemplate.update(sql, args, types);

        if (count > 0) {
            //更新患者资料
            sql = "update user_patient set name = ?, id_no = ? where user_id = ? and relationship = ?;";
            args = new Object[]{realName, idCardNo, userId, RelationshipEnum.MYSELF.getValue()};
            types = new int[]{Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER};
            count = jdbcTemplate.update(sql, args, types);

            if (count == 0) {
                //新增
                UserPatient userPatient = new UserPatient();
                userPatient.setId(idGenerator.genUserPatientId());
                userPatient.setCreateTime(new Date());
                userPatient.setDeleted(false);
                userPatient.setUserId(userId);
                userPatient.setMobile("");
                userPatient.setSex(IdCardUtil.getSexInt(idCardNo));
                userPatient.setUpdateTime(new Date());
                userPatient.setName(realName);
                userPatient.setIdNo(idCardNo);
                userPatient.setParentName("");
                userPatient.setRelationship(RelationshipEnum.MYSELF.getValue());
                userPatientRepository.save(userPatient);
            }
            return serviceResult.succeed();
        }
        return serviceResult.failed("用户不存在");
    }

    /**
     * 医生端小程序，保存SnsUserInfo
     *
     * @param snsUserInfo SnsUserInfo
     * @return
     */
    public SnsUserInfo saveSnsUserInfo(SnsUserInfo snsUserInfo) {
        if (StringHelper.isNullOrWhiteSpace(snsUserInfo.getUnionId()) || StringHelper.isNullOrWhiteSpace(snsUserInfo.getOpenId())) {
            throw new IllegalArgumentException("union_id or open_id is null or white space");
        }

        SnsUserInfo existed = snsUserInfoRepository.getSnsUserInfoByOpenId(snsUserInfo.getOpenId(), snsUserInfo.getTerminal());
        if (existed != null) {
            //存在，更新字段
            existed.setNickname(snsUserInfo.getNickname());
            existed.setSex(snsUserInfo.getSex());
            existed.setProvince(snsUserInfo.getProvince());
            existed.setCity(snsUserInfo.getCity());
            existed.setCountry(snsUserInfo.getCountry());
            existed.setAvatar(snsUserInfo.getAvatar());
            existed.setLanguage(snsUserInfo.getLanguage());
            existed.setExpiresIn(snsUserInfo.getExpiresIn());
            existed.setUpdateTime(snsUserInfo.getUpdateTime());
            existed.setAccessToken(snsUserInfo.getAccessToken());
            existed.setRefreshToken(snsUserInfo.getRefreshToken());
            snsUserInfoRepository.save(existed);
            return existed;
        }

        int userId = 0;
        List<SnsUserInfo> list = snsUserInfoRepository.getSnsUserInfoListByUnionId(snsUserInfo.getUnionId());

        if (list != null && list.size() > 0) {
            //查找用户是否绑定了其它医生端
            List<SnsUserInfo> tmpList = list.stream()
                    .filter(p -> TerminalEnum.isDoctorTerminal(p.getTerminal()) && p.getUserId() > 0)
                    .collect(Collectors.toList());
            if (tmpList.size() > 0) {
                userId = tmpList.get(0).getUserId();
            }
        }

        snsUserInfo.setId(idGenerator.genSnsUserInfoId());
        snsUserInfo.setUserId(userId);
        snsUserInfoRepository.save(snsUserInfo);
        return snsUserInfo;
    }

    /**
     * 选择诊疗卡，给诊疗卡做个标记，标记最后的选择，当用户再次查看诊疗卡时，可根据这个字段获取上一次选的诊疗卡
     *
     * @param cardId 诊疗卡ID
     * @param userId 用户ID
     */
    public BaseResponse selectCard(int cardId, int userId) {
        BaseResponse response = new BaseResponse();
        if (cardId <= 0) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "参数 CardId 不正确");
        }
        List<MedicalCard> medicalCardList = medicalCardRepository.getCardByUserId(userId);
        if (Checker.isNone(medicalCardList)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "参数错误");
        }
        MedicalCard medicalCard = medicalCardList.stream().filter(p -> p.getId() == cardId && p.getUserId() == userId).findFirst().orElse(null);
        if (Checker.isNone(medicalCard)) {
            return response.failed(BaseResponse.PARAMETER_ERROR, "不存在该诊疗卡");
        }
        medicalCardList.forEach(p -> {
            if (p.getId() == cardId) {
                p.setLastChoice(LastChoiceEnum.True.getValue());
            } else {
                p.setLastChoice(LastChoiceEnum.False.getValue());
            }
        });
        medicalCardRepository.saveAll(medicalCardList);
        return response.succeed("操作成功");
    }

    /**
     * 判断用户是否有诊疗卡
     *
     * @param request {@link CheckHasCardRequest}
     * @return {@link Result}
     */
    public Result checkHasCard(CheckHasCardRequest request) {
        Result.Builder builder = Result.newBuilder().setCode(ResultCode.SUCCEED).setInfo("处理成功");
        // hasCard:0:表示没有诊疗卡，1-表示有诊疗卡
        int hasCard = 0;
        String openId = request.getOpenId();
        int terminal = request.getTerminal();
        int hospitalId = request.getHospitalId();
        if (hospitalId == 0) {
            return builder.setCode(ResultCode.PARAMETER_ERROR).setInfo("医院ID不能为空").build();
        }
        // 获取userId
        SnsUserInfo snsUserInfo = snsUserInfoRepository.getSnsUserInfoByOpenId(openId, terminal);
        if (Checker.isNone(snsUserInfo)) {
            return builder.setCode(ResultCode.PARAMETER_ERROR).setInfo("用户不存在").build();
        }
        // 根据userId和hospitalId找对应的诊疗卡信息
        int userId = Checker.getIntegerValue(snsUserInfo.getUserId());
        if (userId > 0) {
            hasCard = medicalCardRepository.checkHasCard(userId, hospitalId);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("hasCard", hasCard);
        return builder.setValue(JsonSerializer.toJson(map)).build();
    }

    public void upsertMrVisible(int userId, String idCardNo, boolean visible, int doctorId) {
        MedRecordSetting setting = medRecordSettingRepository.findByUserIdAndIdCardAndDeletedFalseAndDoctorId(userId, idCardNo, doctorId);
        if (setting == null) {
            setting = new MedRecordSetting();
            setting.setIdCard(idCardNo);
            setting.setUserId(userId);
            setting.setUpdateTime(new Date());
            setting.setCreateTime(new Date());
            setting.setVisible(visible);
            setting.setDeleted(false);
            setting.setDoctorId(doctorId);
        } else {
            setting.setVisible(visible);
            setting.setUpdateTime(new Date());
        }
        medRecordSettingRepository.save(setting);
    }

    public boolean getUserMRVisible(int userId, String idCard, int doctorId) {
        boolean visible = false;
        MedRecordSetting setting = medRecordSettingRepository.findByUserIdAndIdCardAndDeletedFalseAndDoctorId(userId, idCard, doctorId);
        if (setting != null) {
            visible = setting.getVisible();
        }
        return visible;
    }

    /**
     * 保存签名图片
     */
    public ServiceResult saveSign(int userId, String signUrl) {
        ServiceResult serviceResult = new ServiceResult();
        if (userId < 1) {
            return serviceResult.failed(String.format("用户不存在(%d)", userId));
        }
        if (StringHelper.isNullOrWhiteSpace(signUrl)) {
            return serviceResult.failed("签名不存在");
        }
        UserSign sign = new UserSign();
        sign.setUserId(userId);
        sign.setSignUrl(signUrl);
        sign.setDeleted(false);
        sign.setCreateTime(new Date());
        UserSign us = userSignRepository.save(sign);

        Map<String, Object> map = new HashMap<>();
        map.put("signId", us.getId());
        serviceResult.setData(map);
        return serviceResult.succeed("保存成功");
    }

    public GetCommonWxPushResponse getCommonWxPush(GetCommonWxPushRequest request) throws Exception {
        GetCommonWxPushResponse.Builder response = GetCommonWxPushResponse.newBuilder();
        response.setCode(ResultCode.SUCCEED_VALUE).setInfo("处理成功");
        int wxPushId = request.getWxPushId();
        if (wxPushId < 0) {
            response.setCode(ResultCode.PARAMETER_ERROR_VALUE).setInfo("参数错误");
            return response.build();
        }
        CommonWxPush wxPush = commonWxPushRepository.findById(wxPushId).orElse(null);
        if (Checker.isNone(wxPush)) {
            response.setCode(ResultCode.PARAMETER_ERROR_VALUE).setInfo("推送记录不存在");
            return response.build();
        }
        response.setDisplay(Checker.getIntegerValue(wxPush.getDisplay()));
        response.setTitle(Checker.getStringValue(wxPush.getTitle()));
        response.setContent(Checker.getStringValue(wxPush.getContent()));
        return response.build();
    }

    public SnsUserInfo getByUserId(int userId, int terminal){
        List<Object> params = new LinkedList<>();
        List<Integer> argTypes = new LinkedList<>();
        String sql = "select * from sns_user_info where terminal = ? and deleted = 0 ";
        params.add(terminal);
        argTypes.add(Types.INTEGER);


        if (userId > 0) {
            sql += "and user_id = ? ";
            params.add(userId);
            argTypes.add(Types.INTEGER);
        }
        sql += " limit 1 ";

        SnsUserInfo snsUserInfo = null;
        try {
            snsUserInfo = jdbcTemplate.queryForObject(
                    sql, params.toArray(), argTypes.stream().mapToInt(i -> i).toArray(), new BeanPropertyRowMapper<>(SnsUserInfo.class));
        } catch (IncorrectResultSizeDataAccessException e) {
            logger.error("UserService#getByUserId(userId={}): 查找不到结果", userId);
        }
        return snsUserInfo;
    }
}
