package com.honey.honey.repository;

import com.honey.honey.model.Payment;
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.math.BigDecimal;
import java.time.Instant;
import java.util.Optional;

@Repository
public interface PaymentRepository extends JpaRepository<Payment, Long>, JpaSpecificationExecutor<Payment> {
    org.springframework.data.domain.Page<Payment> findByUserId(Integer userId, org.springframework.data.domain.Pageable pageable);
    Optional<Payment> findByOrderId(String orderId);
    Optional<Payment> findByOrderIdAndStatus(String orderId, Payment.PaymentStatus status);
    
    /**
     * Sums all completed payment stars_amount for a user.
     * @param userId The user ID
     * @return Sum of stars_amount for all COMPLETED payments, or 0 if none
     */
    @Query("SELECT COALESCE(SUM(p.starsAmount), 0) FROM Payment p WHERE p.userId = :userId AND p.status = 'COMPLETED'")
    Integer sumCompletedStarsAmountByUserId(@Param("userId") Integer userId);
    
    /**
     * Sums tickets_amount for all payments with given status.
     */
    @Query("SELECT COALESCE(SUM(p.ticketsAmount), 0) FROM Payment p WHERE p.status = :status")
    Optional<Long> sumTicketsAmountByStatus(@Param("status") Payment.PaymentStatus status);
    
    /**
     * Sums tickets_amount for payments with given status created after the specified date.
     */
    @Query("SELECT COALESCE(SUM(p.ticketsAmount), 0) FROM Payment p WHERE p.status = :status AND p.createdAt >= :after")
    Optional<Long> sumTicketsAmountByStatusAndCreatedAtAfter(
            @Param("status") Payment.PaymentStatus status,
            @Param("after") Instant after
    );
    
    /**
     * Sums stars_amount for all payments with given status.
     */
    @Query("SELECT COALESCE(SUM(p.starsAmount), 0) FROM Payment p WHERE p.status = :status")
    Optional<Integer> sumStarsAmountByStatus(@Param("status") Payment.PaymentStatus status);
    
    /**
     * Sums stars_amount for payments with given status created after the specified date.
     */
    @Query("SELECT COALESCE(SUM(p.starsAmount), 0) FROM Payment p WHERE p.status = :status AND p.createdAt >= :after")
    Optional<Integer> sumStarsAmountByStatusAndCreatedAtAfter(
            @Param("status") Payment.PaymentStatus status,
            @Param("after") Instant after
    );
    
    /**
     * Sums stars_amount for payments with given status created between two dates.
     */
    @Query("SELECT COALESCE(SUM(p.starsAmount), 0) FROM Payment p WHERE p.status = :status AND p.createdAt >= :start AND p.createdAt < :end")
    Optional<Integer> sumStarsAmountByStatusAndCreatedAtBetween(
            @Param("status") Payment.PaymentStatus status,
            @Param("start") Instant start,
            @Param("end") Instant end
    );

    /** Sum usd_amount for completed payments where usd_amount is not null (CRYPTO deposits). */
    @Query("SELECT COALESCE(SUM(p.usdAmount), 0) FROM Payment p WHERE p.status = :status AND p.usdAmount IS NOT NULL")
    Optional<BigDecimal> sumUsdAmountByStatusAndUsdAmountNotNull(@Param("status") Payment.PaymentStatus status);

    /** Sum usd_amount for completed payments (CRYPTO) created after the specified date. */
    @Query("SELECT COALESCE(SUM(p.usdAmount), 0) FROM Payment p WHERE p.status = :status AND p.usdAmount IS NOT NULL AND p.createdAt >= :after")
    Optional<BigDecimal> sumUsdAmountByStatusAndUsdAmountNotNullAndCreatedAtAfter(
            @Param("status") Payment.PaymentStatus status,
            @Param("after") Instant after
    );

    /** Sum usd_amount for a user's completed CRYPTO deposits. */
    @Query("SELECT COALESCE(SUM(p.usdAmount), 0) FROM Payment p WHERE p.userId = :userId AND p.status = 'COMPLETED' AND p.usdAmount IS NOT NULL")
    Optional<BigDecimal> sumUsdAmountByUserIdAndCompletedAndUsdAmountNotNull(@Param("userId") Integer userId);

    /** Sum usd_amount for completed CRYPTO payments created between two dates. */
    @Query("SELECT COALESCE(SUM(p.usdAmount), 0) FROM Payment p WHERE p.status = :status AND p.usdAmount IS NOT NULL AND p.createdAt >= :start AND p.createdAt < :end")
    Optional<BigDecimal> sumUsdAmountByStatusAndUsdAmountNotNullAndCreatedAtBetween(
            @Param("status") Payment.PaymentStatus status,
            @Param("start") Instant start,
            @Param("end") Instant end
    );

    /** Sum usd_amount for all completed payments (null usd rows are ignored by SUM). */
    @Query("SELECT COALESCE(SUM(p.usdAmount), 0) FROM Payment p WHERE p.status = :status")
    Optional<BigDecimal> sumUsdAmountByStatus(@Param("status") Payment.PaymentStatus status);

    /** Count completed FTD crypto (usd) deposits completed in [start, end). */
    @Query("SELECT COUNT(p) FROM Payment p WHERE p.status = :status AND p.ftd = true AND p.usdAmount IS NOT NULL AND p.completedAt >= :start AND p.completedAt < :end")
    long countByStatusAndFtdTrueAndUsdNotNullAndCompletedAtBetween(
            @Param("status") Payment.PaymentStatus status,
            @Param("start") Instant start,
            @Param("end") Instant end
    );
}

