package org.raddatz.familienarchiv.dashboard;

import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.audit.ActivityFeedRow;
import org.raddatz.familienarchiv.audit.AuditLogQueryRepository;
import org.raddatz.familienarchiv.audit.ContributorRow;
import org.raddatz.familienarchiv.audit.PulseStatsRow;
import org.raddatz.familienarchiv.PostgresContainerConfig;
import org.raddatz.familienarchiv.config.FlywayConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
import org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureTestDatabase;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.jdbc.Sql;

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

import static org.assertj.core.api.Assertions.assertThat;

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import({PostgresContainerConfig.class, FlywayConfig.class})
class AuditLogQueryRepositoryIntegrationTest {

    static final UUID USER_ID = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
    static final UUID DOC_ID  = UUID.fromString("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb");

    @Autowired AuditLogQueryRepository auditLogQueryRepository;

    @Test
    @Sql(statements = {
        "INSERT INTO app_users (id, enabled, email, password) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', true, 'testuser@test.com', 'pw')",
        "INSERT INTO documents (id, title, original_filename, status) VALUES ('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'Test Doc', 'test.pdf', 'PLACEHOLDER')",
        "INSERT INTO audit_log (kind, actor_id, document_id) VALUES ('ANNOTATION_CREATED', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb')"
    })
    void findMostRecentDocumentIdByActor_returns_document_with_annotation_only_events() {
        Optional<UUID> result = auditLogQueryRepository.findMostRecentDocumentIdByActor(USER_ID);

        assertThat(result).contains(DOC_ID);
    }

    @Test
    @Sql(statements = {
        "INSERT INTO app_users (id, enabled, email, password) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', true, 'testuser@test.com', 'pw')",
        "INSERT INTO documents (id, title, original_filename, status) VALUES ('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'Test Doc', 'test.pdf', 'PLACEHOLDER')",
        "INSERT INTO audit_log (kind, actor_id, document_id, payload) VALUES ('ANNOTATION_CREATED', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '{\"pageNumber\":1}')"
    })
    void findRolledUpActivityFeed_returnsAnnotationEntry() {
        List<ActivityFeedRow> rows = auditLogQueryRepository.findRolledUpActivityFeed(USER_ID.toString(), 10,
                List.of("TEXT_SAVED","FILE_UPLOADED","ANNOTATION_CREATED","BLOCK_REVIEWED","COMMENT_ADDED","MENTION_CREATED"));

        assertThat(rows).hasSize(1);
        assertThat(rows.get(0).getKind()).isEqualTo("ANNOTATION_CREATED");
        assertThat(rows.get(0).getDocumentId()).isEqualTo(DOC_ID);
        assertThat(rows.get(0).getHappenedAt()).isNotNull();
        assertThat(rows.get(0).getCount()).isEqualTo(1);
        assertThat(rows.get(0).getHappenedAtUntil()).isNull();
    }

    @Test
    @Sql(statements = {
        "INSERT INTO app_users (id, enabled, email, password) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', true, 'testuser@test.com', 'pw')",
        "INSERT INTO documents (id, title, original_filename, status) VALUES ('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'Test Doc', 'test.pdf', 'PLACEHOLDER')",
        "INSERT INTO audit_log (kind, actor_id, document_id, payload) VALUES ('ANNOTATION_CREATED', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '{\"pageNumber\":1}')",
        "INSERT INTO audit_log (kind, actor_id, document_id, payload) VALUES ('TEXT_SAVED', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '{\"blockId\":\"ccc\",\"pageNumber\":1}')",
        "INSERT INTO audit_log (kind, document_id) VALUES ('FILE_UPLOADED', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb')"
    })
    void getPulseStats_countsAnnotationsTranscriptionsAndUploads() {
        OffsetDateTime weekStart = OffsetDateTime.now(ZoneOffset.UTC).minusDays(7);

        PulseStatsRow stats = auditLogQueryRepository.getPulseStats(weekStart, USER_ID.toString());

        assertThat(stats.getAnnotated()).isEqualTo(1);
        assertThat(stats.getTranscribed()).isEqualTo(1);
        assertThat(stats.getUploaded()).isEqualTo(1);
        assertThat(stats.getYourPages()).isGreaterThanOrEqualTo(1);
    }

    @Test
    @Sql(statements = {
        "INSERT INTO app_users (id, enabled, email, password, first_name, last_name, color) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', true, 'testuser@test.com', 'pw', 'Anna', 'Meier', '#f00')",
        "INSERT INTO documents (id, title, original_filename, status) VALUES ('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'Test Doc', 'test.pdf', 'PLACEHOLDER')",
        "INSERT INTO audit_log (kind, actor_id, document_id) VALUES ('ANNOTATION_CREATED', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb')"
    })
    void findContributorsPerDocument_returnsContributorWithInitialsAndColor() {
        List<ContributorRow> rows = auditLogQueryRepository.findContributorsPerDocument(List.of(DOC_ID));

        assertThat(rows).hasSize(1);
        assertThat(rows.get(0).getDocumentId()).isEqualTo(DOC_ID);
        assertThat(rows.get(0).getActorInitials()).isEqualTo("AM");
        assertThat(rows.get(0).getActorColor()).isEqualTo("#f00");
    }
}
