package com.ruoyi.cai.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.cai.domain.*;
import com.ruoyi.cai.dto.AddRechargeOrderAdminDto;
import com.ruoyi.cai.dto.AddRechargeOrderDto;
import com.ruoyi.cai.dto.admin.vo.RechargeOrderAdminVo;
import com.ruoyi.cai.enums.AccountBusinessEnum;
import com.ruoyi.cai.enums.AccountChangeEnum;
import com.ruoyi.cai.enums.ConsumeLogType;
import com.ruoyi.cai.manager.IdManager;
import com.ruoyi.cai.mapper.AccountMapper;
import com.ruoyi.cai.mapper.RechargeOrderMapper;
import com.ruoyi.cai.pay.OrderNoUtil;
import com.ruoyi.cai.pay.PayStatusEnum;
import com.ruoyi.cai.pay.PlatformTypeEnum;
import com.ruoyi.cai.pay.RechargeTypeEnum;
import com.ruoyi.cai.service.*;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.ServletUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 充值订单Service业务层处理
 *
 * @author 77
 * @date 2024-01-03
 */
@Service
@Slf4j
public class RechargeOrderServiceImpl extends ServiceImpl<RechargeOrderMapper,RechargeOrder> implements RechargeOrderService {


    @Autowired
    private GoodsService goodsService;
    @Autowired
    private UserService userService;
    @Autowired
    private AccountService accountService;
    @Resource
    private AccountMapper accountMapper;
    @Autowired
    private AccountChangeLogService accountChangeLogService;

    @Override
    public RechargeOrder getByOrderNo(String orderNo){
        return this.getOne(Wrappers.lambdaQuery(RechargeOrder.class).eq(RechargeOrder::getOrderNo,orderNo)
                .last("limit 1"));
    }

    @Override
    public Page<RechargeOrderAdminVo> pageAdmin(PageQuery pageQuery, RechargeOrderAdminVo bo) {
        return baseMapper.pageAdmin(pageQuery.build(),bo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RechargeOrder addRechargeOrder(AddRechargeOrderDto addRechargeOrderDto){
        Long goodId = addRechargeOrderDto.getGoodId();
        Goods goods = goodsService.getById(goodId);
        if(goods == null){
            throw new ServiceException("充值价格错误");
        }
        RechargeOrder order = new RechargeOrder();
        order.setUserId(addRechargeOrderDto.getUserId());
        order.setRechargeId(goods.getId());
        order.setRechargeName(goods.getName());
        order.setRechargeCoin(goods.getAmount());
        order.setRechargeType(RechargeTypeEnum.COIN.getCode());
        order.setPrice(goods.getPrice());
        order.setOrderNo(OrderNoUtil.createOrderNo(OrderNoUtil.RECHARGE_ORDER_SUB));
        order.setPayStatus(PayStatusEnum.READY_PAY.getCode());
        order.setAdmin(false);
        this.save(order);
        return order;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderSuccess(String orderNo){
        RechargeOrder rechargeOrder = this.getByOrderNo(orderNo);
        if(rechargeOrder == null){
            throw new ServiceException("订单不存在");
        }
        if(!PayStatusEnum.READY_PAY.getCode().equals(rechargeOrder.getPayStatus())){
            log.error("订单支付状态错误!vipOrder={}", JSON.toJSONString(rechargeOrder));
            throw new ServiceException("订单支付状态错误!");
        }
        Long traceId = IdManager.nextId();
        boolean update = this.update(Wrappers.lambdaUpdate(RechargeOrder.class)
                .eq(RechargeOrder::getOrderNo, rechargeOrder.getOrderNo())
                .eq(RechargeOrder::getPayStatus, PayStatusEnum.READY_PAY.getCode())
                .set(RechargeOrder::getPayStatus, PayStatusEnum.PAY.getCode())
                .set(RechargeOrder::getTraceId,traceId));
        if(!update){
            log.error("订单支付状态错误!vipOrder={}", JSON.toJSONString(rechargeOrder));
            throw new ServiceException("订单支付状态错误!");
        }
        User user = userService.getById(rechargeOrder.getUserId());
        ConsumeLog consumeLog = new ConsumeLog();
        consumeLog.init(user,null);
        consumeLog.setTraceId(traceId);
        consumeLog.setType(ConsumeLogType.RECHARGE.getCode());
        consumeLog.setAmount(rechargeOrder.getRechargeCoin());
        accountService.recharge(consumeLog);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RechargeOrder updateAdminRechargeOrder(AddRechargeOrderAdminDto dto){
        User user = userService.getByUserCode(dto.getUsercode());
        if(user == null){
            throw new ServiceException("用户不存在");
        }
        RechargeTypeEnum rechargeTypeEnum = RechargeTypeEnum.getByCode(dto.getRechargeType());
        if(rechargeTypeEnum == null){
            throw new ServiceException("参数错误");
        }
        Long userId = user.getId();
        Long traceId = IdManager.nextId();
        RechargeOrder order = new RechargeOrder();
        order.setUserId(userId);
        order.setRechargeName(rechargeTypeEnum.getName());
        order.setRechargeCoin(dto.getRechargeCoin());
        order.setPrice(BigDecimal.ZERO);
        order.setRechargeType(dto.getRechargeType());
        order.setOrderNo(OrderNoUtil.createOrderNo(OrderNoUtil.RECHARGE_ORDER_SUB));
        order.setPlatformType(PlatformTypeEnum.ADMIN.name());
        order.setPayStatus(PayStatusEnum.NO_PAY.getCode());
        order.setOperateIp(ServletUtils.getClientIP());
        order.setAdmin(true);
        order.setAdminId(LoginHelper.getUserId());
        order.setRemark(dto.getRemark());
        order.setTraceId(traceId);
        this.save(order);
        Account account = accountService.getByUserId(userId);
        if(rechargeTypeEnum == RechargeTypeEnum.COIN){ // 余额调整
            if(dto.getRechargeCoin() > 0){
                accountMapper.incsCoin(userId,dto.getRechargeCoin());
                accountChangeLogService.saveLogAdmin(user.getId(),user.getUsercode(),RechargeTypeEnum.COIN, AccountChangeEnum.SYSTEM_COIN_INCS,dto.getRechargeCoin(),traceId);
            }else{
                if(account.getCoin() < -dto.getRechargeCoin()){
                    throw new ServiceException("调整后余额为负数，无法调整");
                }
                boolean l = accountMapper.decrCoin(userId, -dto.getRechargeCoin());
                if(!l){
                    throw new ServiceException("调整后收益为负数，无法调整");
                }
                accountChangeLogService.saveLogAdmin(user.getId(),user.getUsercode(),RechargeTypeEnum.COIN, AccountChangeEnum.SYSTEM_COIN_DECR,dto.getRechargeCoin(),traceId);
            }
        }else{
            if(dto.getRechargeCoin() > 0){
                accountMapper.incsIncomeCoin(userId,dto.getRechargeCoin());
                accountChangeLogService.saveLogAdmin(user.getId(),user.getUsercode(),RechargeTypeEnum.COIN_INCOME, AccountChangeEnum.SYSTEM_INCOME_COIN_INCS,dto.getRechargeCoin(),traceId);
            }else{
                if(account.getIncomeCoin() < -dto.getRechargeCoin()){
                    throw new ServiceException("调整后收益为负数，无法调整");
                }
                boolean l = accountMapper.decrIncomeCoin(userId, -dto.getRechargeCoin());
                if(!l){
                    throw new ServiceException("调整后收益为负数，无法调整");
                }
                accountChangeLogService.saveLogAdmin(user.getId(),user.getUsercode(),RechargeTypeEnum.COIN_INCOME, AccountChangeEnum.SYSTEM_INCOME_COIN_DECR,dto.getRechargeCoin(),traceId);
            }
        }
        return order;
    }


}
