package cn.exploring.engine.server.db.service;

import cn.exploring.engine.server.db.dao.WxUserMapper;
import cn.exploring.engine.server.db.domain.*;
import cn.exploring.engine.server.db.domain.vo.UserVo;
import cn.exploring.engine.server.db.util.RedisUtil;
import cn.exploring.engine.server.db.util.ResponseUtil;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

@Service
public class WxUserService {
    @Resource
    private WxUserMapper userMapper;

    @Autowired
    private RedisUtil redisUtil;
    @Value("${projectRedis.keyPrefix.userInfo}")
    private String projectRedisKeyUserInfo;

    /**
     *
     * 从redis或mysql中查询用户信息
     * 如果redis没有，会从mysql里加载
     * 建议：没必要取最新信息时，从redis里取；非常有必要取最新信息时，从mysql里取
     *
     * @param id  用户ID
     * @param fresh  是否取最新数据。true=是；false或null=否。当为是时，从mysql里取; 当为否时，从redis里取
     * @return WxUser
     */
    public WxUser getUserInfoByIdFromCache(Integer id, Boolean... fresh) {
        // 判断id参数，无效直接返回null
        if (id == null || id <= 0) {
            return null;
        }

        // redis key
        String redisKey = projectRedisKeyUserInfo + id;

        // 从cache里取
        if (fresh == null || fresh.length <= 0 || fresh[0] == null || fresh[0] != true) {
            WxUser user = redisUtil.getObjFrom1And2Cache(redisKey, WxUser.class);
            if (user != null && user.getDeleted() != null) {
                return user;
            }
        }

        // 从mysql里取
        WxUser user = userMapper.selectByPrimaryKey(id);
        if (user != null) {
            redisUtil.setObjTo1And2Cache(redisKey, user);
        }

        return user;
    }

    /**
     * 返回所有记录
     * @return
     */
    public List<WxUser> listAll() {
        WxUserExample example = new WxUserExample();
        WxUserExample.Criteria criteria = example.createCriteria();

        criteria.andDeletedEqualTo(false);

        return userMapper.selectByExample(example);
    }

    public WxUser findById(Integer userId) {
        return userMapper.selectByPrimaryKey(userId);
    }

    public UserVo findUserVoById(Integer userId) {
        WxUser user = findById(userId);
        UserVo userVo = new UserVo();
        userVo.setNickname(user.getNickname());
        userVo.setAvatar(user.getAvatar());
        userVo.setDeleted(user.getDeleted());
        return userVo;
    }

    public WxUser queryByOid(String openId) {
        WxUserExample example = new WxUserExample();
        example.or().andWeixinOpenidEqualTo(openId);
        List<WxUser> users = userMapper.selectByExample(example);
        if (users == null || users.size() <= 0) {
            return null;
        } else {
            return users.get(0);
        }
    }

    public WxUser add(WxUser user) {
        user.setAddTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        userMapper.insertSelective(user);
        return user;
    }


    public int updateById(WxUser user) {
        user.setUpdateTime(LocalDateTime.now());

        String redisKey = projectRedisKeyUserInfo + user.getId();
        redisUtil.setObjTo1And2Cache(redisKey, user);

        return userMapper.updateByPrimaryKeySelective(user);
    }


    //用户名称，积分修改  symbol:1加，2，减，3，直接修改
    //|| !RegexUtil.isNumeric(String.valueOf(scores)) ||
    public int sendScores(Integer userId,Integer scores,Integer symbol) {
        if(userId == null  || symbol == null){
            return 0;
        }
        WxUser userDB = findById(userId);
        if(userDB == null){
            return 0;
        }
        //如果是减积分,当前用户积分必须大于等于要减的积分
        switch (symbol){
            case 1:
                userDB.setScores(userDB.getScores()  + scores);
                break;
            case 2:
                if(userDB.getScores().intValue() < scores) {return 0;}
                userDB.setScores(userDB.getScores()  + scores);
                break;
            case 3:
                userDB.setScores(scores);
                break;
        }
        return updateById(userDB);
    }


    public List<WxUser> querySelective(WxUser user, Integer page, Integer size, String sort, String order) {
        WxUserExample example = new WxUserExample();
        WxUserExample.Criteria criteria = example.createCriteria();

        if(user.getId() != null && user.getId() != 0){
            criteria.andIdEqualTo(user.getId());
        }

        if (!StringUtils.isEmpty(user.getUsername())) {
            criteria.andUsernameLike("%" + user.getUsername() + "%");
        }

        if (!StringUtils.isEmpty(user.getNickname())) {
            criteria.andNicknameLike("%" + user.getNickname() + "%");
        }

        if (!StringUtils.isEmpty(user.getWxId())) {
            criteria.andWxIdLike("%" + user.getWxId() + "%");
        }
        if (!StringUtils.isEmpty(user.getMobile())) {
            criteria.andMobileLike("%" + user.getMobile()+ "%");
        }
        criteria.andDeletedEqualTo(false);

        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {
            example.setOrderByClause(sort + " " + order);
        }

        PageHelper.startPage(page, size);
        return userMapper.selectByExample(example);
    }

    public int count() {
        WxUserExample example = new WxUserExample();
        example.or().andDeletedEqualTo(false);

        return (int) userMapper.countByExample(example);
    }

    public List<WxUser> queryByUsername(String username) {
        WxUserExample example = new WxUserExample();
        example.or().andUsernameEqualTo(username).andDeletedEqualTo(false);
        return userMapper.selectByExample(example);
    }


    public List<WxUser> queryByEmail(String email) {
        WxUserExample example = new WxUserExample();
        example.or().andEmailEqualTo(email);
        return userMapper.selectByExample(example);
    }


    public boolean checkByUsername(String username) {
        WxUserExample example = new WxUserExample();
        example.or().andUsernameEqualTo(username).andDeletedEqualTo(false);
        return userMapper.countByExample(example) != 0;
    }

    public List<WxUser> queryByMobile(String mobile) {
        WxUserExample example = new WxUserExample();
        example.or().andMobileEqualTo(mobile).andDeletedEqualTo(false);
        return userMapper.selectByExample(example);
    }

    //新添加方法，根据手机号查询，手机号应该还唯一标识，上面方法其它地方有调用，暂不修改
    public WxUser queryByOnlyMobile(String mobile) {
        WxUserExample example = new WxUserExample();
        example.or().andMobileEqualTo(mobile).andDeletedEqualTo(false);
        return userMapper.selectOneByExample(example);
    }

    public List<WxUser> queryByOpenid(String openid) {
        WxUserExample example = new WxUserExample();
        example.or().andWeixinOpenidEqualTo(openid).andDeletedEqualTo(false);
        return userMapper.selectByExample(example);
    }

    public Integer updateUserInfo(Integer userId, Integer weight, Byte sex,
                                              Integer height, LocalDate birthDay, Integer footPace) {
        WxUserExample example = new WxUserExample();
        WxUserExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false).andIdEqualTo(userId);
        WxUser userData = userMapper.selectOneByExample(example);

        userData.setBirthday(birthDay);
        userData.setWeight(weight);
        if (sex == null) {
            userData.setGender(Byte.valueOf("0"));
        } else {
            userData.setGender(Byte.valueOf(sex.toString()));
        }
        userData.setHeight(height);
        userData.setStepSize(footPace);
        return updateById(userData);
    }

    /**
     * 是否已经更新过用户的体侧数据
     * @param userId
     * @return
     */
    public Boolean isUpdateUserBodySizeInfo(Integer userId) {
        WxUserExample example = new WxUserExample();
        WxUserExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false).andIdEqualTo(userId);
        WxUser userInfo = userMapper.selectOneByExample(example);

        return userInfo.getStepSize() == null;
    }

    /**
     * 根据模糊搜索用户昵称
     * @param fuzzyNickname
     * @return
     */
    public List<WxUser> selectUserInfoByFuzzyNickname(String fuzzyNickname) {
        WxUserExample example = new WxUserExample();
        WxUserExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false).andNicknameLike(fuzzyNickname);
        return userMapper.selectByExample(example);
    }


    /**
     * 批量删除
     */
    @Transactional(rollbackFor=Exception.class)
    public Object deleteByIds(Integer[] ids) {
        WxUserExample example = new WxUserExample();
        WxUserExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false).andIdIn(Arrays.asList(ids));

        userMapper.logicalDeleteByExample(example);

        return ResponseUtil.ok();
    }
}
