package com.ruoyi.ss.changeBalance.service.impl;

import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.ss.changeBalance.domain.ChangeBalance;
import com.ruoyi.ss.changeBalance.domain.ChangeBalanceQuery;
import com.ruoyi.ss.changeBalance.domain.enums.BusinessType;
import com.ruoyi.ss.changeBalance.mapper.ChangeBalanceMapper;
import com.ruoyi.ss.changeBalance.service.IChangeBalanceService;
import com.ruoyi.ss.user.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

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

import static com.ruoyi.common.constant.ServiceConstants.FLOW_TYPE_DISBURSE;
import static com.ruoyi.common.constant.ServiceConstants.FLOW_TYPE_INCOME;
import static com.ruoyi.common.utils.SecurityUtils.getUsername;

/**
 * 余额变动Service业务层处理
 *
 * @author qzz
 * @date 2024-09-28
 */
@Service
public class ChangeBalanceServiceImpl implements IChangeBalanceService
{
    @Resource
    private ChangeBalanceMapper rlChangeBalanceMapper;

    @Resource
    private IUserService userService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    /**
     * 查询余额变动
     *
     * @param changeId 余额变动主键
     * @return 余额变动
     */
    @Override
    public ChangeBalance selectRlChangeBalanceByChangeId(Long changeId)
    {
        return rlChangeBalanceMapper.selectRlChangeBalanceByChangeId(changeId);
    }

    /**
     * 查询余额变动列表
     *
     * @param rlChangeBalance 余额变动
     * @return 余额变动
     */
    @Override
    @DataScope(merchantAlias = "u")
    public List<ChangeBalance> selectRlChangeBalanceList(ChangeBalance rlChangeBalance)
    {
        return rlChangeBalanceMapper.selectRlChangeBalanceList(rlChangeBalance);
    }

    /**
     * 根据用户id 查询余额变动列表
     *
     * @param RlUserId 用户id
     * @return 余额变动
     */
    @Override
    public List<ChangeBalance> selectRlChangeBalanceListByUserId(ChangeBalanceQuery query, Long RlUserId)
    {
        query.setOwnerId(RlUserId);
        return rlChangeBalanceMapper.selectRlChangeBalanceList(query);
    }

    /**
     * 新增余额变动
     *
     * @param rlChangeBalance 余额变动
     * @return 结果
     */
    @Override
    public int insertRlChangeBalance(ChangeBalance rlChangeBalance)
    {
        rlChangeBalance.setCreateTime(DateUtils.getNowDate());
        return rlChangeBalanceMapper.insertRlChangeBalance(rlChangeBalance);
    }

    /**
     * 修改余额变动
     *
     * @param rlChangeBalance 余额变动
     * @return 结果
     */
    @Override
    public int updateRlChangeBalance(ChangeBalance rlChangeBalance)
    {
        return rlChangeBalanceMapper.updateRlChangeBalance(rlChangeBalance);
    }

    /**
     * 批量删除余额变动
     *
     * @param changeIds 需要删除的余额变动主键
     * @return 结果
     */
    @Override
    public int deleteRlChangeBalanceByChangeIds(Long[] changeIds)
    {
        return rlChangeBalanceMapper.deleteRlChangeBalanceByChangeIds(changeIds);
    }

    /**
     * 删除余额变动信息
     *
     * @param changeId 余额变动主键
     * @return 结果
     */
    @Override
    public int deleteRlChangeBalanceByChangeId(Long changeId)
    {
        return rlChangeBalanceMapper.deleteRlChangeBalanceByChangeId(changeId);
    }

    /**
     * 根据订单信息生成账变记录
     *
     * @param orderNo 订单号
     * @param outTradeNo 第三方流水号
     * @param type 收支类型：1-收入；2-支出
     * @param busType 业务类型
     * @param payFee 支付金额
     * @param userId 用户id
     * @param userName 用户名称
     * @param phone 用户电话
     * @param userType 用户类型
     * @return 结果
     */
    @Override
    public int generateChangeBalance(String orderNo,String outTradeNo,String type,String busType,BigDecimal payFee,Long userId,String userName,String phone,String userType) {
        // 获取当前余额
        BigDecimal balance = userService.selectUserBalanceById(userId);

        String changeType;
        // 计算变更后的余额
        BigDecimal afterBalance;
        if (type.equals(FLOW_TYPE_INCOME)) {
            afterBalance = balance.add(payFee);
            changeType = "管理员加款：+";
        } else {
            afterBalance = balance.subtract(payFee);
            changeType = "管理员扣款：-";
            // 校验余额是否会变成负数
            if (afterBalance.compareTo(BigDecimal.ZERO) < 0) {
                throw new ServiceException("余额不足");
            }
        }

        ChangeBalance rlChangeBalance = new ChangeBalance();
        rlChangeBalance.setOrderNo(orderNo);
        rlChangeBalance.setOutTradeNo(outTradeNo);
        rlChangeBalance.setType(type);
        rlChangeBalance.setBusType(busType);
        rlChangeBalance.setBeforeBalance(balance);
        rlChangeBalance.setAfterBalance(afterBalance);
        rlChangeBalance.setAmount(payFee);
        rlChangeBalance.setOwnerId(userId);
        rlChangeBalance.setOwnerName(userName);
        rlChangeBalance.setOwnerType(userType);
        rlChangeBalance.setOwnerPhone(phone);
        rlChangeBalance.setCreateTime(DateUtils.getNowDate());

        // 根据 busType 生成不同的 reason 描述
        BigDecimal changeAmount = rlChangeBalance.getAmount();
        String reason = "未知业务类型"; // 默认值
        BusinessType businessType = BusinessType.fromCode(busType);

        if (businessType != null) {
            reason = businessType.getDescription() + orderNo;
            if (businessType == BusinessType.SYSTEM_MODIFY) {
                rlChangeBalance.setCreateBy(getUsername());
                reason = changeType + payFee + "元";
            }
            if (type.equals(FLOW_TYPE_DISBURSE)) {
                changeAmount = changeAmount.negate();
            }
        }
        rlChangeBalance.setReason(reason);
        BigDecimal finalChangeAmount = changeAmount;

        Boolean execute = transactionTemplate.execute(e -> {
            int i = insertRlChangeBalance(rlChangeBalance);
            ServiceUtil.assertion(i == 0, "账变记录插入失败");
            int i2 = userService.changeBalance(finalChangeAmount, userId);
            ServiceUtil.assertion(i2 == 0, "用户余额改变失败");
            return Boolean.TRUE;
        });

        if (Boolean.FALSE.equals(execute)) throw new ServiceException("账变记录插入失败");
        return 1;
    }

    /**
     *  最后账变记录
     */
    @Override
    public ChangeBalance lastChangeBalance(Long userId) {
        return rlChangeBalanceMapper.lastChangeBalance(userId);
    }

    /**
     *  根据条件统计账变金额
     */
    @Override
    public BigDecimal selectFee(ChangeBalanceQuery query) {
        return rlChangeBalanceMapper.selectFee(query);
    }
}
