package com.bizzan.bitrade.dao;

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

import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

import com.bizzan.bitrade.dao.base.BaseDao;
import com.bizzan.bitrade.entity.FollowWallet;
import com.bizzan.bitrade.entity.UserPurse;

public interface FollowWalletDao extends BaseDao<FollowWallet> {
	
	@Query(value = "select purse.balance+purse.frozen_balance+purse.frozen_margin as allBalance from follow_wallet purse where purse.id = :id",nativeQuery =true)
    BigDecimal getBalanceById(@Param("id") long id);

	@Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.balance = purse.balance + :amount where purse.id = :id")
    int increaseBalance(@Param("id") long id, @Param("amount") BigDecimal amount);
	
	@Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.balance = purse.balance - :amount where purse.id = :id and purse.balance>=:amount")
    int decreaseBalance(@Param("id") long id, @Param("amount") BigDecimal amount);
	
	@Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.profitPercent = :profitPercent, purse.lossPercent = :lossPercent where purse.id = :id")
    int updatePercent(@Param("id") long id, @Param("profitPercent") BigDecimal profitPercent, @Param("lossPercent") BigDecimal lossPercent);

    /**
     * 冻结钱包余额
     *
     * @param walletId
     * @param amount
     * @return
     */
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.balance = purse.balance - :amount,purse.frozenBalance=purse.frozenBalance + :amount where purse.id = :id and purse.balance >= :amount")
    int freezeBalance(@Param("id") long id, @Param("amount") BigDecimal amount);

    /**
     * 解冻钱包余额
     *
     * @param walletId
     * @param amount
     * @return
     */
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.balance = purse.balance + :amount,purse.frozenBalance=purse.frozenBalance - :amount where purse.id = :id and purse.frozenBalance >= :amount")
    int thawBalance(@Param("id") long id, @Param("amount") BigDecimal amount);

    /**
     * 减少冻结余额
     *
     * @param walletId
     * @param amount
     * @return
     */
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.frozenBalance=purse.frozenBalance - :amount where purse.id = :id and purse.frozenBalance >= :amount")
    int decreaseFrozen(@Param("id") long id, @Param("amount") BigDecimal amount);
    
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.balance = purse.balance - :amount,purse.frozenMargin=purse.frozenMargin + :amount where purse.id = :id and purse.balance >= :amount")
    int freezeMargin(@Param("id") long id, @Param("amount") BigDecimal amount);

    /**
     * 批量直接开仓专用：balance -= total（principal+fee），frozen_balance += principal，跳过 frozen_margin 中转。
     */
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.balance = purse.balance - :total, purse.frozenBalance = purse.frozenBalance + :principal where purse.id = :id and purse.balance >= :total")
    int freezeBalanceDirect(@Param("id") long id, @Param("total") BigDecimal total, @Param("principal") BigDecimal principal);
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.balance = purse.balance + :amount,purse.frozenMargin=purse.frozenMargin - :amount where purse.id = :id and purse.frozenMargin >= :amount")
    int thawMargin(@Param("id") long id, @Param("amount") BigDecimal amount);
    @Transactional
    @Modifying
    @Query(value = "update follow_wallet purse set purse.balance = purse.balance+:amount+(if(purse.frozen_balance-:amount<0,purse.frozen_balance-:amount,0)),purse.frozen_balance=purse.frozen_balance-:amount-(if(purse.frozen_balance-:amount<0,purse.frozen_balance-:amount,0)) where purse.id = :id",nativeQuery =true)
    int releaseMargin(@Param("id") long id, @Param("amount") BigDecimal amount);
    
    @Transactional
    @Modifying
    @Query(value = "update follow_wallet purse set purse.balance = purse.balance+purse.frozen_balance+:openFee,purse.frozen_balance=0 where purse.id = :id",nativeQuery =true)
    int cancelTrade(@Param("id") long id, @Param("openFee") BigDecimal openFee);
    
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.frozenBalance=purse.frozenBalance+:margin, purse.frozenMargin=purse.frozenMargin - :margin - :fee where purse.id = :id")
    int clearOpenFee(@Param("id") long id, @Param("margin") BigDecimal margin, @Param("fee") BigDecimal fee);
    
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.balance=purse.balance - :amount where purse.id = :id")
    int clearCloseFee(@Param("id") long id, @Param("amount") BigDecimal amount);
    
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.balance=purse.balance - :amount where purse.id = :id and purse.balance>:amount")
    int clearContractOvernightFee(@Param("id") long id, @Param("amount") BigDecimal amount);
    
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.leverage=:leverage, purse.balance = purse.balance + :marginDifference,purse.frozenBalance=purse.frozenBalance - :marginDifference where purse.id = :id and purse.balance+:marginDifference>=0")
    int modifyLeverage(@Param("id") long id, @Param("leverage") BigDecimal leverage, @Param("marginDifference") BigDecimal marginDifference);
    
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.balance = purse.balance + :marginDifference,purse.frozenBalance=purse.frozenBalance - :marginDifference where purse.id = :id")
    int adjustMargin(@Param("id") long id, @Param("marginDifference") BigDecimal marginDifference);
    
    @Query("from FollowWallet where size(currentPositionList)>0")
    List<FollowWallet> findAllWithPositions();
    
    @Query("from FollowWallet where id in (:ids)")
    List<FollowWallet> findByIds(@Param("ids") List<Long> ids);
    
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.specialBalance = purse.specialBalance + :amount where purse.id = :id")
    int increaseSpecialBalance(@Param("id") long id, @Param("amount") BigDecimal amount);
	
	@Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.specialBalance = purse.specialBalance - :amount where purse.id = :id")
    int decreaseSpecialBalance(@Param("id") long id, @Param("amount") BigDecimal amount);
	
	@Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.specialFrozenBalance=purse.specialFrozenBalance+:margin, purse.specialFrozenMargin=purse.specialFrozenMargin - :margin - :fee where purse.id = :id")
    int clearSpecialOpenFee(@Param("id") long id, @Param("margin") BigDecimal margin, @Param("fee") BigDecimal fee);
    
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.specialBalance=purse.specialBalance - :amount where purse.id = :id")
    int clearSpecialCloseFee(@Param("id") long id, @Param("amount") BigDecimal amount);
    
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.specialBalance = purse.specialBalance - :amount,purse.specialFrozenMargin=purse.specialFrozenMargin + :amount where purse.id = :id and purse.specialBalance >= :amount")
    int freezeSpecialMargin(@Param("id") long id, @Param("amount") BigDecimal amount);
    @Transactional
    @Modifying
    @Query("update FollowWallet purse set purse.specialBalance = purse.specialBalance + :amount,purse.specialFrozenMargin=purse.specialFrozenMargin - :amount where purse.id = :id and purse.specialFrozenMargin >= :amount")
    int thawSpecialMargin(@Param("id") long id, @Param("amount") BigDecimal amount);
    @Transactional
    @Modifying
    @Query(value = "update follow_wallet purse set purse.special_balance = purse.special_balance+:amount+(if(purse.special_frozen_balance-:amount<0,purse.special_frozen_balance-:amount,0)),purse.special_frozen_balance=purse.special_frozen_balance-:amount-(if(purse.special_frozen_balance-:amount<0,purse.special_frozen_balance-:amount,0)) where purse.id = :id",nativeQuery =true)
    int releaseSpecialMargin(@Param("id") long id, @Param("amount") BigDecimal amount);
    
    @Transactional
    @Modifying
    @Query(value = "update FollowWallet purse set purse.specialBalance = purse.specialBalance+:amount,purse.balance = purse.balance-:amount where purse.id = :id and purse.balance>=:amount and purse.specialBalance=0")
    int followSpecial(@Param("id") long id, @Param("amount") BigDecimal amount);
    @Transactional
    @Modifying
    @Query(value = "update FollowWallet purse set purse.balance = purse.balance+purse.specialBalance, purse.specialBalance = 0,purse.specialFrozenBalance = 0 where purse.id = :id and purse.specialFrozenBalance=0")
    int unfollowSpecial(@Param("id") long id);

    /**
     * 退出跟单时将 frozenMargin 全部释放回 balance（用于清理残留冻结保证金）
     */
    @Transactional
    @Modifying
    @Query(value = "update follow_wallet purse set purse.balance = purse.balance + purse.frozen_margin, purse.frozen_margin = 0 where purse.id = :id", nativeQuery = true)
    int releaseAllFrozenMargin(@Param("id") long id);

    @Query(value = "select sum(a.balance+a.frozen_balance+a.frozen_margin) as allBalance from follow_wallet a where a.id<>1",nativeQuery =true)
    BigDecimal sumBalance();
    
    @Query(value = "select sum(a.balance+a.frozen_balance+a.frozen_margin) as allBalance from follow_wallet a where a.id in (:ids)",nativeQuery =true)
    BigDecimal sumBalanceByMemberIds(@Param("ids") List<Long> ids);
    
    @Query(value = "select count(*) as allCount from follow_wallet a where a.id in (:ids) and a.balance+a.frozen_balance+a.frozen_margin>0",nativeQuery =true)
    long countWithBalanceByMemberIds(@Param("ids") List<Long> ids);
}
