package cn.pluss.platform.userInfo.impl;

import cn.hutool.crypto.SecureUtil;
import cn.jiguang.common.utils.StringUtils;
import cn.pluss.platform.channel.MchChannelRateNewService;
import cn.pluss.platform.constants.CommonError;
import cn.pluss.platform.dto.ChangePwdDTO;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.ipLocation.IpLocationService;
import cn.pluss.platform.mapper.*;
import cn.pluss.platform.merchant.MerchantBaseInfoService;
import cn.pluss.platform.merchant.MerchantRateNewRecordService;
import cn.pluss.platform.merchant.MerchantStaffConnService;
import cn.pluss.platform.merchantChannelStatus.MerchantChannelStatusService;
import cn.pluss.platform.operationRecord.OperationRecordService;
import cn.pluss.platform.other.JfShopParam;
import cn.pluss.platform.other.JfShopSyncUser;
import cn.pluss.platform.phoneValidateCode.PhoneValidateCodeService;
import cn.pluss.platform.userApp.UserAppService;
import cn.pluss.platform.userInfo.UserInfoService;
import cn.pluss.platform.util.*;
import cn.pluss.platform.vo.MerchantStaffConnVO;
import cn.pluss.platform.wechat.WxConstants;
import cn.pluss.platform.wx.WxAccessTokenRequest;
import cn.pluss.platform.wx.WxCommonService;
import cn.pluss.platform.wx.WxTemolateRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 基础服务类
 *
 * @author djh
 */
@Slf4j
public abstract class BaseUserInfoService extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Setter(onMethod_ = {@Lazy, @Autowired})
    private MerchantBaseInfoService merchantBaseInfoService;

    @Setter(onMethod_ = {@Autowired})
    private PhoneValidateCodeMapper phoneValidateCodeMapper;

    @Setter(onMethod_ = {@Autowired})
    private UserAppMapper userAppMapper;

    @Resource
    protected MerchantRateMapper merchantRateMapper;

    @Setter(onMethod_ = {@Autowired})
    private MerchantChannelStatusService mcsService;

    @Autowired
    private MchChannelRateNewService sxfChangeRateNewService;

    @Autowired
    private MchChannelRateNewService ryxChangeRateNewService;


    @Setter(onMethod_ = {@Lazy, @Autowired})
    protected UserAppService userAppService;

    @Setter(onMethod_ = {@Autowired})
    private MerchantBaseInfoMapper merchantBaseInfoMapper;

    @Setter(onMethod_ = {@Autowired})
    private RestTemplate restTemplate;

    @Setter(onMethod_ = {@Autowired})
    private MerchantStaffConnService staffConnService;

    @Autowired
    protected PhoneValidateCodeService phoneValidateCodeService;

    @Autowired
    protected OperationRecordService opRecordService;

    @Setter(onMethod_ = {@Lazy, @Autowired})
    private MerchantStaffConnService merchantStaffConnService;

    @Setter(onMethod_ = {@Lazy, @Autowired})
    private MerchantRateNewRecordService merchantRateNewRecordService;

    @Autowired
    @Lazy
    private MchChannelRateNewService ysChangeRateService;

    @Autowired
    @Lazy
    private MchChannelRateNewService ysChangeRateNewService;

    @Setter(onMethod_ = {@Lazy, @Autowired})
    private WxCommonService wxCommonService;

    @Setter(onMethod_ = {@Autowired})
    private UserInfoMapper userInfoMapper;

    @Override
    public void bindInviteCode(String inviteCode) {
        UserApp userApp = userAppService.queryUserAppByToken();
        if (userApp.getParentId() != null) {
            throw new MsgException("拒绝访问!");
        }

        UserApp parentApp = new UserApp();
        parentApp.setInviteNum(inviteCode.toUpperCase());
        List<UserApp> queryUserAppList = userAppService.queryUserAppList(parentApp);

        if (queryUserAppList == null || queryUserAppList.isEmpty()) {
            throw new MsgException("无效的邀请码！");
        }

        UserApp pUserApp = queryUserAppList.get(0);

        if (pUserApp.getUserType().equals("agent_staff")) {
            UserApp agentUa = userAppService.getOne(new QueryWrapper<UserApp>().eq("userId", pUserApp.getParentId()));
            if (!Objects.equals(agentUa.getStatus(), 3) || !Objects.equals(agentUa.getBankStatus(), 3)) {
                throw new MsgException("邀请码无效，当前推广服务商未完成实名");
            }

            UserInfo ui = getById(agentUa.getUserId());
            if (Objects.equals(ui.getStatus(), UserInfo.STATUS_NO_SPREAD)) {
                throw new MsgException("当前推广服务商存在违规行为, 已被关闭推广权限, 请联系收银呗客服申诉");
            }
        } else {
            if (!Objects.equals(pUserApp.getStatus(), 3) || !Objects.equals(pUserApp.getBankStatus(), 3)) {
                throw new MsgException("邀请码无效，当前推广服务商未完成实名");
            }

            UserInfo ui = getById(pUserApp.getUserId());
            if (Objects.equals(ui.getStatus(), UserInfo.STATUS_NO_SPREAD)) {
                throw new MsgException("当前推广服务商存在违规行为, 已被关闭推广权限, 请联系收银呗客服申诉");
            }

            if (!"1".equals(pUserApp.getSpreadFlag())) {
                throw new MsgException("该服务商已注册多个账户，该推广码无效");
            }
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setId(userApp.getUserId());
        userInfo = queryUserInfo(userInfo);
        userInfo.setInviteCode(inviteCode);
        updateUserInfo(userInfo);

        userApp.setParentId(pUserApp.getUserId());
        UserApp.setSort(pUserApp, userApp);
        UserApp.setRoleInfo(pUserApp, userApp, null);
        userApp.setInviteNum(getRandomNum());

        if ("agent_staff".equals(pUserApp.getUserType())) {
            userApp.setParentId(pUserApp.getParentId());
            userApp.setAgentStaffId(pUserApp.getUserId());
        } else {
            userApp.setParentId(pUserApp.getUserId());
        }
        userAppService.updateById(userApp);
    }

    protected UserApp getSaveUserAppInfo(UserInfo userInfo) {

        // 保存用户信息到userApp表
        UserApp userApp = new UserApp();
        userApp.setUserId(userInfo.getId());
        // 默认一级推广员
        userApp.setLevel(1);
        userApp.setCreateDt(new Date());
        userApp.setStatus(0);
        userApp.setUserType("promoter");

        userApp.setInviteNum(getRandomNum());

        // 根据邀请码查询确定当前用户的上级关系
        if (!StringUtils.isEmpty(userInfo.getInviteCode())) {
            UserApp parentApp = new UserApp();
            parentApp.setInviteNum(userInfo.getInviteCode());
            parentApp = userAppService.queryUserApp(parentApp);
            if (parentApp == null) {
                throw new MsgException("请输入正确的邀请码");
            }

            userApp.setParentId(parentApp.getUserId());

            if ("agent_staff".equals(parentApp.getUserType())) {
                userApp.setParentId(parentApp.getParentId());
                userApp.setAgentStaffId(parentApp.getUserId());
            } else {
                userApp.setParentId(parentApp.getUserId());
            }
        }
        return userApp;
    }

    private String getRandomNum() {
        String inviteNum;
        UserApp condition = new UserApp();

        do {
            inviteNum = StringUtil.genRandomNum(5);
            condition.setInviteNum(inviteNum);
            UserApp userApp = userAppService.queryUserApp(condition);
            if (userApp == null) {
                return inviteNum;
            }
        } while (true);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void changePhone(ChangePwdDTO changePwdDTO) throws MsgException {
        UserApp userApp = userAppService.queryUserAppByToken();

        if ("agent".equals(userApp.getUserType()) && !"ZY_BST".equals(userApp.getRoleCode())) {
            // 非倍斯特的代理账号，不允许修改手机号
            throw new MsgException("原代理账号不支持修改手机号");
        }


        // step 1、数据校验
        UserInfo userInfoCondition = new UserInfo();
        userInfoCondition.setLoginName(changePwdDTO.getPhone());
        UserInfo userInfo = baseMapper.queryUserInfo(userInfoCondition);
        if (userInfo != null) {
            QueryWrapper<UserApp> qWrapper = new QueryWrapper<UserApp>()
                    .eq("userId", userApp.getUserId())
                    .eq("userType", userApp.getUserType())
                    .last("limit 1");
            UserApp nua = userAppService.getOne(qWrapper);

            MsgException.checkNonNull(nua, "新手机号已经存在关联账号");
        }

        userInfo = baseMapper.selectById(userApp.getUserId());
        if (userInfo == null || !Objects.equals(userInfo.getPhone(), changePwdDTO.getOldPhone())) {
            throw new MsgException("无法获取用户信息");
        }

        if (!MD5Util.MD5Encode(changePwdDTO.getPassword(), "utf-8").equalsIgnoreCase(userInfo.getPassword())) {
            throw new MsgException("密码错误，请检查后重新输入");
        }

        // 校验手机验证码
        LambdaQueryWrapper<PhoneValidateCode> qWrapper = Wrappers.lambdaQuery();
        qWrapper.eq(PhoneValidateCode::getPhone, changePwdDTO.getPhone())
                .orderByDesc(PhoneValidateCode::getSendDt)
                .last("limit 1");
        PhoneValidateCode existValidCode = phoneValidateCodeService.getOne(qWrapper);
        MsgException.checkNull(existValidCode, "验证码不存在或验证码已失效");

        if (!Objects.equals(existValidCode.getCode(), changePwdDTO.getCode())) {
            if (existValidCode.getAttempt() == null) {
                existValidCode.setAttempt(1);
                phoneValidateCodeService.updateById(existValidCode);
                throw new MsgException("验证码错误");
            }

            int newAttemptCount = existValidCode.getAttempt() + 1;
            if (newAttemptCount == 5) {
                phoneValidateCodeService.removeById(existValidCode.getId());
                throw new MsgException("验证码错误，请重新获取验证码");
            }
        } else {
            phoneValidateCodeService.removeById(existValidCode.getId());
        }


        // step 2、修改主账号手机号
        userInfo.setOldPhone(changePwdDTO.getOldPhone());
        userInfo.setPhone(changePwdDTO.getPhone());
        userInfo.setLoginName(changePwdDTO.getPhone());
        userInfo.setUpdateTime(new Date());
        userInfo.setUpdator(changePwdDTO.getPhone());
        baseMapper.updateUserInfo(userInfo);
        // step 3、修改子账号(店员)手机号
        changeChildPhone(userInfo.getOldPhone(), userInfo.getPhone());

        try {
            if (userApp != null && "promoter".equals(userApp.getUserType())) {
                String url = "https://shop.shouyinbei.net/web/wmerchant.php?c=site&a=entry&ctrl=store&ac=oauth&op=set_password&ta=update_phone&do=web&m=we7_wmall&i=1";
                url += "&old=" + changePwdDTO.getOldPhone();
                url += "&new=" + changePwdDTO.getPhone();
                log.info("==================>修改小程序请求链接为: {}<=================", url);
                try {
                    String result = restTemplate.getForObject(url, String.class);
                    log.info("==================>修改小程序手机号结果: {}<=================", result);
                } catch (Exception e) {
                    log.info("==================>修改小程序手机号异常: {}<=================", e.getMessage());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 修改子账号手机号
     *
     * @param oldPhone 老手机号
     * @param phone    新手机号
     */
    private void changeChildPhone(String oldPhone, String phone) {
        UserInfo queryCondition = new UserInfo();
        queryCondition.setPhone(oldPhone);
        List<UserInfo> queryUserInfoListLikeByPhone = baseMapper.queryUserInfoListLikeByPhone(queryCondition);
        for (UserInfo userInfo : queryUserInfoListLikeByPhone) {
            String childPhone = userInfo.getPhone();
            if (StringUtils.isNotEmpty(childPhone) && childPhone.length() > 11 && childPhone.contains("@")) {
                String newPhone = phone + childPhone.substring(childPhone.indexOf("@"));
                userInfo.setPhone(newPhone);
                userInfo.setLoginName(newPhone);
                userInfo.setUpdateTime(new Date());
                baseMapper.updateUserInfo(userInfo);
            }
        }
    }

    @Override
    public Map<String, Object> login(String loginName, String password) {
        Map<String, Object> resultMap = new HashMap<>();

        UserInfo userInfo = new UserInfo();
        userInfo.setLoginName(loginName);
        String mdPasswordString = MD5Util.MD5Encode(password, "utf-8");
        UserInfo checkUserInfo;
        checkUserInfo = queryUserInfo(userInfo);

        MsgException.checkNull(checkUserInfo, "无此用户！");

        // 原则上不能以原密码进行对比，这里只是给后台登录页面一个方便
        if (password.equalsIgnoreCase(checkUserInfo.getPassword())) {
            UserApp queryUserApp;
            queryUserApp = userAppMapper.selectUserApp(new QueryWrapper<>().eq("ua.userId", checkUserInfo.getId()));
            log.error("=====================queryUserApp=====================" + JSON.toJSONString(queryUserApp));
            String genRandomNum = StringUtil.genRandomNum(6) + StringUtil.getBillno() + StringUtil.genRandomNum(6);
            UserApp uApp = new UserApp();
            uApp.setToken(genRandomNum);
            uApp.setId(queryUserApp.getId());
            userAppMapper.updateById(uApp);
            queryUserApp.setToken(genRandomNum);
            resultMap.put("userInfo", checkUserInfo);
            Long userId = checkUserInfo.getId();
            MerchantBaseInfo merchantBaseInfo = new MerchantBaseInfo();
            merchantBaseInfo.setUserId(userId + "");
            List<MerchantBaseInfo> queryMerchantBaseInfoList = merchantBaseInfoService.queryMerchantBaseInfoList(merchantBaseInfo);
            if (null != queryMerchantBaseInfoList && !queryMerchantBaseInfoList.isEmpty()) {
                merchantBaseInfo = queryMerchantBaseInfoList.get(0);
                queryUserApp.setMercId(merchantBaseInfo.getId());
                queryUserApp.setMerchantType(merchantBaseInfo.getMerchantType());
                queryUserApp.setMerchantName(merchantBaseInfo.getAlias());
                queryUserApp.setAlias(merchantBaseInfo.getAlias());
            }
            resultMap.put("userApp", queryUserApp);
            return resultMap;
        }

        if (!mdPasswordString.equalsIgnoreCase(checkUserInfo.getPassword())) {
            throw new MsgException("密码不正确！");
        }
        // 获取当前用户的详情信息来判断用户的登陆类型
        UserApp queryUserApp = new UserApp().setUserId(checkUserInfo.getId());
        queryUserApp = userAppMapper.selectOne(new QueryWrapper<>(queryUserApp));

        // TODO 去掉该用户只能登录一个设备
        //String genRandomNum = StringUtil.genRandomNum(6) + StringUtil.getBillno() + StringUtil.genRandomNum(6);
        String genRandomNum = loginName;

        UserApp uApp = new UserApp();
        uApp.setToken(genRandomNum);
        uApp.setId(queryUserApp.getId());

        MerchantChannelStatus merchantChannelStatus = mcsService.getValidData(queryUserApp.getMerchantCode());
        uApp.setMerchantId(merchantChannelStatus == null ? null : merchantChannelStatus.getMerchantId());
        uApp.setMerchantAuditStatus(merchantChannelStatus == null ? "0" : merchantChannelStatus.getAppStatus());

        if (StringUtil.isEmpty(queryUserApp.getJfShopKey())) {
            //TODO 积分商城登录后 加密用户ID用户Code等数据 用户积分商城那边默认登录 确认登录用户是哪个
            JfShopSyncUser jfUser = new JfShopSyncUser(checkUserInfo, queryUserApp);
            String aesKey = jfUser.createAesData(JfShopParam.pubKey);
            if (StringUtils.isNotEmpty(aesKey)) {
                String key = Base64Util.encode(aesKey);
                uApp.setJfShopKey(key);
                queryUserApp.setJfShopKey(key);
            }
        }
        userAppMapper.updateById(uApp);

        queryUserApp.setToken(genRandomNum);
        checkUserInfo.setPassword(MD5Util.MD5Encode(password, "utf-8"));

        LambdaUpdateWrapper<UserInfo> uWrapper = Wrappers.lambdaUpdate();
        uWrapper.eq(UserInfo::getId, checkUserInfo.getId());
        uWrapper.set(UserInfo::getFaceCert, 0);
        userInfoMapper.update(null, uWrapper);

        if ("staff".equals(queryUserApp.getUserType())) {

            List<MerchantStaffConnVO> connList = staffConnService.getListByUserId(queryUserApp.getUserId() + "");
            if (connList.size() == 1) {
                // 只属于一家的员工时，拉出在所属商店的关联信息以及权限信息等
                MerchantStaffConnVO connVO = connList.get(0);
                queryUserApp.setMerchantCode(connVO.getMerchantCode());

                UserApp bossUserApp = new UserApp();
                bossUserApp.setMerchantCode(queryUserApp.getMerchantCode());
                bossUserApp.setUserType("promoter");
                bossUserApp = userAppMapper.selectOne(new QueryWrapper<>(bossUserApp));

//                queryUserApp.setLeshuaStatus(bossUserApp.getLeshuaStatus());
                queryUserApp.setLevel(bossUserApp.getLevel());
                queryUserApp.setStatus(bossUserApp.getStatus());
                queryUserApp.setPermissionBill(connVO.getPermissionBill());
            }
            resultMap.put("connList", connList);
        }


        resultMap.put("userInfo", checkUserInfo);
        MerchantBaseInfo merchantBaseInfo = new MerchantBaseInfo();
        if (StringUtils.isNotEmpty(queryUserApp.getMerchantCode())) {
            merchantBaseInfo.setMerchantCode(queryUserApp.getMerchantCode());
            List<MerchantBaseInfo> queryMerchantBaseInfoList = merchantBaseInfoService.queryMerchantBaseInfoList(merchantBaseInfo);
            if (null != queryMerchantBaseInfoList && !queryMerchantBaseInfoList.isEmpty()) {
                merchantBaseInfo = queryMerchantBaseInfoList.get(0);
                queryUserApp.setMercId(merchantBaseInfo.getId());
                queryUserApp.setMerchantType(merchantBaseInfo.getMerchantType());
                queryUserApp.setMerchantName(merchantBaseInfo.getAlias());
                queryUserApp.setAlias(merchantBaseInfo.getAlias());
            }
        }

        resultMap.put("userApp", queryUserApp);

        clearJpushAlias(queryUserApp.getUserId() + "");

        OperationRecord opRecord = new OperationRecord();
        opRecord.setUserId(queryUserApp.getUserId() + "");
        opRecord.setDictValue("APP_LOGIN");
        opRecord.setRemark("用户登录");
        opRecord.setOperator(queryUserApp.getUserId() + "");
        opRecordService.save(opRecord);
        return resultMap;
    }

    private void clearJpushAlias(String userId) {
        // 删除极光别名
        try {
            restTemplate.delete("https://device.jpush.cn/v3/aliases/" + userId);
        } catch (Exception ignored) {
        }
    }

    @Override
    public void changeRate(String userId, Integer rate) {
        UserApp userApp = userAppMapper.selectByUserId(userId);

        LambdaQueryWrapper<MerchantChannelStatus> qWrapper = Wrappers.lambdaQuery();
        qWrapper.eq(MerchantChannelStatus::getMerchantCode, userApp.getMerchantCode());
        qWrapper.eq(MerchantChannelStatus::getStatus, MerchantChannelStatus.AUDIT_STATUS_SUCCESS);
        List<MerchantChannelStatus> mcsList = mcsService.list(qWrapper);

        for (MerchantChannelStatus mcs : mcsList) {
            QueryWrapper<MerchantRateNewRecord> queryWrapper = new QueryWrapper<MerchantRateNewRecord>()
                    .eq("merchantId", mcs.getMerchantId()).orderByDesc("createTime").last("limit 1");
            MerchantRateNewRecord record = merchantRateNewRecordService.getOne(queryWrapper);

            if (record != null) {
                if (record.getWxRate() < rate) {
                    MsgException.throwException("当前费率小于等于需要修改的费率，无需修改！");
                } else if (record.getWxRate().intValue() == rate.intValue()) {
                    MsgException.throwException("当前费率已经修改成功，无需再次修改！");
                }
            }
            MerchantRateNew rateNew = new MerchantRateNew();
            rateNew.setAliRate(rate);
            rateNew.setWxRate(rate);
            rateNew.setBankRate(rate);
            rateNew.setBankRateLarge(rate);
            rateNew.setChannel(mcs.getChannel());
            rateNew.setMerchantId(mcs.getMerchantId());
            MerchantRateNew.setRateValue(rateNew);
            switch (mcs.getChannel()) {
                case 1:
                    sxfChangeRateNewService.changeRate(userId, rateNew, false);
                    break;
                case 2:
                    // 乐刷的, 暂不考虑
                    break;
                case 3:
                    ryxChangeRateNewService.changeRate(userId, rateNew, false);
                    break;
                case 4:
                    if (StringUtils.isEmpty(mcs.getApplicationId())) {
                        ysChangeRateNewService.changeRate(userId, rateNew, false);
                    } else {
                        ysChangeRateService.changeRate(userId, rateNew, false);
                    }
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    public void apiChangeRate(String userId, Integer rate) {
        UserApp userApp = userAppService.queryUserAppByToken();
        if (userApp == null) {
            throw new MsgException("拒绝访问");
        }

        MerchantRate selfRate = new MerchantRate().setUserId(userApp.getUserId() + "");
        selfRate = merchantRateMapper.selectOne(new QueryWrapper<>(selfRate));

        if (selfRate == null) {
            throw new MsgException("数据异常");
        }

        //费率校验
        if (rate < selfRate.getRate() || rate > 38) {
            throw new MsgException("商户费率应在0." + selfRate.getRate() + "%到0.38%之间");
        }

        changeRate(userId, rate);
    }

    @Override
    public JSONObject getUserMerchantBaseInfo() {
        UserApp userApp = userAppService.queryUserAppByToken();
        MerchantBaseInfo merchantBaseInfo = new MerchantBaseInfo().setMerchantCode(userApp.getMerchantCode()).setUserId(userApp.getUserId() + "");
        merchantBaseInfo = merchantBaseInfoMapper.selectOne(new QueryWrapper<>(merchantBaseInfo));

        UserInfo userInfo = new UserInfo().setId(userApp.getUserId());
        userInfo = queryUserInfo(userInfo);

        MerchantChannelStatus merchantChannelStatus = mcsService.getByMerchantCode(userApp.getMerchantCode());

        JSONObject result = new JSONObject();
        result.put("phone", userInfo.getPhone());
        result.put("token", userApp.getToken());
        result.put("inviteNum", userApp.getInviteNum());
        result.put("merchantCode", userApp.getMerchantCode());
        result.put("userName", userApp.getUserName());
        result.put("status", userApp.getStatus());
        result.put("bankStatus", userApp.getBankStatus());

        if (merchantBaseInfo != null) {
            result.put("merchantName", merchantBaseInfo.getMerchantName());
            result.put("merchantType", merchantBaseInfo.getMerchantType());
            result.put("alisa", merchantBaseInfo.getAlias());
        } else {
            result.put("merchantName", null);
            result.put("merchantType", null);
            result.put("alisa", null);
        }

        if (merchantChannelStatus != null) {
            result.put("merchantId", merchantChannelStatus.getMerchantId());
            result.put("merchantAuditStatus", merchantChannelStatus.getAppStatus());
        } else {
            result.put("merchantId", null);
            result.put("merchantAuditStatus", null);
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePayPassword(UserInfo userInfo) {
        UserApp userApp = userAppService.queryUserAppByToken();
        // 只有推广者可以进入该方法
        if (!("promoter".equals(userApp.getUserType()) || "agent".equals(userApp.getUserType()))) {
            throw new MsgException("拒绝访问");
        }

        if (StringUtils.isEmpty(userInfo.getPayPassword())) {
            throw new MsgException("缺少支付密码");
        }

        UserInfo tokenUserInfo = new UserInfo().setId(userApp.getUserId());
        tokenUserInfo = getOne(new QueryWrapper<>(tokenUserInfo));

        if (tokenUserInfo.getPhone().contains("@")) {
            throw new MsgException("请切换至主商户进行操作");
        }

        if (StringUtils.isEmpty(userInfo.getCheckCode()) && StringUtils.isEmpty(userInfo.getOldPayPassword())) {
            throw new MsgException("缺少验证码或支付密码");
        }

        if (StringUtils.isNotEmpty(userInfo.getCheckCode())) {
            PhoneValidateCode phoneValidateCode;
            QueryWrapper<PhoneValidateCode> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("phone", tokenUserInfo.getPhone());
            queryWrapper.orderByDesc("sendDt");
            queryWrapper.last("limit 1");
            phoneValidateCode = phoneValidateCodeMapper.selectOne(queryWrapper);

            MsgException.checkNull(phoneValidateCode, "未获取验证码");

            MsgException.checkUnequals(userInfo.getCheckCode(), phoneValidateCode.getCode(), "验证码不正确");

            phoneValidateCodeMapper.deleteById(phoneValidateCode.getId());
        } else {
            verifyPayPassword(tokenUserInfo.getId(), userInfo.getOldPayPassword());
        }

        userInfo.setPayPassword(SecureUtil.md5(userInfo.getPayPassword()));
        userInfo.setId(tokenUserInfo.getId());
        updateById(userInfo);

    }

    @Override
    public void apiVerifyPayPassword(String payPassword) {
        UserApp userApp = userAppService.queryUserAppByToken();
        verifyPayPassword(userApp.getUserId(), payPassword);
    }

    @Override
    public void verifyPayPassword(Long userId, String payPassword) {
        if (userId == null) {
            throw new MsgException("用户不存在");
        }

        UserInfo userInfo = getMainUserInfo(userId);

        if (!SecureUtil.md5(payPassword).equals(userInfo.getPayPassword())) {
            throw new MsgException("安全密码错误");
        }
    }

    @Override
    public UserInfo getMainUserInfo(Long id) {
        UserInfo result = baseMapper.selectMainUserInfo(id);
        if (result == null) {
            result = baseMapper.selectById(id);
        }
        return result;
    }

    @Override
    public void appVerifyFaceCert() {
        UserApp tokenUserApp = userAppService.queryUserAppByToken();
        verifyFaceCert(tokenUserApp.getUserId());
    }

    @Override
    public void verifyFaceCert(Long userId) {
        LambdaUpdateWrapper<UserInfo> uWrapper = Wrappers.lambdaUpdate();
        uWrapper.eq(UserInfo::getId, userId)
                .set(UserInfo::getFaceCert, "1")
                .set(UserInfo::getFaceCompare, "1");

        baseMapper.update(null, uWrapper);
    }

    @Override
    public void forgetPwd(UserInfo userInfo) {
        UserInfo queryUserInfo = new UserInfo();
        queryUserInfo.setLoginName(userInfo.getPhone());
        // 根据手机号获取当前用户信息
        queryUserInfo = getOne(new QueryWrapper<>(queryUserInfo).last("limit 1"));

        MsgException.checkNull(queryUserInfo, CommonError.NO_EXIST_ACCOUNT);

        // 校验手机验证码
        LambdaQueryWrapper<PhoneValidateCode> qWrapper = Wrappers.lambdaQuery();
        qWrapper.eq(PhoneValidateCode::getPhone, queryUserInfo.getPhone())
                .orderByDesc(PhoneValidateCode::getSendDt)
                .last("limit 1");
        PhoneValidateCode existValidCode = phoneValidateCodeService.getOne(qWrapper);
        MsgException.checkNull(existValidCode, "验证码不存在或验证码已失效");

        if (!Objects.equals(existValidCode.getCode(), userInfo.getCheckCode())) {
            if (existValidCode.getAttempt() == null) {
                existValidCode.setAttempt(1);
                phoneValidateCodeService.updateById(existValidCode);
                throw new MsgException("验证码错误");
            }

            int newAttemptCount = existValidCode.getAttempt() + 1;
            if (newAttemptCount == 5) {
                phoneValidateCodeService.removeById(existValidCode.getId());
                throw new MsgException("验证码错误，请重新获取验证码");
            }
        } else {
            phoneValidateCodeService.removeById(existValidCode.getId());
        }

        // 忘记密码
        UserInfo updateUserInfo = new UserInfo();
        updateUserInfo.setId(queryUserInfo.getId());
        updateUserInfo.setPassword(MD5Util.MD5Encode(userInfo.getPassword(), "utf-8"));
        updateUserInfo.setUpdateTime(new Date());
        updateById(updateUserInfo);

        // 修改小程序密码
        UserApp userApp = new UserApp().setUserId(updateUserInfo.getId());
        userApp = userAppService.queryUserApp(userApp);
        if (userApp != null && "promoter".equals(userApp.getUserType())) {
            String url = "https://shop.shouyinbei.net/web/wmerchant.php?c=site&a=entry&ctrl=store&ac=oauth&op=set_password&do=web&m=we7_wmall&i=1";
            url += "&password=" + updateUserInfo.getPassword();
            url += "&mobile=" + queryUserInfo.getLoginName();
            log.info("==================>修改小程序请求链接为: {}<=================", url);
            try {
                String result = restTemplate.getForObject(url, String.class);
                log.info("==================>修改小程序密码结果: {}<=================", result);
            } catch (Exception e) {
                log.info("==================>修改小程序密码异常: {}<=================", e.getMessage());
            }
        }
    }

    @Override
    public void sendPayWxTemplateMessage(MerchantOrder order) {

        MerchantBaseInfo baseinfo = merchantBaseInfoService.getMerchantBaseInfoByMerchantCode(order.getMerchantCode());
        if (baseinfo != null) {
            UserInfo userInfo = baseMapper.selectById(baseinfo.getUserId());
            if (userInfo != null) {
                sendWxMessage(userInfo, order, baseinfo);
                if (userInfo.getLoginName().indexOf("@") > 0) {
                    userInfo = baseMapper.selectMainUserInfo(Long.valueOf(baseinfo.getUserId()));
                    sendWxMessage(userInfo, order, baseinfo);
                }
            }
        }
    }

    public void sendWxMessage(UserInfo userInfo, MerchantOrder order, MerchantBaseInfo baseinfo) {
        String tempId = "gqCxjTXqDbklITY2IdgqAJWvFLS6Q0zmlc--bEa9bs4";
        if (userInfo != null) {
            String first = "您有新的收款信息!";
            if (StringUtils.isNotEmpty(order.getRemark())) {
                first = "您有新的收款信息！（备注：" + order.getRemark() + "）";
            }
            String remark = "如对此订单有疑问，可以在app中查看详细信息";
            MerchantOrder.updateOrderTypeDesc(order);
            String[] array = {order.getConsumeFee() + "元", order.getMerchantName(), order.getOrderTypeDesc(), order.getOrderNumber(), DateUtils.formatDateDefault(order.getTransDt(), "yyyy-MM-dd HH:mm:ss")};
            WxTemolateRequest request = new WxTemolateRequest(userInfo.getOpenId(), tempId, null, null).buildData(first, remark, array);
            WxAccessTokenRequest tokenRequest = WxAccessTokenRequest.buidWxToken(ParametersUtil.SJ_APPID, ParametersUtil.SJ_APPSECRET, null, WxConstants.WX_SEND_TEMPLATE_URL);
            if (StringUtils.isNotEmpty(userInfo.getOpenId()) && "1".equals(baseinfo.getIsPushWxMessage())) {
                wxCommonService.sendTemplateMsg(request, tokenRequest);
            }
            //获取当前订单是否是由员工进行收款
            String staffCode = order.getStaffCode();
            if (StringUtils.isNotEmpty(staffCode) && StringUtil.isNumber(staffCode)) {
                UserInfo staffInfo = baseMapper.selectById(Long.parseLong(staffCode));
                if (staffInfo != null) {
                    MerchantStaffConn conn = merchantStaffConnService.getStaffConnInfoByCodeAndId(staffCode, order.getMerchantCode());
                    if (conn != null && StringUtils.isNotEmpty(staffInfo.getOpenId()) && "1".equals(conn.getIsPushWxMessage())) {
                        request.setTouser(staffInfo.getOpenId());
                        wxCommonService.sendTemplateMsg(request, tokenRequest);
                    }
                }
            }
            QueryWrapper<UserApp> queryWrapper = new QueryWrapper<UserApp>()
                    .eq("merchantCode", order.getMerchantCode()).eq("userType", "staff");
            List<UserApp> list = userAppService.list(queryWrapper);
            if (!list.isEmpty()) {
                for (UserApp u : list) {
                    UserInfo info = userInfoMapper.selectById(u.getUserId());
                    if (info != null && StringUtil.isNotEmpty(info.getOpenId())) {
                        request.setTouser(info.getOpenId());
                        wxCommonService.sendTemplateMsg(request, tokenRequest);
                    }
                }
            }
        }
    }

    @Override
    public UserInfo getUserInfoByLoginName(String loginName) {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>().eq("loginName", loginName);
        return baseMapper.selectOne(queryWrapper);
    }
}