package org.raddatz.familienarchiv.dashboard;

import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.PostgresContainerConfig;
import org.raddatz.familienarchiv.audit.AuditLogQueryRepository;
import org.raddatz.familienarchiv.audit.ContributorRow;
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.util.List;
import java.util.UUID;

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

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

    static final UUID DOC_ID   = UUID.fromString("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb");
    static final UUID USER_A   = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-000000000001");
    static final UUID USER_B   = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-000000000002");
    static final UUID USER_C   = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-000000000003");
    static final UUID USER_D   = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-000000000004");
    static final UUID USER_E   = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-000000000005");

    @Autowired AuditLogQueryRepository auditLogQueryRepository;

    @Test
    @Sql(statements = {
        "INSERT INTO app_users (id, enabled, email, password, first_name, last_name, color) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-000000000001', true, 'a@test.com', 'pw', 'Anna', 'Meier', '#f00')",
        "INSERT INTO documents (id, title, original_filename, status) VALUES ('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'Test', 'test.pdf', 'PLACEHOLDER')",
        "INSERT INTO audit_log (kind, actor_id, document_id) VALUES ('ANNOTATION_CREATED', 'aaaaaaaa-aaaa-aaaa-aaaa-000000000001', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb')"
    })
    void findRecentContributors_returns_contributor_with_initials_and_color() {
        List<ContributorRow> rows = auditLogQueryRepository.findRecentContributorsForDocuments(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");
    }

    @Test
    @Sql(statements = {
        "INSERT INTO app_users (id, enabled, email, password, first_name, last_name, color) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-000000000001', true, 'a@test.com', 'pw', 'Anna', 'Meier', '#aaa')",
        "INSERT INTO app_users (id, enabled, email, password, first_name, last_name, color) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-000000000002', true, 'b@test.com', 'pw', 'Ben', 'Wolf', '#bbb')",
        "INSERT INTO app_users (id, enabled, email, password, first_name, last_name, color) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-000000000003', true, 'c@test.com', 'pw', 'Clara', 'Zorn', '#ccc')",
        "INSERT INTO app_users (id, enabled, email, password, first_name, last_name, color) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-000000000004', true, 'd@test.com', 'pw', 'Dirk', 'Ott', '#ddd')",
        "INSERT INTO app_users (id, enabled, email, password, first_name, last_name, color) VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-000000000005', true, 'e@test.com', 'pw', 'Eva', 'Kern', '#eee')",
        "INSERT INTO documents (id, title, original_filename, status) VALUES ('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'Test', 'test.pdf', 'PLACEHOLDER')",
        "INSERT INTO audit_log (kind, actor_id, document_id, happened_at) VALUES ('ANNOTATION_CREATED', 'aaaaaaaa-aaaa-aaaa-aaaa-000000000001', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', now() - interval '5 hours')",
        "INSERT INTO audit_log (kind, actor_id, document_id, happened_at) VALUES ('TEXT_SAVED', 'aaaaaaaa-aaaa-aaaa-aaaa-000000000002', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', now() - interval '4 hours')",
        "INSERT INTO audit_log (kind, actor_id, document_id, happened_at) VALUES ('TEXT_SAVED', 'aaaaaaaa-aaaa-aaaa-aaaa-000000000003', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', now() - interval '3 hours')",
        "INSERT INTO audit_log (kind, actor_id, document_id, happened_at) VALUES ('BLOCK_REVIEWED', 'aaaaaaaa-aaaa-aaaa-aaaa-000000000004', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', now() - interval '2 hours')",
        "INSERT INTO audit_log (kind, actor_id, document_id, happened_at) VALUES ('BLOCK_REVIEWED', 'aaaaaaaa-aaaa-aaaa-aaaa-000000000005', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', now() - interval '1 hour')"
    })
    void findRecentContributors_limits_to_4_most_recent() {
        List<ContributorRow> rows = auditLogQueryRepository.findRecentContributorsForDocuments(List.of(DOC_ID));

        assertThat(rows).hasSize(4);
        // Most recent first: E, D, C, B (A is 5th, excluded)
        assertThat(rows.get(0).getActorInitials()).isEqualTo("EK");
        assertThat(rows.get(1).getActorInitials()).isEqualTo("DO");
        assertThat(rows.get(2).getActorInitials()).isEqualTo("CZ");
        assertThat(rows.get(3).getActorInitials()).isEqualTo("BW");
    }

    @Test
    @Sql(statements = {
        "INSERT INTO documents (id, title, original_filename, status) VALUES ('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'Test', 'test.pdf', 'PLACEHOLDER')"
    })
    void findRecentContributors_returns_empty_when_no_audit_entries() {
        List<ContributorRow> rows = auditLogQueryRepository.findRecentContributorsForDocuments(List.of(DOC_ID));

        assertThat(rows).isEmpty();
    }

    @Test
    @Sql(statements = {
        "INSERT INTO documents (id, title, original_filename, status) VALUES ('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'Test', 'test.pdf', 'PLACEHOLDER')",
        // Deleted user: ON DELETE SET NULL makes actor_id NULL — query excludes these rows
        "INSERT INTO audit_log (kind, actor_id, document_id) VALUES ('TEXT_SAVED', NULL, 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb')"
    })
    void findRecentContributors_excludes_entries_from_deleted_users() {
        List<ContributorRow> rows = auditLogQueryRepository.findRecentContributorsForDocuments(List.of(DOC_ID));

        assertThat(rows).isEmpty();
    }
}
