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.Query;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import com.bizzan.bitrade.constant.BooleanEnum;
import com.bizzan.bitrade.constant.CommonStatus;
import com.bizzan.bitrade.dto.CoinDTO;
import com.bizzan.bitrade.entity.Coin;

import java.util.List;

/**
 * @author 
 * @description 货币操作
 * @date 2019/12/29 14:41
 */
@Repository
public interface CoinDao extends JpaRepository<Coin, String>, JpaSpecificationExecutor<Coin>, QueryDslPredicateExecutor<Coin> {
    Coin findByUnit(String unit);

    List<Coin> findAllByCanWithdrawAndStatusAndHasLegal(BooleanEnum is, CommonStatus status, boolean hasLegal);

    List<Coin> findAllByStatusAndHasLegal(CommonStatus status, boolean hasLegal);

    Coin findCoinByIsPlatformCoin(BooleanEnum is);

    List<Coin> findByHasLegal(Boolean hasLegal);

    @Query("select a from Coin a where a.unit in (:units) ")
    List<Coin> findAllByOtc(@Param("units") List<String> otcUnits);

    @Query("select a.name from Coin a")
    List<String> findAllName();

    @Query(value = "select  new com.bizzan.bitrade.dto.CoinDTO(a.name,a.unit) from Coin a")
    List<CoinDTO> findAllNameAndUnit();

    @Query("select a.name from Coin a where a.hasLegal = true ")
    List<String> findAllCoinNameLegal();

    @Query("select a.unit from Coin a where a.enableRpc = 1")
    List<String> findAllRpcUnit();

    List<Coin> findAllByIsPlatformCoin(BooleanEnum isPlatformCoin);
    
    @Query(value = "select * from coin a where a.can_search=1 order by a.sort",nativeQuery =true)
    List<Coin> findAllByCanSearch();

    /**
     * 按上级币种名称查询子币种列表，按 sort 升序
     *
     * @param parentCoinName 上级币种名称
     * @return 子币种列表
     */
    List<Coin> findAllByParentCoinNameOrderBySortAsc(String parentCoinName);

    /**
     * 查询可充值且无上级的顶级币种（parentCoinName 为 null），按 sort 升序
     *
     * @param canRecharge 充值开关
     * @param status      币种状态
     * @return 顶级可充值币种列表
     */
    @Query("select c from Coin c where c.canRecharge = :canRecharge and c.status = :status and c.parentCoinName is null order by c.sort asc")
    List<Coin> findAllRechargeParentCoins(@Param("canRecharge") BooleanEnum canRecharge,
                                          @Param("status") CommonStatus status);

    /**
     * 查询所有顶级币种名称（parentCoinName 为空），用于"上级币种"下拉选择
     *
     * @return 顶级币种名称列表，按 sort 升序
     */
    @Query("select c.name from Coin c where c.parentCoinName is null or c.parentCoinName = '' order by c.sort asc, c.name asc")
    List<String> findAllTopCoinNames();

    /**
     * 查询所有顶级币种 name + unit（parentCoinName 为空），供下拉选择
     */
    @Query("select new com.bizzan.bitrade.dto.CoinDTO(c.name, c.unit) from Coin c " +
            "where (c.parentCoinName is null or c.parentCoinName = '') " +
            "order by c.sort asc, c.name asc")
    List<CoinDTO> findAllTopCoinNameAndUnit();

    /**
     * 某主网下可配置的子币种：parent_coin_name 不为空且尚未在该主网配置
     */
    @Query("select c.name from Coin c where c.parentCoinName is not null and c.parentCoinName <> '' " +
            "and c.name not in (select cfg.coinName from CoinNetworkConfig cfg where cfg.network.id = :networkId) " +
            "order by c.sort asc, c.name asc")
    List<String> findAvailableCoinNamesForNetwork(@Param("networkId") Long networkId);

    /**
     * 编辑时下拉：包含当前已选币种
     */
    @Query("select c.name from Coin c where c.parentCoinName is not null and c.parentCoinName <> '' " +
            "and (c.name not in (select cfg.coinName from CoinNetworkConfig cfg where cfg.network.id = :networkId) " +
            "or c.name = :includeCoinName) order by c.sort asc, c.name asc")
    List<String> findAvailableCoinNamesForNetworkEdit(@Param("networkId") Long networkId,
                                                      @Param("includeCoinName") String includeCoinName);
}
