package com.ruoyi.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.user.domain.User;
import com.ruoyi.user.domain.UserThirdIdentity;
import com.ruoyi.user.domain.bo.PersonalDataBo;
import com.ruoyi.user.domain.bo.UserBo;
import com.ruoyi.user.domain.vo.UserStatisticsVo;
import com.ruoyi.user.domain.vo.UserVo;
import com.ruoyi.user.exception.UserExceptionEnum;
import com.ruoyi.user.mapper.UserMapper;
import com.ruoyi.user.mapper.UserThirdIdentityMapper;
import com.ruoyi.user.service.IUserService;
import com.ruoyi.weixin.domain.WxUserDto;
import com.ruoyi.weixin.service.WxUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 小程序用户管理Service业务层处理
 *
 * @author wuchao
 * @date 2022-03-03
 */
@RequiredArgsConstructor
@Service
public class UserServiceImpl implements IUserService {

    private final UserMapper baseMapper;

    private final WxUserService wxUserService;

    private final UserThirdIdentityMapper userThirdIdentityMapper;


    /**
     * 查询小程序用户管理
     *
     * @param id 小程序用户管理主键
     * @return 小程序用户管理
     */
    @Override
    public UserVo queryById(Long id) {
        UserVo userVo = baseMapper.selectVoById(id);
        if(ObjectUtil.isNull(userVo)) {
            return null;
        }
        return userVo;
    }

    /**
     * 查询小程序用户管理列表
     *
     * @param bo 小程序用户管理
     * @return 小程序用户管理
     */
    @Override
    public TableDataInfo<UserVo> queryPageList(UserBo bo, PageQuery pageQuery) {
        if(ObjectUtil.isNotNull(bo.getCreateDayStart())) {
            bo.setCreateDayStart(DateUtil.beginOfDay(bo.getCreateDayStart()));
        }
        if(ObjectUtil.isNotNull(bo.getCreateDayEnd())) {
            bo.setCreateDayEnd(DateUtil.endOfDay(bo.getCreateDayEnd()));
        }

        LambdaQueryWrapper<User> lqw = buildQueryWrapper(bo);
        Page<UserVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询小程序用户管理列表
     *
     * @param bo 小程序用户管理
     * @return 小程序用户管理
     */
    @Override
    public List<UserVo> queryList(UserBo bo) {
        LambdaQueryWrapper<User> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<User> buildQueryWrapper(UserBo bo) {
        LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();
        lqw.like(StrUtil.isNotBlank(bo.getMobile()), User::getMobile, bo.getMobile());
        lqw.like(StrUtil.isNotBlank(bo.getNickname()), User::getNickname, bo.getNickname());
        lqw.like(StrUtil.isNotBlank(bo.getRealName()), User::getRealName, bo.getRealName());
        lqw.like(StrUtil.isNotBlank(bo.getBusinessId()), User::getBusinessId, bo.getBusinessId());
        lqw.eq(StrUtil.isNotBlank(bo.getHeadPhoto()), User::getHeadPhoto, bo.getHeadPhoto());
        lqw.eq(ObjectUtil.isNotNull(bo.getAge()), User::getAge, bo.getAge());
        lqw.eq(ObjectUtil.isNotNull(bo.getGender()), User::getGender, bo.getGender());
        lqw.eq(StrUtil.isNotBlank(bo.getBirthday()), User::getBirthday, bo.getBirthday());
        lqw.eq(ObjectUtil.isNotNull(bo.getStatus()), User::getStatus, bo.getStatus());
        lqw.eq(ObjectUtil.isNotNull(bo.getLastLoginTime()), User::getLastLoginTime, bo.getLastLoginTime());
        lqw.ge(ObjectUtil.isNotNull(bo.getCreateDayStart()), User::getCreateTime, bo.getCreateDayStart());
        lqw.le(ObjectUtil.isNotNull(bo.getCreateDayEnd()), User::getCreateTime, bo.getCreateDayEnd());
        lqw.orderByDesc(User::getCreateTime);
        return lqw;
    }

    @Override
    public List<UserVo> queryListForSelect(UserBo bo) {
        LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();
        lqw.select(User::getId, User::getNickname, User::getRealName, User::getMobile);
        if (StringUtils.isNotBlank(bo.getNickname())) {
            lqw.like(User::getNickname, bo.getNickname());
        }
        if (StringUtils.isNotBlank(bo.getRealName())) {
            lqw.like(User::getRealName, bo.getRealName());
        }
        if (ObjectUtil.isNotNull(bo.getMobile())) {
            lqw.eq(User::getMobile, bo.getMobile());
        }
        return this.baseMapper.selectVoList(lqw);
    }

    /**
     * 新增小程序用户管理
     *
     * @param bo 小程序用户管理
     * @return 结果
     */
    @Override
    public Boolean insertByBo(UserBo bo) {
        User add = BeanUtil.toBean(bo, User.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改小程序用户管理
     *
     * @param bo 小程序用户管理
     * @return 结果
     */
    @Override
    public Boolean updateByBo(UserBo bo) {
        User update = BeanUtil.toBean(bo, User.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(User entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除小程序用户管理
     *
     * @param ids 需要删除的小程序用户管理主键
     * @return 结果
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User authorization(WxUserDto wxUserDto) {
        String openId = wxUserDto.getOpenId();

        //查询此openid是否绑定过用户
        UserThirdIdentity userThirdIdentity = userThirdIdentityMapper.selectOne(
            new LambdaQueryWrapper<UserThirdIdentity>()
                .eq(UserThirdIdentity::getThirdType, 0)
                .eq(UserThirdIdentity::getIdentityCode, openId)
                .last("limit 1")
        );

        if (ObjectUtil.isNotNull(userThirdIdentity)) {
            return this.getById(userThirdIdentity.getUserId(), true);
        }


        User user = this.loadByMobile(wxUserDto.getMobile(), false);
        if(ObjectUtil.isNotNull(user))
        {
            //查询此用户是否绑定过微信
            userThirdIdentity = userThirdIdentityMapper.selectOne(
                new LambdaQueryWrapper<UserThirdIdentity>()
                    .eq(UserThirdIdentity::getThirdType, 0)
                    .eq(UserThirdIdentity::getUserId, user.getId())
                    .last("limit 1")
            );
            if (ObjectUtil.isNull(userThirdIdentity)) {
                userThirdIdentity = new UserThirdIdentity();
                userThirdIdentity.setUserId(user.getId());
                userThirdIdentity.setThirdType(0);
            }
            userThirdIdentity.setIdentityCode(openId);
            userThirdIdentityMapper.insertOrUpdate(userThirdIdentity);
            return user;
        }


        //创建用户
        user = new User();
        user.setBusinessId(wxUserDto.getBusinessId());
        user.setNickname(wxUserDto.getNickname());
        user.setHeadPhoto(wxUserDto.getHeadPhoto());
        user.setAge(wxUserDto.getAge());
        user.setGender(wxUserDto.getGender());//info.getGender()
        user.setRealName(wxUserDto.getRealName());
        user.setBirthday(wxUserDto.getBirthday());
        user.setStatus(true);
        user.setMobile(wxUserDto.getMobile());
        user.setCreateDay(new Date());
        user.setLastLoginTime(new Date());
        //保存用户信息
        this.baseMapper.insert(user);

        //保存第三方关系
        userThirdIdentity = new UserThirdIdentity();
        userThirdIdentity.setUserId(user.getId());
        userThirdIdentity.setThirdType(0);
        userThirdIdentity.setIdentityCode(openId);
        userThirdIdentityMapper.insert(userThirdIdentity);

        return user;
    }

    @Override
    public User loadByMobile(String mobile, Boolean tw) {
        User user = this.baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getMobile, mobile).last("limit 1"));
        if (tw && ObjectUtil.isNotNull(user)) {
            throw new ServiceException(UserExceptionEnum.MOBILE_USER_EXIST);
        }
        return user;
    }



    @Override
    public User getById(Long userId, boolean isThrow) {
        User obj = this.baseMapper.selectById(userId);
        if (ObjectUtil.isNull(obj)) {
            if (isThrow) {
                throw new ServiceException("用户不存在");
            }
        }
        return obj;
    }

    @Override
    public UserVo getUserById(Long userId, boolean isThrow) {
        UserVo obj = this.baseMapper.selectVoById(userId);
        if (ObjectUtil.isNull(obj)) {
            if (isThrow) {
                throw new ServiceException("用户不存在");
            }
        }

        return obj;
    }

    @Override
    public String getOpenId(String code) {
        return  wxUserService.getOpenIdByCode(code);
    }

    @Override
    public User loginAuthorization(String openId) {
        //查询此openid是否绑定过用户
        UserThirdIdentity userThirdIdentity = userThirdIdentityMapper.selectOne(
            new LambdaQueryWrapper<UserThirdIdentity>()
                .eq(UserThirdIdentity::getThirdType, 0)
                .eq(UserThirdIdentity::getIdentityCode, openId)
                .last("limit 1")
        );
        if (ObjectUtil.isNull(userThirdIdentity)) {
            throw new ServiceException(UserExceptionEnum.USER_THIRD_ID_NOT_EXISTS);
        }

        User user = this.getById(userThirdIdentity.getUserId(), true);
        user.setLastLoginTime(new Date());
        this.baseMapper.updateById(user);
        return user;
    }

    @Override
    public void personalDataUpdate(PersonalDataBo bo, Long userId) {
        User user = this.getById(userId, true);
        BeanUtil.copyProperties(bo, user);
        this.baseMapper.updateById(user);
    }

    /**
     * 首页头部统计
     * @return
     */
    @Override
    public Integer queryUserSumForHome() {
        Long count = this.baseMapper.selectCount(new LambdaQueryWrapper<User>());
        return count.intValue();
    }

    /**
     * 首页统计 最近七日注册数
     * @return
     */
    @Override
    public List<UserStatisticsVo> statisticsUserRegisterForHome() {
        // 往前查询最近七日
        Date endDay = new Date();
        DateTime startDay = DateUtil.offsetDay(endDay, -7);

        String start = DateUtil.format(startDay, "yyyy-MM-dd");
        String end = DateUtil.format(endDay, "yyyy-MM-dd");
        List<UserStatisticsVo> list = this.baseMapper.selectUserRegister(start, end);

        // 七天的日期
        List<UserStatisticsVo> dataList = this.completionDate(start, end);
        for (UserStatisticsVo vo : dataList) {
            String createDay = vo.getCreateDay();
            Optional<UserStatisticsVo> first = list.stream().filter(e -> e.getCreateDay().equals(createDay)).findFirst();
            if(first.isPresent()){
                UserStatisticsVo userVo = first.get();
                vo.setUserSum(userVo.getUserSum());
            }
        }
        return dataList;
    }

    @Override
    public void logout(Long userId, Integer type) {
        userThirdIdentityMapper.update(null, new LambdaUpdateWrapper<UserThirdIdentity>()
            .eq(UserThirdIdentity::getUserId, userId)
            .eq(UserThirdIdentity::getThirdType, type)
            .set(UserThirdIdentity::getIdentityCode, "")
        );
    }

    @Override
    public void addNum(Long userId) {
        this.baseMapper.update(null, new LambdaUpdateWrapper<User>()
            .eq(User::getId, userId)
            .setSql("order_num = order_num + 1")
        );
    }

    @Override
    public void updateBusinessId(List<User> users) {
        this.baseMapper.updateBatchById(users);
    }

    public static List<UserStatisticsVo> completionDate(String start, String end) {
        //日期格式化
        List<UserStatisticsVo> dateList = new ArrayList<>();

        DateTime startDate = DateUtil.parse(start, "yyyy-MM-dd");
        DateTime endDay = DateUtil.parse(end, "yyyy-MM-dd");
        while (startDate.compareTo(endDay)<=0) {
            String date = DateUtil.format(startDate, "yyyy-MM-dd");
            //添加日期
            UserStatisticsVo build = UserStatisticsVo
                .builder()
                .createDay(date)
                .userSum(Constants.NUM_ZERO)
                .build();
            dateList.add(build);
            startDate = DateUtil.offsetDay(startDate, 1);
        }
        return dateList;
    }

}
