package com.bizzan.bitrade.dao;

import com.bizzan.bitrade.constant.BooleanEnum;
import com.bizzan.bitrade.constant.CommonStatus;
import com.bizzan.bitrade.entity.CoinNetwork;
import com.bizzan.bitrade.entity.CoinNetworkConfig;
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.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * 币种主网配置 DAO
 *
 * @author auto
 * @date 2026-05-13
 */
@Repository
public interface CoinNetworkConfigDao extends JpaRepository<CoinNetworkConfig, Long>, JpaSpecificationExecutor<CoinNetworkConfig> {

    /**
     * 按主键查询主网配置
     *
     * @param id 主键
     * @return 配置信息，不存在返回 null
     */
    CoinNetworkConfig findById(Long id);

    /**
     * 查询某币种下所有主网配置，按排序升序
     *
     * @param coinName 币种名称
     * @return 配置列表
     */
    List<CoinNetworkConfig> findAllByCoinNameOrderBySortAsc(String coinName);

    /**
     * 查询某主网下所有币种配置
     *
     * @param networkId 主网ID
     * @return 配置列表
     */
    List<CoinNetworkConfig> findAllByNetworkId(Long networkId);

    /**
     * 查询某币种在某主网下的配置
     *
     * @param coinName  币种名称
     * @param networkId 主网ID
     * @return 配置信息
     */
    CoinNetworkConfig findByCoinNameAndNetworkId(String coinName, Long networkId);

    /**
     * 判断某币种在某主网下是否已有配置
     *
     * @param coinName  币种名称
     * @param networkId 主网ID
     * @return 是否存在
     */
    boolean existsByCoinNameAndNetworkId(String coinName, Long networkId);

    /**
     * 某顶级币种下、在 coin_network_config 中已配置且可充值的主网（去重）
     */
    @Query("select distinct n from CoinNetwork n, CoinNetworkConfig cfg, Coin c "
            + "where cfg.network.id = n.id and cfg.coinName = c.name "
            + "and c.parentCoinName = :parentCoinName "
            + "and c.canRecharge = :canRecharge and c.status = :coinStatus "
            + "and n.status = :networkStatus "
            + "order by n.sort asc, n.id asc")
    List<CoinNetwork> findRechargeNetworksForParent(
            @Param("parentCoinName") String parentCoinName,
            @Param("canRecharge") BooleanEnum canRecharge,
            @Param("coinStatus") CommonStatus coinStatus,
            @Param("networkStatus") CommonStatus networkStatus);

    /**
     * 某顶级币种下、指定主网 id 在 coin_network_config 中的可充值子币种配置
     */
    @Query("select cfg from CoinNetworkConfig cfg join fetch cfg.network n "
            + "where cfg.network.id = :networkId and cfg.coinName in ("
            + "select c.name from Coin c where c.parentCoinName = :parentCoinName "
            + "and c.canRecharge = :canRecharge and c.status = :coinStatus"
            + ") order by cfg.sort asc, cfg.coinName asc")
    List<CoinNetworkConfig> findRechargeConfigsByParentAndNetwork(
            @Param("parentCoinName") String parentCoinName,
            @Param("networkId") Long networkId,
            @Param("canRecharge") BooleanEnum canRecharge,
            @Param("coinStatus") CommonStatus coinStatus);

    /**
     * 提币：coin_network 中至少有一条可提币种配置的主网
     */
    @Query("select distinct n from CoinNetwork n, CoinNetworkConfig cfg, Coin c "
            + "where cfg.network.id = n.id and cfg.coinName = c.name "
            + "and c.canWithdraw = :canWithdraw and c.status = :coinStatus "
            + "and n.status = :networkStatus "
            + "order by n.sort asc, n.id asc")
    List<CoinNetwork> findWithdrawNetworks(
            @Param("canWithdraw") BooleanEnum canWithdraw,
            @Param("coinStatus") CommonStatus coinStatus,
            @Param("networkStatus") CommonStatus networkStatus);

    /**
     * 提币：指定 coin_network.id 下 coin_network_config 中可提币种
     */
    @Query("select cfg from CoinNetworkConfig cfg join fetch cfg.network n "
            + "where cfg.network.id = :networkId and cfg.coinName in ("
            + "select c.name from Coin c where c.canWithdraw = :canWithdraw and c.status = :coinStatus"
            + ") order by cfg.sort asc, cfg.coinName asc")
    List<CoinNetworkConfig> findWithdrawConfigsByNetwork(
            @Param("networkId") Long networkId,
            @Param("canWithdraw") BooleanEnum canWithdraw,
            @Param("coinStatus") CommonStatus coinStatus);
}
