package com.kexue.skills.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.kexue.skills.entity.PointsAccount;
import com.kexue.skills.entity.PointsTransaction;
import com.kexue.skills.entity.dto.PointsAccountDto;
import com.kexue.skills.common.Assert;
import com.kexue.skills.exception.BizException;
import com.kexue.skills.mapper.PointsAccountMapper;
import com.kexue.skills.mapper.PointsTransactionMapper;
import com.kexue.skills.service.PointsAccountService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * (PointsAccount)表服务实现类
 *
 * @author 王志维
 * @since 2025-02-21 23:01:48
 */
@Service("pointsAccountService")
@Transactional(rollbackFor = Exception.class)
public class PointsAccountServiceImpl implements PointsAccountService {
    @Resource
    private PointsAccountMapper pointsAccountMapper;

    @Resource
    private PointsTransactionMapper pointsTransactionMapper;

    /**
     * 分页查询
     *
     * @param queryDto 筛选条件
     * @return 查询结果
     */
    @Override
    public PageInfo<PointsAccount> getPageList(PointsAccountDto queryDto) {
        PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());
        List<PointsAccount> list = this.pointsAccountMapper.getPageList(queryDto);
        return new PageInfo<>(list);
    }

    /**
     * 查询列表
     *
     * @param queryDto 筛选条件
     * @return 查询结果
     */
    @Override
    public List<PointsAccount> getList(PointsAccountDto queryDto) {
        return this.pointsAccountMapper.getList(queryDto);
    }

    /**
     * 通过主键查询单条数据
     *
     * @param accountId 主键
     * @return 实例对象
     */
    @Override
    public PointsAccount queryById(Long accountId) {
        return this.pointsAccountMapper.queryById(accountId);
    }

    /**
     * 通过用户ID查询积分账户
     *
     * @param userId 用户ID
     * @return 实例对象
     */
    @Override
    public PointsAccount queryByUserId(Long userId) {
        return this.pointsAccountMapper.queryByUserId(userId);
    }

    /**
     * 新增数据
     *
     * @param pointsAccount 实例对象
     * @return 实例对象
     */
    @Override
    public PointsAccount insert(PointsAccount pointsAccount) {
        // 设置创建时间和更新时间
        Date now = new Date();
        pointsAccount.setCreateTime(now);
        pointsAccount.setUpdateTime(now);
        // 设置默认值
        pointsAccount.setDeleteFlag(0);
        if (pointsAccount.getTotalPoints() == null) {
            pointsAccount.setTotalPoints(0);
        }
        if (pointsAccount.getAvailablePoints() == null) {
            pointsAccount.setAvailablePoints(0);
        }
        if (pointsAccount.getFrozenPoints() == null) {
            pointsAccount.setFrozenPoints(0);
        }
        // 保存数据
        this.pointsAccountMapper.insert(pointsAccount);
        return pointsAccount;
    }

    /**
     * 更新数据
     *
     * @param pointsAccount 实例对象
     * @return 实例对象
     */
    @Override
    public PointsAccount update(PointsAccount pointsAccount) {
        // 设置更新时间
        pointsAccount.setUpdateTime(new Date());
        // 更新数据
        this.pointsAccountMapper.update(pointsAccount);
        return this.queryById(pointsAccount.getAccountId());
    }

    /**
     * 增加积分
     *
     * @param userId 用户ID
     * @param points 增加积分
     * @param transactionNo 交易单号
     * @param businessId 业务ID
     * @param businessType 业务类型
     * @param remark 备注
     * @return 影响行数
     */
    @Override
    public int addPoints(Long userId, Integer points, String transactionNo, Long businessId, String businessType, String remark) {
        // 1. 查询积分账户信息
        PointsAccount account = this.queryByUserId(userId);
        if (account == null) {
            // 创建积分账户
            account = new PointsAccount();
            account.setUserId(userId);
            account.setTotalPoints(0);
            account.setAvailablePoints(0);
            account.setFrozenPoints(0);
            this.insert(account);
        }

        // 2. 保存积分交易记录
        PointsTransaction transaction = new PointsTransaction();
        transaction.setUserId(userId);
        transaction.setUserName(account.getUserName());
        transaction.setTransactionType(1); // 1.获得积分
        transaction.setPoints(points);
        transaction.setBeforePoints(account.getAvailablePoints());
        transaction.setAfterPoints(account.getAvailablePoints() + points);
        transaction.setStatus(1); // 成功
        transaction.setTransactionNo(transactionNo);
        transaction.setBusinessId(businessId);
        transaction.setBusinessType(businessType);
        transaction.setRemark(remark);
        this.pointsTransactionMapper.insert(transaction);

        // 3. 更新积分账户
        return this.pointsAccountMapper.updatePoints(userId, points, 1);
    }

    /**
     * 减少积分
     *
     * @param userId 用户ID
     * @param points 减少积分
     * @param transactionNo 交易单号
     * @param businessId 业务ID
     * @param businessType 业务类型
     * @param remark 备注
     * @return 影响行数
     */
    @Override
    public int reducePoints(Long userId, Integer points, String transactionNo, Long businessId, String businessType, String remark) {
        // 1. 查询积分账户信息
        PointsAccount account = this.queryByUserId(userId);
        Assert.notNull(account, "积分账户不存在");

        // 2. 检查积分是否足够
        Assert.isTrue(account.getAvailablePoints() >= points, "积分不足");

        // 3. 保存积分交易记录
        PointsTransaction transaction = new PointsTransaction();
        transaction.setUserId(userId);
        transaction.setUserName(account.getUserName());
        transaction.setTransactionType(2); // 2.使用积分
        transaction.setPoints(points);
        transaction.setBeforePoints(account.getAvailablePoints());
        transaction.setAfterPoints(account.getAvailablePoints() - points);
        transaction.setStatus(1); // 成功
        transaction.setTransactionNo(transactionNo);
        transaction.setBusinessId(businessId);
        transaction.setBusinessType(businessType);
        transaction.setRemark(remark);
        this.pointsTransactionMapper.insert(transaction);

        // 4. 更新积分账户
        return this.pointsAccountMapper.updatePoints(userId, points, 2);
    }

    /**
     * 通过主键逻辑删除
     *
     * @param accountId 主键
     * @param updateBy 更新人
     * @return 影响行数
     */
    @Override
    public int logicDeleteById(Long accountId, String updateBy) {
        return this.pointsAccountMapper.logicDeleteById(accountId, updateBy);
    }

    /**
     * 通过主键物理删除
     *
     * @param accountId 主键
     * @return 影响行数
     */
    @Override
    public int deleteById(Long accountId) {
        return this.pointsAccountMapper.deleteById(accountId);
    }
}