package com.bizzan.bitrade.dao;

import com.bizzan.bitrade.entity.ContractOrderDirection;
import com.bizzan.bitrade.entity.ExperienceGiftRecord;
import com.bizzan.bitrade.entity.ExperienceGiftRecordStatus;
import org.springframework.data.jpa.repository.JpaRepository;
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 java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Optional;

public interface ExperienceGiftRecordRepository extends JpaRepository<ExperienceGiftRecord, Long> {

    Optional<ExperienceGiftRecord> findByIdAndMemberId(Long id, Long memberId);

    /** 按状态列表查询用户的体验金券，按创建时间倒序 */
    List<ExperienceGiftRecord> findByMemberIdAndStatusInOrderByCreatedAtDesc(
            Long memberId, List<ExperienceGiftRecordStatus> statuses);

    /** 查询可用（待使用且未过期）体验金，用于下拉选择 */
    List<ExperienceGiftRecord> findByMemberIdAndStatusAndExpireAtAfterOrderByCreatedAtDesc(
            Long memberId, ExperienceGiftRecordStatus status, Date now);

    /** 查询可用体验金（按交易对过滤），只返回产品配置支持该交易对的券 */
    @Query("SELECT r FROM ExperienceGiftRecord r " +
           "WHERE r.memberId = :memberId AND r.status = :status AND r.expireAt > :now " +
           "AND EXISTS (SELECT c FROM ExperienceGiftProductCoin c " +
           "            WHERE c.productId = r.productId AND c.coinSymbol = :coinSymbol) " +
           "ORDER BY r.createdAt DESC")
    List<ExperienceGiftRecord> findAvailableByMemberIdAndCoinSymbol(
            @Param("memberId") Long memberId,
            @Param("status") ExperienceGiftRecordStatus status,
            @Param("now") Date now,
            @Param("coinSymbol") String coinSymbol);

    /** 全局查询指定状态的所有体验金券（行情监控使用） */
    List<ExperienceGiftRecord> findByStatus(ExperienceGiftRecordStatus status);

    /** 按状态和交易对查询体验金券（引擎 tick 检查使用） */
    List<ExperienceGiftRecord> findByStatusAndCoinSymbol(ExperienceGiftRecordStatus status, String coinSymbol);


    /** 检查同交易对指定方向是否已有持仓中的体验金 */
    @Query("SELECT COUNT(r) FROM ExperienceGiftRecord r WHERE r.memberId = :memberId " +
           "AND r.coinSymbol = :coinSymbol AND r.status = :status AND r.positionDirection = :direction")
    long countByMemberCoinStatusAndDirection(@Param("memberId") Long memberId,
                                             @Param("coinSymbol") String coinSymbol,
                                             @Param("status") ExperienceGiftRecordStatus status,
                                             @Param("direction") ContractOrderDirection direction);

    /** 统计用户在指定产品下的领取次数 */
    long countByMemberIdAndProductId(Long memberId, Long productId);

    /** 检查同 IP 是否已领取过指定产品（防同 IP 多账户套利） */
    boolean existsByClientIpAndProductId(String clientIp, Long productId);

    /** 更新用户设置的止盈止损价 */
    @Transactional
    @Modifying
    @Query("UPDATE ExperienceGiftRecord r SET r.stopProfitPrice = :stopProfitPrice, " +
           "r.stopLossPrice = :stopLossPrice, r.updatedAt = :now " +
           "WHERE r.id = :id AND r.memberId = :memberId AND r.status = :status")
    int updateStopPrices(@Param("id") Long id,
                         @Param("memberId") Long memberId,
                         @Param("stopProfitPrice") BigDecimal stopProfitPrice,
                         @Param("stopLossPrice") BigDecimal stopLossPrice,
                         @Param("now") Date now,
                         @Param("status") ExperienceGiftRecordStatus status);

    /** 开仓后更新券状态 */
    @Transactional
    @Modifying
    @Query("UPDATE ExperienceGiftRecord r SET r.status = :newStatus, r.positionId = :positionId, " +
           "r.coinSymbol = :coinSymbol, r.positionDirection = :direction, " +
           "r.openFee = :openFee, r.autoClosePrice = :autoClosePrice, " +
           "r.usedAt = :usedAt, r.updatedAt = :now " +
           "WHERE r.id = :id AND r.status = :expectedStatus")
    int activateRecord(@Param("id") Long id,
                       @Param("positionId") Long positionId,
                       @Param("coinSymbol") String coinSymbol,
                       @Param("direction") ContractOrderDirection direction,
                       @Param("openFee") BigDecimal openFee,
                       @Param("autoClosePrice") BigDecimal autoClosePrice,
                       @Param("usedAt") Date usedAt,
                       @Param("now") Date now,
                       @Param("newStatus") ExperienceGiftRecordStatus newStatus,
                       @Param("expectedStatus") ExperienceGiftRecordStatus expectedStatus);
}
