package org.raddatz.familienarchiv.audit;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.PostgresContainerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.transaction.support.TransactionTemplate;
import software.amazon.awssdk.services.s3.S3Client;

import static java.util.concurrent.TimeUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ActiveProfiles("test")
@Import(PostgresContainerConfig.class)
class AuditServiceIntegrationTest {

    @MockitoBean S3Client s3Client;
    @Autowired AuditService auditService;
    @Autowired AuditLogRepository auditLogRepository;
    @Autowired TransactionTemplate transactionTemplate;

    @BeforeEach
    void resetAuditLog() {
        auditLogRepository.deleteAll();
    }

    @Test
    void logAfterCommit_writes_ANNOTATION_CREATED_row_after_transaction_commits() {
        transactionTemplate.execute(status -> {
            auditService.logAfterCommit(AuditKind.ANNOTATION_CREATED, null, null, null);
            return null;
        });

        await().atMost(5, SECONDS).until(() -> auditLogRepository.count() > 0);
        assertThat(auditLogRepository.findAll())
                .extracting(AuditLog::getKind)
                .containsExactly(AuditKind.ANNOTATION_CREATED);
    }

    @Test
    void logAfterCommit_writes_no_row_when_transaction_rolls_back() {
        try {
            transactionTemplate.execute(status -> {
                auditService.logAfterCommit(AuditKind.ANNOTATION_CREATED, null, null, null);
                throw new RuntimeException("force rollback");
            });
        } catch (RuntimeException ignored) {}

        assertThat(auditLogRepository.count()).isZero();
    }
}
