package cn.newfeifan.mall.module.distri.service.integral;

import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.newfeifan.mall.module.distri.controller.admin.integral.vo.IntegralSaveReqVO;
import cn.newfeifan.mall.module.distri.controller.admin.integralchangelog.vo.IntegralChangeLogSaveReqVO;
import cn.newfeifan.mall.module.distri.controller.admin.ptprofitlog.vo.PtProfitLogSaveReqVO;
import cn.newfeifan.mall.module.distri.dal.dataobject.integral.IntegralDO;
import cn.newfeifan.mall.module.distri.dal.dataobject.orderpercentage.OrderPercentageDO;
import cn.newfeifan.mall.module.distri.dal.mysql.integral.IntegralMapper;
import cn.newfeifan.mall.module.distri.dal.mysql.ptprofit.PtProfitMapper;
import cn.newfeifan.mall.module.distri.enums.CaclEnum;
import cn.newfeifan.mall.module.distri.enums.IntegralEnum;
import cn.newfeifan.mall.module.distri.enums.IntegralTypeEnum;
import cn.newfeifan.mall.module.distri.service.integralchangelog.IntegralChangeLogService;
import cn.newfeifan.mall.module.distri.service.orderpercentage.OrderPercentageService;
import cn.newfeifan.mall.module.distri.service.ptprofitlog.PtProfitLogService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;

import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.newfeifan.mall.module.distri.enums.ErrorCodeConstants.INTEGRAL_NOT_EXISTS;

/**
 * 推荐用户积分 Service 实现类
 *
 * @author 非繁人
 */
@Service
@Validated
public class IntegralServiceImpl implements IntegralService {

    @Resource
    private PtProfitMapper ptProfitMapper;
    @Resource
    private IntegralMapper integralMapper;
    @Resource
    private PtProfitLogService ptProfitLogService;
    @Resource
    private OrderPercentageService orderPercentageService;

    @Resource
    private IntegralChangeLogService integralChangeLogService;

    @Override
    public void updateUserIntegral(Long generateUserId,//导致产生积分变动的用户ID
                                      Long userId, IntegralEnum integralEnum, Long amount,
                                      Long tradeOrderId,
                                      String orderNum,
                                      Integer integralType,
                                      Long highQuota
    ) {

        if (amount == null || amount == 0L) return;

        // 用户钱包
        IntegralDO integralDO = integralMapper.selectOne(new LambdaQueryWrapperX<IntegralDO>().eq(IntegralDO::getUserId, userId));
        Long afterIntegralPoints = 0L;

        // 溢出额度
        Long ancestorQuotaAmount = null;
        Long getHighQuota = 0L;     // 实得直推奖奖

        // 校验用户积分是否足够
        if (integralType.equals(IntegralTypeEnum.RED_INTEGRAL.getType())) {
            getHighQuota = -amount;

            // 修改用户积分
            integralDO.setRedCurrentQuota(integralDO.getRedCurrentQuota() - amount);
            afterIntegralPoints = integralDO.getRedCurrentQuota();

            if (highQuota != null) {
                // 增加峰值
                integralDO.setHighQuota(integralDO.getHighQuota() + highQuota);     //剩余峰值
                integralDO.setHighQuotaTotal(integralDO.getHighQuotaTotal() + highQuota);      //累计峰值
            }
        } else if (integralType.equals(IntegralTypeEnum.GREEN_INTEGRAL.getType())) {
            getHighQuota = -amount;

            // 修改用户积分
            integralDO.setGreenCurrentQuota(integralDO.getGreenCurrentQuota() - amount);
            afterIntegralPoints = integralDO.getGreenCurrentQuota();
        } else if (integralType.equals(IntegralTypeEnum.YELLOW_INTEGRAL.getType())) {
            // 峰值小于获得额度
            if (integralDO.getHighQuota() < amount) {
                ancestorQuotaAmount = amount - integralDO.getHighQuota();
                getHighQuota = integralDO.getHighQuota();
                highQuota = -integralDO.getHighQuota();

                integralDO.setYellowCurrentQuota(integralDO.getYellowCurrentQuota() + integralDO.getHighQuota());
                integralDO.setHighQuota(0L);
            } else {
                getHighQuota = amount;
                highQuota = -amount;
                integralDO.setHighQuota(integralDO.getHighQuota() - amount);
                integralDO.setYellowCurrentQuota(integralDO.getYellowCurrentQuota() + amount);
            }
            afterIntegralPoints = integralDO.getYellowCurrentQuota();
        }

        integralMapper.updateById(integralDO);

        amount = integralType.equals(IntegralTypeEnum.RED_INTEGRAL.getType()) ||
                integralType.equals(IntegralTypeEnum.GREEN_INTEGRAL.getType()) ? -amount : amount;

        // 记录积分变动日志
        IntegralChangeLogSaveReqVO changeLog = IntegralChangeLogSaveReqVO.builder()
                .userId(userId)
                .integralPoints(amount)
                .afterIntegralPoints(afterIntegralPoints)
                .practicalIntegralPoints(getHighQuota)
                .generateUserId(generateUserId)
                .orderId(tradeOrderId)
                .orderNo(orderNum)
                .integralStatus(integralEnum.getType())
                .maxAvailablePointsAmount(highQuota)
                .afterMaxAvailablePointsAmount(integralDO.getHighQuota())
                .ancestorQuotaAmount(ancestorQuotaAmount)
                .integralType(integralType)
                .build();
//        integralChangeLogService.createIntegralChangeLog(changeLog);
    }

    @Override
    public void updateUserIntegral(Long userId, CaclEnum caclEnum, Long payIntegral, Long tradeOrderId, String orderNum) {

    }

    @Override
    public void updateIntegralFreezeHighQuota(Long generateUserId, Long userId, CaclEnum caclEnum, Long totalFreezeHighQuota, Long tradeOrderId, String orderNum) {
        IntegralDO integralDO = integralMapper.selectOne(IntegralDO::getUserId, userId);
//        integralDO.setFreezeHighQuota(integralDO.getFreezeHighQuota() - totalFreezeHighQuota);
        integralDO.setHighQuota(integralDO.getHighQuota() - totalFreezeHighQuota);
        integralDO.setHighQuotaTotal(integralDO.getHighQuotaTotal() - totalFreezeHighQuota);
        integralMapper.updateById(integralDO);

        OrderPercentageDO orderPercentageDO = orderPercentageService.queryStatus();

        //记录用户的积分变动日志
        PtProfitLogSaveReqVO profitLogSaveReqVO = PtProfitLogSaveReqVO.builder()
//                .freezeHighQuota(-totalFreezeHighQuota)
//                .afterFreezeHighQuota(integralDO.getFreezeHighQuota())
                .maxAvailablePointsAmount(-totalFreezeHighQuota)
                .afterMaxAvailablePointsAmount(integralDO.getHighQuota() + Long.parseLong(orderPercentageDO.getBaseMaxQuota()))     // 系统设置的最大可用积分
                .userId(userId)
                .generateUserId(generateUserId)
                .profitStatus(caclEnum.getType())
                .orderId(tradeOrderId)
                .orderNo(orderNum)
                .build();
        ptProfitLogService.createPtProfitLog(profitLogSaveReqVO);
    }

    @Override
    public IntegralDO selectByUser(Long descendant) {
        return integralMapper.selectOne(new LambdaQueryWrapper<IntegralDO>().eq(IntegralDO::getUserId, descendant));
    }

    @Override
    public void updateIntegral(IntegralSaveReqVO updateReqVO) {
        // 校验存在
        validateIntegralExists(updateReqVO.getId());
        // 更新
        IntegralDO updateObj = BeanUtils.toBean(updateReqVO, IntegralDO.class);
        integralMapper.updateById(updateObj);
    }

    @Override
    public void updateUserIntegralByAmountWithHighQuota(Long orderUserId, Long ancesterUserId, CaclEnum caclEnum, Long ancestorIncreaseIntegral, Long tradeOrderId, String tradeOrderNum) {
        IntegralDO integralDO = integralMapper.selectOne(IntegralDO::getUserId, ancesterUserId);
        integralDO.setHighQuota(integralDO.getHighQuota() + ancestorIncreaseIntegral);
        integralMapper.updateById(integralDO);

        OrderPercentageDO orderPercentageDO = orderPercentageService.queryStatus();

        //记录用户的积分变动日志
        PtProfitLogSaveReqVO profitLogSaveReqVO = PtProfitLogSaveReqVO.builder()
                .amount(-ancestorIncreaseIntegral)
                .afterAmount(integralDO.getRedCurrentQuota())
                .maxAvailablePointsAmount(ancestorIncreaseIntegral)
                .afterMaxAvailablePointsAmount(integralDO.getHighQuota() + Long.parseLong(orderPercentageDO.getBaseMaxQuota()))     // 系统设置的最大可用积分
                .userId(ancesterUserId)
                .generateUserId(orderUserId)
                .profitStatus(caclEnum.getType())
                .orderId(tradeOrderId)
                .orderNo(tradeOrderNum)
                .build();
        ptProfitLogService.createPtProfitLog(profitLogSaveReqVO);
    }

    private void validateIntegralExists(Long id) {
        if (integralMapper.selectById(id) == null) {
            throw exception(INTEGRAL_NOT_EXISTS);
        }
    }
}