package org.raddatz.familienarchiv.document;

import io.swagger.v3.oas.annotations.media.Schema;
import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.audit.ActivityActorDTO;
import org.raddatz.familienarchiv.document.Document;
import org.raddatz.familienarchiv.document.DocumentStatus;
import org.springframework.data.domain.PageRequest;

import java.util.List;
import java.util.UUID;

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

class DocumentSearchResultTest {

    private DocumentSearchItem item(UUID docId) {
        Document doc = Document.builder()
                .id(docId)
                .title("Test")
                .originalFilename("test.pdf")
                .status(DocumentStatus.UPLOADED)
                .build();
        return new DocumentSearchItem(doc, SearchMatchData.empty(), 0, List.of());
    }

    @Test
    void of_totalElements_equals_list_size_for_unpaged_shortcut() {
        DocumentSearchResult result = DocumentSearchResult.of(
                List.of(item(UUID.randomUUID()), item(UUID.randomUUID())));

        assertThat(result.totalElements()).isEqualTo(2L);
        assertThat(result.pageNumber()).isZero();
        assertThat(result.pageSize()).isEqualTo(2);
        assertThat(result.totalPages()).isEqualTo(1);
    }

    @Test
    void of_empty_shortcut_has_zero_totalPages() {
        DocumentSearchResult result = DocumentSearchResult.of(List.of());

        assertThat(result.totalElements()).isZero();
        assertThat(result.totalPages()).isZero();
    }

    @Test
    void paged_factory_populates_paging_fields_from_pageable_and_total() {
        List<DocumentSearchItem> slice = List.of(item(UUID.randomUUID()), item(UUID.randomUUID()));

        DocumentSearchResult result = DocumentSearchResult.paged(slice, PageRequest.of(1, 50), 120L);

        assertThat(result.items()).hasSize(2);
        assertThat(result.totalElements()).isEqualTo(120L);
        assertThat(result.pageNumber()).isEqualTo(1);
        assertThat(result.pageSize()).isEqualTo(50);
        assertThat(result.totalPages()).isEqualTo(3); // ceil(120 / 50)
    }

    @Test
    void paged_factory_totalPages_rounds_up_on_remainder() {
        DocumentSearchResult result =
                DocumentSearchResult.paged(List.of(), PageRequest.of(0, 7), 30L);

        assertThat(result.totalPages()).isEqualTo(5); // ceil(30 / 7)
    }

    @Test
    void of_exposes_items_with_completion_and_contributors() {
        UUID id = UUID.randomUUID();
        ActivityActorDTO actor = new ActivityActorDTO("AB", "#f00", "Anna Braun");
        Document doc = Document.builder().id(id).title("T").originalFilename("t.pdf")
                .status(DocumentStatus.UPLOADED).build();
        DocumentSearchItem item = new DocumentSearchItem(doc, SearchMatchData.empty(), 75, List.of(actor));

        DocumentSearchResult result = DocumentSearchResult.of(List.of(item));

        assertThat(result.items()).hasSize(1);
        assertThat(result.items().get(0).completionPercentage()).isEqualTo(75);
        assertThat(result.items().get(0).contributors()).containsExactly(actor);
    }

    @Test
    void items_component_is_annotated_as_required_in_openapi_schema() throws NoSuchFieldException {
        Schema schema = DocumentSearchResult.class.getDeclaredField("items").getAnnotation(Schema.class);
        assertThat(schema).isNotNull();
        assertThat(schema.requiredMode()).isEqualTo(Schema.RequiredMode.REQUIRED);
    }

    @Test
    void totalElements_component_is_annotated_as_required_in_openapi_schema() throws NoSuchFieldException {
        Schema schema = DocumentSearchResult.class.getDeclaredField("totalElements").getAnnotation(Schema.class);
        assertThat(schema).isNotNull();
        assertThat(schema.requiredMode()).isEqualTo(Schema.RequiredMode.REQUIRED);
    }

    @Test
    void paging_components_are_annotated_as_required_in_openapi_schema() throws NoSuchFieldException {
        for (String name : List.of("pageNumber", "pageSize", "totalPages")) {
            Schema schema = DocumentSearchResult.class.getDeclaredField(name).getAnnotation(Schema.class);
            assertThat(schema).as(name + " must have @Schema").isNotNull();
            assertThat(schema.requiredMode()).isEqualTo(Schema.RequiredMode.REQUIRED);
        }
    }
}
