package com.spot.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.spot.entity.Account;

import java.math.BigDecimal;
import java.util.List;

/**
 * 账户服务接口
 *
 * @author jean
 * @date 2026-05-06
 */
public interface AccountService extends IService<Account> {

    /**
     * 根据用户ID和币种查询账户
     *
     * @param uid    用户ID
     * @param symbol 币种符号
     * @return 账户对象，不存在返回null
     */
    Account getByUidAndSymbol(Long uid, String symbol);

    /**
     * 撤单退币：从冻结余额扣除，增加到可用余额（原子操作）
     *
     * @param accountId    账户ID
     * @param refundAmount 退还金额
     * @return 更新行数，0表示冻结余额不足
     */
    int refundFromFrozenToAvailable(Long accountId, BigDecimal refundAmount);

    /**
     * 扣除冻结余额
     *
     * @param accountId    账户ID
     * @param frozenAmount 扣除金额
     * @return 更新行数，0表示冻结余额不足
     */
    int deductFrozenBalance(Long accountId, BigDecimal frozenAmount);

    /**
     * 增加可用余额
     *
     * @param accountId       账户ID
     * @param availableAmount 增加金额
     * @return 更新行数
     */
    int addAvailableBalance(Long accountId, BigDecimal availableAmount);

    /**
     * 增加冻结余额
     *
     * @param accountId    账户ID
     * @param frozenAmount 增加金额
     * @return 更新行数
     */
    int addFrozenBalance(Long accountId, BigDecimal frozenAmount);

    /**
     * 冻结金额：从可用余额扣除，增加到冻结余额（原子操作）
     *
     * @param accountId    账户ID
     * @param freezeAmount 冻结金额
     * @return 更新行数，0表示可用余额不足
     */
    int freezeFromAvailableToFrozen(Long accountId, BigDecimal freezeAmount);

    /**
     * 扣除可用余额
     *
     * @param accountId       账户ID
     * @param availableAmount 扣除金额
     * @return 更新行数，0表示可用余额不足
     */
    int deductAvailableBalance(Long accountId, BigDecimal availableAmount);

    /**
     * 获取或初始化现货账户
     * 账户不存在时执行 INSERT IGNORE 创建零余额账户，再返回账户对象。
     * 使用 INSERT IGNORE 保证并发安全，不会因重复创建产生异常。
     *
     * @param uid    用户ID
     * @param symbol 币种符号
     * @return 现货账户对象，不会返回 null
     */
    Account getOrCreateAccount(Long uid, String symbol);

    /**
     * 查询有冻结余额但无对应活跃委托的孤悬账户
     * 用于定时任务批量扫描并释放异常滞留的冻结余额
     *
     * @param batchSize 每批次最大返回数量
     * @return 孤悬冻结账户列表
     */
    List<Account> findFrozenAccountsWithoutOrders(int batchSize);

    /**
     * 释放孤悬冻结余额：将账户全部 cold_money 移回 hot_money，并写入解冻流水
     * 操作在同一事务内完成，任意步骤失败均触发回滚。
     *
     * @param account 待解冻的账户（cold_money 必须 > 0）
     */
    void releaseOrphanFrozenBalance(Account account);
}
