package com.zhongzheng.framework.web.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.zhongzheng.common.exception.CustomException;
import com.zhongzheng.common.utils.DateUtils;
import com.zhongzheng.modules.collect.domain.CollectBank;
import com.zhongzheng.modules.collect.domain.CollectCourse;
import com.zhongzheng.modules.collect.domain.CollectNote;
import com.zhongzheng.modules.collect.mapper.CollectBankMapper;
import com.zhongzheng.modules.collect.mapper.CollectCourseMapper;
import com.zhongzheng.modules.collect.mapper.CollectNoteMapper;
import com.zhongzheng.modules.course.domain.MajorCategory;
import com.zhongzheng.modules.user.bo.*;
import com.zhongzheng.modules.user.domain.User;
import com.zhongzheng.modules.user.domain.UserBankRecord;
import com.zhongzheng.modules.user.entity.ClientLoginUser;
import com.zhongzheng.modules.user.mapper.UserMapper;
import com.zhongzheng.modules.user.service.IUserService;
import com.zhongzheng.modules.user.vo.RanKingUser;
import com.zhongzheng.modules.user.vo.UserStudyRecordVo;
import com.zhongzheng.modules.user.vo.UserVo;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;



/**
 * 用户Service业务层处理
 *
 * @author change
 * @date 2021-05-25
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private CollectCourseMapper collectCourseMapper;

    @Autowired
    private CollectBankMapper collectBankMapper;

    @Autowired
    private CollectNoteMapper collectNoteMapper;



    @Autowired
    private IUserService userService;



    @Autowired
    private UserMapper userMapper;


    @Override
    public UserVo queryById(Long userId) {
        User db = this.baseMapper.selectById(userId);
        return BeanUtil.toBean(db, UserVo.class);
    }

    @Override
    public User queryByUnionId(String unionId) {
        User user = getOne(new LambdaQueryWrapper<User>()
                .eq(User::getUnionId, unionId)
                .last("limit 1"));
        if (Validator.isNotNull(user)) {
            return user;
        }
        return null;
    }

    @Override
    public User queryByAccount(String userAccount) {
        User user = getOne(new LambdaQueryWrapper<User>()
                .eq(User::getUserAccount, userAccount)
                .last("limit 1"));
        if (Validator.isNotNull(user)) {
            return user;
        }
        return null;
    }


    @Override
    public List<UserVo> queryList(UserQueryBo bo) {
        LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();
        lqw.eq(StrUtil.isNotBlank(bo.getUserAccout()), User::getUserAccount, bo.getUserAccout());
        lqw.like(StrUtil.isNotBlank(bo.getNickname()), User::getNickname, bo.getNickname());
        lqw.like(StrUtil.isNotBlank(bo.getRealname()), User::getRealname, bo.getRealname());
        lqw.eq(bo.getSex() != null, User::getSex, bo.getSex());
        lqw.eq(StrUtil.isNotBlank(bo.getIdCard()), User::getIdCard, bo.getIdCard());
        lqw.eq(StrUtil.isNotBlank(bo.getTelphone()), User::getTelphone, bo.getTelphone());
        lqw.eq(bo.getUserLevel() != null, User::getUserLevel, bo.getUserLevel());
        lqw.eq(StrUtil.isNotBlank(bo.getUserBirth()), User::getUserBirth, bo.getUserBirth());
        lqw.eq(StrUtil.isNotBlank(bo.getEduLevel()), User::getEduLevel, bo.getEduLevel());
        lqw.eq(bo.getSchoolId() != null, User::getSchoolId, bo.getSchoolId());
        lqw.eq(StrUtil.isNotBlank(bo.getMajor()), User::getMajor, bo.getMajor());
        lqw.eq(bo.getEntranceTime() != null, User::getEntranceTime, bo.getEntranceTime());
        lqw.eq(StrUtil.isNotBlank(bo.getOpenId()), User::getOpenId, bo.getOpenId());
        lqw.eq(StrUtil.isNotBlank(bo.getIdCardImg1()), User::getIdCardImg1, bo.getIdCardImg1());
        lqw.eq(StrUtil.isNotBlank(bo.getIdCardImg2()), User::getIdCardImg2, bo.getIdCardImg2());
        lqw.eq(StrUtil.isNotBlank(bo.getCountry()), User::getCountry, bo.getCountry());
        lqw.eq(StrUtil.isNotBlank(bo.getProvince()), User::getProvince, bo.getProvince());
        lqw.eq(StrUtil.isNotBlank(bo.getCity()), User::getCity, bo.getCity());
        lqw.eq(bo.getIntegral() != null, User::getIntegral, bo.getIntegral());
        lqw.in(bo.getStatus() != null, User::getStatus, bo.getStatus());
        return entity2Vo(this.list(lqw));
    }

    @Override
    public List<UserVo> selectList(UserQueryBo bo) {
        List<User> list = userMapper.selectList(bo);
        return entity2Vo(list);
    }

    @Override
    public List<UserStudyRecordVo> selectStudyRecordList(UserStudyRecordQueryBo bo) {
        return userMapper.selectStudyRecordList(bo);
    }

    private List<UserVo> entity2Vo(List<User> list) {
        List<UserVo> newList = new ArrayList<>();
        for(int i=0;i<list.size();i++){
            UserVo vo = BeanUtil.toBean(list.get(i), UserVo.class);
            vo.setNull(); //清除关键数据
            newList.add(vo);
        }
        return newList;
    }

    /**
     * 实体类转化成视图对象
     *
     * @param collection 实体类集合
     * @return
     */
    private List<UserVo> entity2Vo(Collection<User> collection) {
        List<UserVo> voList = collection.stream()
                .map(any -> BeanUtil.toBean(any, UserVo.class))
                .collect(Collectors.toList());
        if (collection instanceof Page) {
            Page<User> page = (Page<User>) collection;
            Page<UserVo> pageVo = new Page<>();
            BeanUtil.copyProperties(page, pageVo);
            pageVo.addAll(voList);
            voList = pageVo;
        }
        return voList;
    }

    @Override
    public Boolean insertByAddBo(UserAddBo bo) {
        User add = BeanUtil.toBean(bo, User.class);
        validEntityBeforeSave(add);
        add.setCreateTime(DateUtils.getNowTime());
        add.setUpdateTime(DateUtils.getNowTime());
        return this.save(add);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByEditBo(UserEditBo bo) throws IllegalAccessException {
        User update = BeanUtil.toBean(bo, User.class);
        validEntityBeforeSave(update);
        update.setUpdateTime(DateUtils.getNowTime());

        //增加客户端信息进行添加积分


        return this.updateById(update);
    }




    private Boolean increaseUser(UserVo userVo,Long score){
        User user = BeanUtil.toBean(userVo, User.class);
        user.setIntegral(score);
        user.setUpdateTime(DateUtils.getNowTime());
        return userService.updateById(user);
    }

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

    public Integer  countUser(UserEditBo userVo) throws IllegalAccessException {
        // Java的反射
        Field[] field = userVo.getClass().getDeclaredFields();
        int count = 0;
        for(int i=0; i<field.length; i++){
            Field f = field[i];
            f.setAccessible(true);
            if (f.get(userVo) != null){
                count++;
            }
        }
        return count;
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return this.removeByIds(ids);
    }

    @Override
    public Integer getCollectTotal(Long userId) {
        Integer collectCourse = collectCourseMapper.selectCount(new LambdaQueryWrapper<CollectCourse>()
                .eq(CollectCourse::getUserId, userId));
        Integer collectBank = collectBankMapper.selectCount(new LambdaQueryWrapper<CollectBank>()
                .eq(CollectBank::getUserId, userId));
        Integer collectNote = collectNoteMapper.selectCount(new LambdaQueryWrapper<CollectNote>()
                .eq(CollectNote::getUserId, userId));
        return collectCourse + collectBank + collectNote;
    }

    @Override
    public RanKingUser rankingList(RanKingUserQuery query) {
        RanKingUser ranKingUser = new RanKingUser();
        Long time = System.currentTimeMillis(); //当前时间的时间戳
        if (query.getStatus() == 0) {
            long zero1 = time / (1000 * 3600 * 24) * (1000 * 3600 * 24) - TimeZone.getDefault().getRawOffset();
            long zero = zero1 / 1000;
            Calendar calendar = Calendar.getInstance();
            calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
            long tt = calendar.getTime().getTime() / 1000;
            query.setStartTime(zero);
            query.setEndTime(tt);
            ranKingUser = baseMapper.selectByRank(query);
            if (ranKingUser != null && ranKingUser.getHourse() != null) {
                Integer rank = baseMapper.selectByRankOneByTime(Convert.toInt(ranKingUser.getHourse()),zero,tt);
                ranKingUser.setRank(rank);
            } else {
                ranKingUser = baseMapper.selectByOneRank(query);
                ranKingUser.setRank(null);
            }
            List<RanKingUser> ranKingUsers = baseMapper.selectByRanks(query);
            if (ranKingUsers != null && ranKingUsers.size() != 0) {
                for (int i = 0; i < ranKingUsers.size(); i++) {
                    ranKingUsers.get(i).setRank(i+1);
                }
                ranKingUser.setRanKingUsers(ranKingUsers);
            } else {
                ranKingUser.setRanKingUsers(new ArrayList<>());
            }
        } else {
            ranKingUser = baseMapper.selectByRank(query);
            if (ranKingUser != null && ranKingUser.getHourse() != null) {
                Integer rank = baseMapper.selectByRankOne(Convert.toInt(ranKingUser.getHourse()));
                ranKingUser.setRank(rank);
            } else {
                ranKingUser = baseMapper.selectByOneRank(query);
                ranKingUser.setRank(null);
            }
            List<RanKingUser> ranKingUsers = baseMapper.selectByRanks(query);
            if (ranKingUsers != null && ranKingUsers.size() != 0) {
                for (int i = 0; i < ranKingUsers.size(); i++) {
                    ranKingUsers.get(i).setRank(i+1);
                }
                ranKingUser.setRanKingUsers(ranKingUsers);
            } else {
                ranKingUser.setRanKingUsers(new ArrayList<>());
            }
        }
        if (ranKingUser.getHourse() != null){
            ranKingUser.setHourse(getHour(ranKingUser.getHourse()));
        }
        if (!CollectionUtils.isEmpty(ranKingUser.getRanKingUsers())){
            ranKingUser.getRanKingUsers().stream().forEach(c -> {
                if (c.getHourse() ==null) {
                    c.setHourse("0");
                }
                    c.setHourse(getHour(c.getHourse()));

            });
        }
        return ranKingUser;

    }


    //Util.java
    public static String getHour(String date) {
        //秒数
		Integer dt = Integer.parseInt(date) ;
		if (dt < 3600) return Math.round(dt / 60) + "m";
		int hour = Math.round(dt / 3600);
		int minute = Math.round((dt - (hour * 3600)) / 60);
		return hour + "h" + (minute == 0 ? "" : minute + "m");
    }




    @Override
    public Integer getRank(Long userId) {
        RanKingUserQuery query = new RanKingUserQuery();
        query.setUserId(userId);
        Long time = System.currentTimeMillis();
        long zero1 = time / (1000 * 3600 * 24) * (1000 * 3600 * 24) - TimeZone.getDefault().getRawOffset();
        long zero = zero1 / 1000;
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        long tt = calendar.getTime().getTime() / 1000;
        query.setStartTime(zero);
        query.setEndTime(tt);
        RanKingUser ranKingUser = baseMapper.selectByRank(query);
        if (ranKingUser != null && ranKingUser.getHourse() != null) {
            Integer rank = baseMapper.selectByRankOneByTime(Convert.toInt(ranKingUser.getHourse()),zero,tt);
            if (rank == 0) {
                return rank + 1;
            }
            return rank;
         }
        return 0;
    }

    @Override
    public Integer getIssue(Long userId) {

        return 0;
    }

    @Override
    public BigDecimal getMoney(Long userId) {
        User info = getOne(new QueryWrapper<User>()
                .select("money")
                .eq("user_id",userId)
                .last("limit 1"));
        if (Validator.isNotNull(info)) {
            return info.getMoney();
        }
        return null;
    }

    @Override
    public Integer selectUserNum(Integer grade) {
        return baseMapper.selectUserNum(grade);
    }

    @Override
    public Integer getLookNum(Long userId) {
        return baseMapper.selectLookNum(userId);
    }

    /**
     * 获取当前月第一天
     * @param month
     * @return
     */
    public static Long getFirstDayOfMonth(int month) {
        Calendar calendar = Calendar.getInstance();
        // 设置月份
        calendar.set(Calendar.MONTH, month - 1);
        // 获取某月最小天数
        int firstDay = calendar.getActualMinimum(Calendar.DAY_OF_MONTH);
        // 设置日历中月份的最小天数
        calendar.set(Calendar.DAY_OF_MONTH, firstDay);
        //将小时至0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        calendar.set(Calendar.MINUTE, 0);
        //将秒至0
        calendar.set(Calendar.SECOND,0);
        Date time = calendar.getTime();
        return time.getTime() / 1000;
    }

    public static Long getLastDayOfMonth(int month) {
        Calendar calendar = Calendar.getInstance();
        // 设置月份
        calendar.set(Calendar.MONTH, month - 1);
        // 获取某月最大天数
        int lastDay=0;
        //2月的平年瑞年天数
        if(month==2) {
            lastDay = calendar.getLeastMaximum(Calendar.DAY_OF_MONTH);
        }else {
            lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        }
        // 设置日历中月份的最大天数
        calendar.set(Calendar.DAY_OF_MONTH, lastDay);
        //将小时至0
        calendar.set(Calendar.HOUR_OF_DAY, 24);
        //将分钟至0
        calendar.set(Calendar.MINUTE, 0);
        //将秒至0
        calendar.set(Calendar.SECOND,0);
        Date time = calendar.getTime();
        return time.getTime() / 1000;
    }
}
