package com.hfkj.service.user.impl;

import com.hfkj.common.exception.BaseException;
import com.hfkj.common.exception.ErrorCode;
import com.hfkj.common.exception.ErrorHelp;
import com.hfkj.common.exception.SysCode;
import com.hfkj.entity.BsUser;
import com.hfkj.entity.BsUserIntegralRecord;
import com.hfkj.service.user.BsUserIntegralRecordService;
import com.hfkj.service.user.BsUserService;
import com.hfkj.service.user.UserIntegralService;
import com.hfkj.sysenum.UserIntegralRecordStatusEnum;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Map;

/**
 * @className: UserIntegralServiceImpl
 * @author: HuRui
 * @date: 2024/5/20
 **/
@Service("userIntegralService")
public class UserIntegralServiceImpl implements UserIntegralService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private BsUserService userService;
    @Resource
    private BsUserIntegralRecordService userIntegralRecordService;
    @Override
    public Long getIntegral(Long userId) {
        BsUser user = userService.getUser(userId);
        if (user != null) {
            return user.getIntegral();
        }
        return 0L;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void entry(Long userId, Long integralNum, Map<String,Object> opUser, Map<String,Object> source) {
        String key = "USER_INTEGRAL_" + userId;
        // 获取锁
        Boolean lock = redisTemplate.opsForValue().setIfAbsent(key, integralNum);
        if (Boolean.FALSE.equals(lock)) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            entry(userId,integralNum, opUser, source);
        }

        try {
            // 获取锁成功
            // 查询用户
            BsUser user = userService.getUser(userId);
            if (user == null) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的账户");
            }
            // 变更前积分数
            Long beforeAmount = user.getIntegral();

            // 计算金额
            user.setIntegral(user.getIntegral() + integralNum);
            userService.editData(user);

            // 变更后积分数
            Long afterAmount = user.getIntegral();

            BsUserIntegralRecord record = new BsUserIntegralRecord();
            record.setUserId(userId);
            record.setType(UserIntegralRecordStatusEnum.type1.getCode());
            record.setTransactionAmount(integralNum);
            record.setBeforeAmount(beforeAmount);
            record.setAfterAmount(afterAmount);
            record.setSourceType(MapUtils.getInteger(source, "sourceType"));
            record.setSourceId(MapUtils.getLong(source, "sourceId"));
            record.setSourceOrderNo(MapUtils.getString(source, "sourceOrderNo"));
            record.setSourceContent(MapUtils.getString(source, "sourceContent"));
            record.setOpUserType(MapUtils.getInteger(source, "opUserType"));
            record.setOpUserId(MapUtils.getLong(source, "opUserId"));
            record.setOpUserName(MapUtils.getString(source, "opUserName"));
            record.setOpUserPhone(MapUtils.getString(source, "opUserPhone"));
            userIntegralRecordService.create(record);

        } catch (Exception e) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "积分交易异常");
        } finally {
            redisTemplate.delete(key);
        }
    }

    @Override
    public void consume(Long userId, Long integralNum, Map<String,Object> opUser, Map<String,Object> source) {
        String key = "USER_INTEGRAL_" + userId;
        // 获取锁
        Boolean lock = redisTemplate.opsForValue().setIfAbsent(key, integralNum);
        if (Boolean.FALSE.equals(lock)) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            entry(userId,integralNum, opUser, source);
        }

        try {
            // 获取锁成功
            // 查询用户
            BsUser user = userService.getUser(userId);
            if (user == null) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的账户");
            }
            if (user.getIntegral() < integralNum) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "积分数量不足");
            }
            // 变更前积分数
            Long beforeAmount = user.getIntegral();

            // 计算金额
            user.setIntegral(user.getIntegral() - integralNum);
            userService.editData(user);

            // 变更后积分数
            Long afterAmount = user.getIntegral();

            BsUserIntegralRecord record = new BsUserIntegralRecord();
            record.setUserId(userId);
            record.setType(UserIntegralRecordStatusEnum.type2.getCode());
            record.setTransactionAmount(integralNum);
            record.setBeforeAmount(beforeAmount);
            record.setAfterAmount(afterAmount);
            record.setSourceType(MapUtils.getInteger(source, "sourceType"));
            record.setSourceId(MapUtils.getLong(source, "sourceId"));
            record.setSourceOrderNo(MapUtils.getString(source, "sourceOrderNo"));
            record.setSourceContent(MapUtils.getString(source, "sourceContent"));
            record.setOpUserType(MapUtils.getInteger(source, "opUserType"));
            record.setOpUserId(MapUtils.getLong(source, "opUserId"));
            record.setOpUserName(MapUtils.getString(source, "opUserName"));
            record.setOpUserPhone(MapUtils.getString(source, "opUserPhone"));
            userIntegralRecordService.create(record);

        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "积分交易异常");
        } finally {
            redisTemplate.delete(key);
        }
    }

}
