package com.bizzan.bitrade.dao;

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

import com.bizzan.bitrade.constant.CertifiedBusinessStatus;
import com.bizzan.bitrade.dao.base.BaseDao;
import com.bizzan.bitrade.entity.Member;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

public interface MemberDao extends BaseDao<Member> {

    List<Member> getAllByEmailEquals(String email);

    List<Member> getAllByUsernameEquals(String username);

    List<Member> getAllByMobilePhoneEquals(String phone);

    Member findByUsername(String username);

    Member findMemberByTokenAndTokenExpireTimeAfter(String token, Date date);

    Member findMemberByToken(String token);

    Member findMemberByMobilePhoneOrEmail(String phone, String email);

    int countByRegistrationTimeBetween(Date startTime, Date endTime);
    
    int countByInviterId(Long inviterId);

    int countByInviterIdAndSuperPartner(Long inviterId, String superPartner);

    Member findMemberByPromotionCode(String code);

    Member findMemberByEmail(String email);

    Member findMemberByMobilePhone(String mobilePhone);
    
    Member findMemberByIsTrader(int isTrader);
    
    List<Member> findByIsTrader(int isTrader);
    
    List<Member> findByIsService(int isService);

    List<Member> findAllByInviterId(Long id);
    
    @Query(value="select * from member where is_trader>=:level",nativeQuery = true)
    List<Member> findSpecialTraders(@Param("level") int level);

    /*@Query("select new com.bizzan.bitrade.dto.MemberDTO(member,memberWallet) from")*/

    @Query(value = "select m.username from member m where m.id = :id", nativeQuery = true)
    String findUserNameById(@Param("id") Long id);

    @Modifying
    @Query(value = "update Member set signInAbility = true ")
    void resetSignIn();

    @Query(value = "update Member set certified_business_status = :status where id in (:idList) and certified_business_status=2")
    void updateCertifiedBusinessStatusByIdList(@Param("idList")List<Long> idList, @Param("status")CertifiedBusinessStatus status);

    @Query(value ="select count(id) from member where date_format(registration_time,'%Y-%m-%d') = :date",nativeQuery = true)
    int getRegistrationNum(@Param("date")String date);

    @Query(value ="select count(id) from member where date_format(certified_business_check_time,'%Y-%m-%d') = :date",nativeQuery = true)
    int getBussinessNum(@Param("date")String date);

    //以前没有application_time,若以此方法，需手动更新 在添加application_time字段之前的会员的实名通过时间
    /*
        update member a , member_application b
        set a.application_time = b.update_time
        where b.audit_status = 2 and a.application_time is NULL
        and a.id = b.member_id;
     */
    /*@Query(value ="select count(id) from member where date_format(application_time,'%Y-%m-%d') = :date",nativeQuery = true)
    int getApplicationNum(@Param("date")String date);*/

    @Query(value ="select count(a.id) from member a , member_application b where a.id = b.member_id and b.audit_status = 2 and date_format(b.update_time,'%Y-%m-%d') = :date",nativeQuery = true)
    int getApplicationNum(@Param("date")String date);

    @Query("select min(a.registrationTime) as date from Member a")
    Date getStartRegistrationDate();
    
    @Query("select max(a.id) as id from Member a")
    Long getMaxId();

    List<Member> getAllByPromotionCodeEquals(String promotion);

    @Query(value = "select * from member where id in (:ids) and super_partner='1' order by id desc",nativeQuery = true)
    List<Member> findSuperPartnerMembersByIds(@Param("ids") List<Long> ids);

    @Query(value = "select * from member where id in (:ids) order by id desc",nativeQuery = true)
    List<Member> findAllByIds(@Param("ids") List<Long> ids);

    List<Member> findByInviterId(Long userId);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET token=null WHERE token=:token",nativeQuery = true)
    void updateExistingToken(@Param("token")String token);

    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET promotion_code=:promotionCode WHERE id=:id",nativeQuery = true)
    void updatePromotionCode(@Param("id")Long id, @Param("promotionCode")String promotionCode);

    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET inviter_id=:inviterId WHERE id=:id",nativeQuery = true)
    void updateInviterId(@Param("id")Long id, @Param("inviterId")Long inviterId);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET first_level=first_level+1 WHERE id=:id",nativeQuery = true)
    void updateFirstLevel(@Param("id")Long id);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET second_level=second_level+1 WHERE id=:id",nativeQuery = true)
    void updateSecondLevel(@Param("id")Long id);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET super_partner=:superPartner WHERE id=:id",nativeQuery = true)
    void updateSuperPartner(@Param("id")Long id, @Param("superPartner")String superPartner);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET is_lock=:isLock WHERE id=:id",nativeQuery = true)
    void updateIsLock(@Param("id")Long id, @Param("isLock")int isLock);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET google_date=null, google_key=null, google_state=null WHERE id=:id",nativeQuery = true)
    void resetGoogle(@Param("id")Long id);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET token=:token WHERE id=:id",nativeQuery = true)
    void updateToken(@Param("id")Long id, @Param("token")String token);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET avatar=:avatar, real_name=:nickname WHERE id=:id",nativeQuery = true)
    void updateAvatarAndNickname(@Param("id")Long id, @Param("avatar")String avatar, @Param("nickname")String nickname);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET is_trader=:isTrader WHERE id=:id",nativeQuery = true)
    void updateIsTrader(@Param("id")Long id, @Param("isTrader")int isTrader);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET transaction_status=:transactionStatus WHERE id=:id",nativeQuery = true)
    void updateTransactionStatus(@Param("id")Long id, @Param("transactionStatus")int transactionStatus);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET is_money_lock=:isMoneyLock WHERE id=:id",nativeQuery = true)
    void updateIsMoneyLock(@Param("id")Long id, @Param("isMoneyLock")int isMoneyLock);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET disable_reward=:disableReward WHERE id=:id",nativeQuery = true)
    void updateDisableReward(@Param("id")Long id, @Param("disableReward")int disableReward);
    
    @Transactional(rollbackFor = Exception.class)
    @Modifying
    @Query(value = "UPDATE member SET is_service=:isService WHERE id=:id",nativeQuery = true)
    void updateIsService(@Param("id")Long id, @Param("isService")int isService);
    
    @Query("select isTrader from Member where id=:id")
    Integer getIsTrader(@Param("id")Long id);
    
    @Query("select count(*) as total from Member a")
    int countAll();
    
    @Query(value = "select count(*) as total from member a where a.registration_time between :startDate and :endDate", nativeQuery = true)
    int countByDate(@Param("startDate") String startDate, @Param("endDate") String endDate);
    
    @Query(value="select sum(total_balance) as total_balance, count(*) as total_count, sum(total_recharge) as total_recharge, sum(total_withdraw) as total_withdraw, sum(total_award) as total_award, sum(total_fee) as total_fee, sum(total_profit) as total_profit, sum(total_loss) as total_loss from member a where a.id in (:ids)",nativeQuery = true)
    Object[][] sumStatsByIds(@Param("ids") List<Long> ids);
    
    @Query(value = "select count(*) as total from member a where a.registration_time between :startDate and :endDate and a.id in (:ids)", nativeQuery = true)
    int countByDateAndIds(@Param("startDate") String startDate, @Param("endDate") String endDate, @Param("ids") List<Long> ids);
}
