package co.yixiang.yshop.module.member.service.user;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.NumberUtil;
import co.yixiang.yshop.framework.common.enums.ShopCommonEnum;
import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.module.member.controller.admin.user.vo.*;
import co.yixiang.yshop.module.member.controller.admin.usertagref.vo.UserTagRefExportReqVO;
import co.yixiang.yshop.module.member.convert.user.UserConvert;
import co.yixiang.yshop.module.member.dal.dataobject.user.MemberUserDO;
import co.yixiang.yshop.module.member.dal.dataobject.userlevelgrowthvalueconfig.UserLevelGrowthValueConfigDO;
import co.yixiang.yshop.module.member.dal.dataobject.usertagref.UserTagRefDO;
import co.yixiang.yshop.module.member.dal.mysql.user.MemberUserMapper;
import co.yixiang.yshop.module.member.enums.BillDetailEnum;
import co.yixiang.yshop.module.member.enums.LevelGrowthValueEnum;
import co.yixiang.yshop.module.member.service.userbill.UserBillService;
import co.yixiang.yshop.module.member.service.userlevelconfig.UserLevelConfigService;
import co.yixiang.yshop.module.member.service.userlevelgrowthvalueconfig.UserLevelGrowthValueConfigService;
import co.yixiang.yshop.module.member.service.usertagref.UserTagRefService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.module.member.enums.ErrorCodeConstants.USER_NOT_EXISTS;

/**
 * 用户 Service 实现类
 *
 * @author yshop
 */
@Service
@Validated
public class UserServiceImpl implements UserService {

    @Resource
    private MemberUserMapper userMapper;
    @Resource
    private UserBillService userBillService;
    @Resource
    private UserTagRefService userTagRefService;
    @Resource
    private UserLevelGrowthValueConfigService growthValueConfigService;
    @Resource
    private UserLevelConfigService levelConfigService;

    @Override
    public Long createUser(UserCreateReqVO createReqVO) {
        // 插入
        MemberUserDO user = UserConvert.INSTANCE.convert(createReqVO);
        userMapper.insert(user);
        // 返回
        return user.getId();
    }

    @Override
    public void updateUser(UserUpdateReqVO updateReqVO) {
        // 校验存在
        validateUserExists(updateReqVO.getId());
        // 更新
        MemberUserDO updateObj = UserConvert.INSTANCE.convert(updateReqVO);
        userMapper.updateById(updateObj);
    }

    /**
     * 更新金额与积分
     *
     * @param updateReqVO 更新信息
     */
    @Override
    public void updateMoney(UserUpdateMoneyReqVO updateReqVO) {
        MemberUserDO memberUserDO = userMapper.selectById(updateReqVO.getId());
        double newMoney;
        String mark;
        if (ShopCommonEnum.ADD_1.getValue().equals(updateReqVO.getPtype())) {
            mark = "系统增加了" + updateReqVO.getMoney() + "余额";
            newMoney = NumberUtil.add(memberUserDO.getNowMoney(), new BigDecimal(updateReqVO.getMoney())).doubleValue();
            userBillService.income(memberUserDO.getId(), "系统增加余额", BillDetailEnum.CATEGORY_1.getValue(),
                    BillDetailEnum.TYPE_6.getValue(), BigDecimal.valueOf(Double.parseDouble(updateReqVO.getMoney())), BigDecimal.valueOf(newMoney), mark, "");
        } else {
            mark = "系统扣除了" + updateReqVO.getMoney() + "余额";
            newMoney = NumberUtil.sub(memberUserDO.getNowMoney(), new BigDecimal(updateReqVO.getMoney())).doubleValue();
            if (newMoney < 0) {
                newMoney = 0d;
            }
            userBillService.expend(memberUserDO.getId(), "系统减少余额",
                    BillDetailEnum.CATEGORY_1.getValue(),
                    BillDetailEnum.TYPE_7.getValue(),
                    Double.parseDouble(updateReqVO.getMoney()), newMoney, mark);
        }
        double newIntegral;
        if (ShopCommonEnum.ADD_1.getValue().equals(updateReqVO.getItype())) {
            mark = "系统增加了" + updateReqVO.getIntegral() + "积分";
            newIntegral = NumberUtil.add(memberUserDO.getIntegral(), new BigDecimal(updateReqVO.getIntegral())).doubleValue();
            userBillService.income(memberUserDO.getId(), "系统增加积分", BillDetailEnum.CATEGORY_1.getValue(),
                    BillDetailEnum.TYPE_6.getValue(), BigDecimal.valueOf(Double.parseDouble(updateReqVO.getIntegral())), BigDecimal.valueOf(newIntegral), mark, "");
        } else {
            mark = "系统扣除了" + updateReqVO.getIntegral() + "积分";
            newIntegral = NumberUtil.sub(memberUserDO.getIntegral(), new BigDecimal(updateReqVO.getIntegral())).doubleValue();
            if (newIntegral < 0) {
                newIntegral = 0d;
            }
            userBillService.expend(memberUserDO.getId(), "系统减少积分",
                    BillDetailEnum.CATEGORY_1.getValue(),
                    BillDetailEnum.TYPE_7.getValue(),
                    Double.parseDouble(updateReqVO.getIntegral()), newIntegral, mark);
        }
        memberUserDO.setIntegral(BigDecimal.valueOf(newIntegral));
        memberUserDO.setNowMoney(BigDecimal.valueOf(newMoney));
        userMapper.updateById(memberUserDO);

    }


    @Override
    public void deleteUser(Long id) {
        // 校验存在
        validateUserExists(id);
        // 删除
        userMapper.deleteById(id);
    }

    private void validateUserExists(Long id) {
        if (userMapper.selectById(id) == null) {
            throw exception(USER_NOT_EXISTS);
        }
    }

    @Override
    public MemberUserDO getUser(Long id) {
        return userMapper.selectById(id);
    }

    @Override
    public List<MemberUserDO> getUserList(Collection<Long> ids) {
        return userMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<UserRespVO> getUserPage(UserPageReqVO pageReqVO) {
        List<Long> userIds = userTagRefService.getUserIdByTagName(pageReqVO);
        pageReqVO.setUserIds(userIds);
        PageResult<MemberUserDO> pageResult = userMapper.selectPage(pageReqVO);
        PageResult<UserRespVO> result = UserConvert.INSTANCE.convertPage(pageResult);
        // 填充标签等数据
        fillData(result);
        return result;

    }

    /**
     * 填充标签等数据
     *
     * @param result 用户列表
     */
    private void fillData(PageResult<UserRespVO> result) {
        List<Long> resUserIds = result.getList().stream().map(UserRespVO::getId).distinct().collect(Collectors.toList());
        //查询关联标签
        List<UserTagRefDO> userTagRefList = userTagRefService.getUserTagRefList(UserTagRefExportReqVO.builder().userIds(resUserIds).build());
        Map<Long, List<UserTagRefDO>> tagMap = userTagRefList.stream().collect(Collectors.groupingBy(UserTagRefDO::getUserId));

        result.getList().forEach(item -> item.setTagList(tagMap.getOrDefault(item.getId(), ListUtil.empty())));
    }


    @Override
    public List<MemberUserDO> getUserList(UserExportReqVO exportReqVO) {
        return userMapper.selectList(exportReqVO);
    }

    @Override
    public void updateTag(UserUpdateTagDTO dto) {
        userTagRefService.deleteByUserId(dto.getId());
        if (CollectionUtil.isNotEmpty(dto.getTagIdList())) {
            List<UserTagRefDO> collect = dto.getTagIdList().stream().map(item -> {
                UserTagRefDO userTagRefDO = new UserTagRefDO();
                userTagRefDO.setUserId(dto.getId());
                userTagRefDO.setTagId(item);
                return userTagRefDO;
            }).collect(Collectors.toList());
            userTagRefService.insertBatch(collect);
        }

    }

    @Override
    public Integer addGrowthValue(Long userId, String type, BigDecimal consumeAmount) {
        //查询对应成长配置
        UserLevelGrowthValueConfigDO growthValueConfig = growthValueConfigService.getByType(type);
        Integer growthValue = 0;
        if (type.equals(LevelGrowthValueEnum.INVITE.getType())) {
            growthValue = growthValueConfig.getGrowthValue();
        } else if (type.equals(LevelGrowthValueEnum.CONSUME.getType())) {
            growthValue = NumberUtil.mul(growthValueConfig.getGrowthValue(), consumeAmount).setScale(0, RoundingMode.DOWN).intValue();
        }
        if (growthValue > 0) {
            userMapper.addGrowthValue(userId, growthValue);
            //升级
            levelConfigService.upgradeLevel(userId);
        }
        return null;
    }

    @Override
    public void updateById(MemberUserDO newUser) {
        userMapper.updateById(newUser);
    }

    @Override
    public void addIntegral(Long userId, BigDecimal integral) {
        userMapper.addIntegral(userId, integral);
    }

    @Override
    public void updateWriteOffAuthority(Long userId, boolean writeOffAuthority) {
        userMapper.updateWriteOffAuthority(userId, writeOffAuthority);
    }

}
