package com.kexue.skills.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.kexue.skills.entity.Account;
import com.kexue.skills.entity.AccountTransaction;
import com.kexue.skills.entity.dto.AccountDto;
import com.kexue.skills.common.Assert;
import com.kexue.skills.exception.BizException;
import com.kexue.skills.mapper.AccountMapper;
import com.kexue.skills.mapper.AccountTransactionMapper;
import com.kexue.skills.service.AccountService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * (Account)表服务实现类
 *
 * @author 王志维
 * @since 2025-02-21 23:01:48
 */
@Service("accountService")
@Transactional(rollbackFor = Exception.class)
public class AccountServiceImpl implements AccountService {
    @Resource
    private AccountMapper accountMapper;

    @Resource
    private AccountTransactionMapper accountTransactionMapper;

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

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

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

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

    /**
     * 新增数据
     *
     * @param account 实例对象
     * @return 实例对象
     */
    @Override
    public Account insert(Account account) {
        // 设置创建时间和更新时间
        Date now = new Date();
        account.setCreateTime(now);
        account.setUpdateTime(now);
        // 设置默认值
        account.setDeleteFlag(0);
        if (account.getBalance() == null) {
            account.setBalance(BigDecimal.ZERO);
        }
        if (account.getFrozenAmount() == null) {
            account.setFrozenAmount(BigDecimal.ZERO);
        }
        // 保存数据
        this.accountMapper.insert(account);
        return account;
    }

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

    /**
     * 增加账户余额
     *
     * @param userId 用户ID
     * @param amount 增加金额
     * @param transactionNo 交易单号
     * @param businessId 业务ID
     * @param businessType 业务类型
     * @param remark 备注
     * @return 影响行数
     */
    @Override
    public int addBalance(Long userId, BigDecimal amount, String transactionNo, Long businessId, String businessType, String remark) {
        // 1. 查询账户信息
        Account account = this.queryByUserId(userId);
        if (account == null) {
            // 创建账户
            account = new Account();
            account.setUserId(userId);
            account.setBalance(BigDecimal.ZERO);
            account.setFrozenAmount(BigDecimal.ZERO);
            this.insert(account);
        }

        // 2. 保存交易记录
        AccountTransaction transaction = new AccountTransaction();
        transaction.setUserId(userId);
        transaction.setUserName(account.getUserName());
        transaction.setTransactionType(1); // 充值
        transaction.setAmount(amount);
        transaction.setBeforeBalance(account.getBalance());
        transaction.setAfterBalance(account.getBalance().add(amount));
        transaction.setStatus(1); // 成功
        transaction.setTransactionNo(transactionNo);
        transaction.setPayType(3); // 余额支付
        transaction.setBusinessId(businessId);
        transaction.setBusinessType(businessType);
        transaction.setRemark(remark);
        this.accountTransactionMapper.insert(transaction);

        // 3. 更新账户余额
        return this.accountMapper.updateBalance(userId, amount, 1);
    }

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

        // 2. 检查余额是否足够
        Assert.isTrue(account.getBalance().compareTo(amount) >= 0, "账户余额不足");

        // 3. 保存交易记录
        AccountTransaction transaction = new AccountTransaction();
        transaction.setUserId(userId);
        transaction.setUserName(account.getUserName());
        transaction.setTransactionType(3); // 购买内容
        transaction.setAmount(amount);
        transaction.setBeforeBalance(account.getBalance());
        transaction.setAfterBalance(account.getBalance().subtract(amount));
        transaction.setStatus(1); // 成功
        transaction.setTransactionNo(transactionNo);
        transaction.setPayType(3); // 余额支付
        transaction.setBusinessId(businessId);
        transaction.setBusinessType(businessType);
        transaction.setRemark(remark);
        this.accountTransactionMapper.insert(transaction);

        // 4. 更新账户余额
        return this.accountMapper.updateBalance(userId, amount, 2);
    }

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

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