package com.bizzan.bitrade.dao;


import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
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.constant.TransactionType;
import com.bizzan.bitrade.dao.base.BaseDao;
import com.bizzan.bitrade.entity.MemberTransaction;
import com.bizzan.bitrade.vo.MemberTransactionStat;

import java.util.List;
import java.util.Map;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;

public interface MemberTransactionDao extends BaseDao<MemberTransaction> {

    @Query("select m from MemberTransaction as m where m.createTime between :startTime and  :endTime and m.type = :type")
    List<MemberTransaction> findAllDailyMatch(String startTime,String endTime,TransactionType type);

    /*@Query(value="select sum(amount),sum(fee) ,symbol as unit from member_transaction where type = 3 and date_format(create_time,'%Y-%m-%d')= :date group by symbol",nativeQuery = true)
    List<Object[]> getExchangeTurnover(@Param("date") String date);*/

    @Query("select sum(t.amount)  as amount from MemberTransaction t where t.flag = 0 and t.amount > 0 and t.memberId = :memberId and t.symbol = :symbol and t.type in :types")
    Map<String,Object> findMatchTransactionSum(@Param("memberId") Long memberId,@Param("symbol") String symbol,@Param("types") List<TransactionType> types);

    @Query("select sum(t.amount)  as amount from MemberTransaction t where t.flag = 0  and t.memberId = :memberId and t.symbol = :symbol and t.type = :type and t.createTime >= :startTime and t.createTime <= :endTime")
    Map<String,Object> findMatchTransactionSum(@Param("memberId") Long memberId,@Param("symbol") String symbol,@Param("type") TransactionType type,@Param("startTime") Date startTime,@Param("endTime") Date endTime);

    @Query("select sum(t.amount)  as amount from MemberTransaction t where t.flag = 0  and t.symbol = :symbol and t.type = :type and t.createTime >= :startTime and t.createTime <= :endTime")
    Map<String,Object> findMatchTransactionSum(@Param("symbol") String symbol,@Param("type") TransactionType type,@Param("startTime") Date startTime,@Param("endTime") Date endTime);
   
    @Transactional
    @Modifying
    @Query("delete from MemberTransaction as m where m.createTime < :beforeTime and m.type = 3 and m.memberId = 1")
    int deleteHistory(@Param("beforeTime") Date beforeTime);
    
    @Modifying
    @Query(value = "update MemberTransaction set flag = 1 where id = :id ")
    void updateRewardFlag(@Param("id") Long id);
    
    @Query(value="select * from member_transaction m where m.member_id = :memberId and m.type = :type order by id desc limit 1",nativeQuery = true)
    MemberTransaction getLastByMemberIdAndType(@Param("memberId") Long memberId, @Param("type") int type);
    
    @Query(value="select * from member_transaction m where m.member_id = :memberId and m.type = :type order by id limit 1",nativeQuery = true)
    MemberTransaction getFirstByMemberIdAndType(@Param("memberId") Long memberId, @Param("type") int type);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.member_id in (:ids) and  m.create_time between :startTime and  :endTime and m.type = :type",nativeQuery = true)
    BigDecimal getTotalProfitByIds(@Param("ids") List<Long> ids, @Param("startTime") String startTime,@Param("endTime") String endTime,@Param("type") int type);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.member_id in (:ids) and  m.create_time between :startTime and  :endTime and m.type = :type",nativeQuery = true)
    BigDecimal getTotalLossByIds(@Param("ids") List<Long> ids, @Param("startTime") String startTime,@Param("endTime") String endTime,@Param("type") int type);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.member_id not in (801375,801376,801377,801378,801379,801380,801381,801382,801473,801477,801478,801479,801480,801481,801482,801487,801488,801489,801491,801492,801493,800008) and m.create_time between :startTime and  :endTime",nativeQuery = true)
    BigDecimal sumTotal(@Param("startTime") String startTime,@Param("endTime") String endTime);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.member_id not in (801375,801376,801377,801378,801379,801380,801381,801382,801473,801477,801478,801479,801480,801481,801482,801487,801488,801489,801491,801492,801493,800008) and m.create_time between :startTime and  :endTime and m.type = :type",nativeQuery = true)
    BigDecimal sumTotalByType(@Param("startTime") String startTime,@Param("endTime") String endTime,@Param("type") int type);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.member_id = :memberId",nativeQuery = true)
    BigDecimal sumAmountByMemberId(@Param("memberId") long memberId);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.member_id = :memberId and m.type = :type",nativeQuery = true)
    BigDecimal sumAmountByMemberIdAndType(@Param("memberId") long memberId,@Param("type") int type);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.member_id = :memberId and m.type in (:types)",nativeQuery = true)
    BigDecimal sumAmountByMemberIdAndTypes(@Param("memberId") long memberId,@Param("types") List<Integer> types);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.create_time between :startTime and  :endTime and m.member_id = :memberId and m.type = :type",nativeQuery = true)
    BigDecimal sumAmountByMemberIdAndTypeAndTime(@Param("startTime") String startTime,@Param("endTime") String endTime,@Param("memberId") long memberId,@Param("type") int type);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.create_time between :startTime and  :endTime and m.member_id = :memberId and m.type in (:types)",nativeQuery = true)
    BigDecimal sumAmountByMemberIdAndTypesAndTime(@Param("startTime") String startTime,@Param("endTime") String endTime,@Param("memberId") long memberId,@Param("types") List<Integer> types);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.create_time between :startTime and  :endTime and m.member_id = :memberId and m.type not in (:types)",nativeQuery = true)
    BigDecimal sumAmountByMemberIdAndNotTypesAndTime(@Param("startTime") String startTime,@Param("endTime") String endTime,@Param("memberId") long memberId,@Param("types") List<Integer> types);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.create_time between :startTime and  :endTime and m.member_id in (:ids) and m.type = :type",nativeQuery = true)
    BigDecimal sumAmountByMemberIdsAndTypeAndTime(@Param("startTime") String startTime,@Param("endTime") String endTime,@Param("ids") List<Long> ids,@Param("type") int type);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.create_time between :startTime and  :endTime and m.member_id in (:ids) and m.type = :type and m.amount>0",nativeQuery = true)
    BigDecimal sumPositiveAmountByMemberIdsAndTypeAndTime(@Param("startTime") String startTime,@Param("endTime") String endTime,@Param("ids") List<Long> ids,@Param("type") int type);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.create_time between :startTime and  :endTime and m.member_id = :memberId",nativeQuery = true)
    BigDecimal sumAmountByMemberIdAndTime(@Param("startTime") String startTime,@Param("endTime") String endTime,@Param("memberId") long memberId);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.create_time between :startTime and  :endTime and m.member_id in (:ids)",nativeQuery = true)
    BigDecimal sumAmountByMemberIdsAndTime(@Param("startTime") String startTime,@Param("endTime") String endTime,@Param("ids") List<Long> ids);
    
    @Query(value="select sum(m.amount) as allAmount from member_transaction m where m.create_time between :startTime and  :endTime and m.type = :type and m.symbol in (:symbols)",nativeQuery = true)
    BigDecimal sumRechargeAndWithdrawAmountBySymbol(@Param("startTime") String startTime,@Param("endTime") String endTime,@Param("type") int type,@Param("symbols") List<String> symbols);
    
    @Query(value="SELECT member_id FROM `member_transaction` where type in (20,21) and create_time between :startTime and  :endTime group by member_id HAVING sum(amount)*:sign>0",nativeQuery = true)
    List<BigInteger> getMemberIdListByTimeAndSign(@Param("startTime") String startTime,@Param("endTime") String endTime, @Param("sign") int sign);
    
    @Query(value="SELECT new com.bizzan.bitrade.vo.MemberTransactionStat(type, SUM(amount)) FROM MemberTransaction where memberId not in (801375,801376,801377,801378,801379,801380,801381,801382,801473,801477,801478,801479,801480,801481,801482,801487,801488,801489,801491,801492,801493,800008) GROUP by type")
    List<MemberTransactionStat> statByType();
    
    @Query(value="SELECT member_id, type, if(amount>0, 1, 0), sum(amount) FROM `member_transaction` where create_time>=:startTime and create_time<:endTime group by member_id, type, if(amount>0, 1, 0) order by member_id desc",nativeQuery = true)
    Object[][] statByMemberIdAndType(@Param("startTime") String startTime,@Param("endTime") String endTime);
    
    @Query(value="SELECT member_id, sum(amount), sum(if(type=25, amount, 0)) FROM `member_transaction` where create_time>=:startTime and create_time<:endTime group by member_id having sum(if(type=25, amount, 0)) / sum(amount) > 0.8",nativeQuery = true)
    Object[][] statFarmingControl(@Param("startTime") String startTime,@Param("endTime") String endTime);
}
