package com.magistr.app.repository;

import com.magistr.app.model.AuthRefreshToken;
import jakarta.persistence.LockModeType;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Lock;
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.time.Instant;
import java.util.Optional;

public interface AuthRefreshTokenRepository extends JpaRepository<AuthRefreshToken, Long> {

    Optional<AuthRefreshToken> findByTokenHash(String tokenHash);

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("""
            SELECT token
            FROM AuthRefreshToken token
            JOIN FETCH token.user
            WHERE token.tokenHash = :tokenHash
            """)
    Optional<AuthRefreshToken> findByTokenHashForUpdate(@Param("tokenHash") String tokenHash);

    /**
     * Удаляет ограниченную пачку старых audit-записей. SKIP LOCKED позволяет нескольким
     * backend-pod безопасно разбирать непересекающиеся пачки одной tenant-БД.
     */
    @Modifying
    @Transactional
    @Query(value = """
            WITH cleanup_candidates AS (
                SELECT id
                FROM auth_refresh_tokens
                WHERE expires_at < :cutoff
                   OR (revoked_at IS NOT NULL AND revoked_at < :cutoff)
                ORDER BY LEAST(expires_at, COALESCE(revoked_at, expires_at)), id
                FOR UPDATE SKIP LOCKED
                LIMIT :batchSize
            )
            DELETE FROM auth_refresh_tokens token
            USING cleanup_candidates candidate
            WHERE token.id = candidate.id
            """, nativeQuery = true)
    int deleteCleanupBatch(@Param("cutoff") Instant cutoff,
                           @Param("batchSize") int batchSize);
}
