package cloud.nstart.terravault.ordinis.domain.audit;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.time.OffsetDateTime;
import java.util.List;
import java.util.UUID;

public interface AuditLogRepository extends JpaRepository<AuditLog, Long> {

  List<AuditLog> findByDictionaryIdOrderByEventTimeDesc(UUID dictionaryId);

  /**
   * Audit entries для конкретного dict, отфильтрованные по event_type IN
   * списке. Используется ChangelogService — берёт только DEFINITION_*
   * events, skip RECORD_* шум.
   */
  @Query("""
      SELECT a FROM AuditLog a
      WHERE a.dictionaryId = :dictionaryId
        AND a.eventType IN :eventTypes
      ORDER BY a.eventTime DESC
      """)
  List<AuditLog> findByDictionaryIdAndEventTypes(
      @Param("dictionaryId") UUID dictionaryId,
      @Param("eventTypes") List<String> eventTypes,
      Pageable pageable);

  List<AuditLog> findByRecordIdOrderByEventTimeDesc(UUID recordId);

  List<AuditLog> findByUserIdOrderByEventTimeDesc(String userId);

  List<AuditLog> findByEventTimeBetweenOrderByEventTimeDesc(OffsetDateTime from, OffsetDateTime to);

  /**
   * Гибкий запрос для admin UI: фильтры nullable, NULL = «не фильтруем».
   * Сортировка задаётся {@link Pageable}.
   *
   * <p>Для {@code from}/{@code to} (OffsetDateTime) NULL не передаём — PostgreSQL не
   * может вывести тип параметра из {@code IS NULL} проверки. Вместо этого
   * controller подставляет {@link OffsetDateTime#MIN} / {@link OffsetDateTime#MAX}.
   */
  @Query("""
      SELECT a FROM AuditLog a
      WHERE (:dictionaryName IS NULL OR a.dictionaryName = :dictionaryName)
        AND (:userId IS NULL OR a.userId = :userId)
        AND (:action IS NULL OR a.action = :action)
        AND (:businessKey IS NULL OR a.businessKey = :businessKey)
        AND a.eventTime >= :from
        AND a.eventTime <= :to
      """)
  Page<AuditLog> search(
      @Param("dictionaryName") String dictionaryName,
      @Param("userId") String userId,
      @Param("action") String action,
      @Param("businessKey") String businessKey,
      @Param("from") OffsetDateTime from,
      @Param("to") OffsetDateTime to,
      Pageable pageable);
}
