package at.procon.dip.search.integration;

import at.procon.dip.domain.document.DocumentFamily;
import at.procon.dip.domain.document.DocumentType;
import at.procon.dip.domain.document.RepresentationType;
import at.procon.dip.search.api.SearchExecutionContext;
import at.procon.dip.search.dto.SearchHit;
import at.procon.dip.search.dto.SearchMode;
import at.procon.dip.search.dto.SearchRequest;
import at.procon.dip.search.dto.SearchRepresentationSelectionMode;
import at.procon.dip.search.repository.DocumentFullTextSearchRepository;
import at.procon.dip.search.repository.DocumentTrigramSearchRepository;
import at.procon.dip.search.spi.SearchDocumentScope;
import at.procon.dip.testsupport.AbstractSearchIntegrationTest;
import at.procon.dip.testsupport.SearchTestDataFactory;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

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

class GenericSearchRepositoryIntegrationTest extends AbstractSearchIntegrationTest {

    @Autowired
    private SearchTestDataFactory dataFactory;

    @Autowired
    private DocumentFullTextSearchRepository fullTextRepository;

    @Autowired
    private DocumentTrigramSearchRepository trigramRepository;

    @Test
    void fullTextRepository_should_find_exact_keyword_in_primary_representation() {
        dataFactory.createDocumentWithPrimaryRepresentation(
                "Vienna school renovation framework",
                "School roof framework agreement",
                "Framework agreement for school roof renovation in Vienna.",
                DocumentType.TED_NOTICE,
                DocumentFamily.PROCUREMENT,
                "en",
                RepresentationType.SEMANTIC_TEXT);

        dataFactory.createDocumentWithPrimaryRepresentation(
                "Pump maintenance manual",
                "Maintenance procedures",
                "Calibration procedure for pumps and gauges.",
                DocumentType.PDF,
                DocumentFamily.KNOWLEDGE,
                "en",
                RepresentationType.FULLTEXT);

        assertThat(jdbcTemplate.queryForObject(
                "select count(*) from doc.doc_text_representation",
                Integer.class
        )).isGreaterThan(0);

        assertThat(jdbcTemplate.queryForObject(
                "select count(*) from doc.doc_text_representation where search_vector is not null",
                Integer.class
        )).isGreaterThan(0);

        SearchExecutionContext context = SearchExecutionContext.builder()
                .request(SearchRequest.builder()
                        .queryText("framework agreement")
                        .modes(Set.of(SearchMode.FULLTEXT))
                        .representationSelectionMode(SearchRepresentationSelectionMode.PRIMARY_ONLY)
                        .build())
                .scope(new SearchDocumentScope(Set.of(), null, null, null, null, null))
                .page(0)
                .size(10)
                .build();

        List<SearchHit> hits = fullTextRepository.search(context, 10);
        assertThat(hits).isNotEmpty();
        assertThat(hits).extracting(SearchHit::getTitle)
                .contains("Vienna school renovation framework")
                .doesNotContain("Pump maintenance manual");
    }

    @Test
    void trigramRepository_should_match_fuzzy_title() {
        dataFactory.createDocumentWithPrimaryRepresentation(
                "Vienna school renovation framework",
                "School roof framework agreement",
                "Framework agreement for school roof renovation in Vienna.",
                DocumentType.TED_NOTICE,
                DocumentFamily.PROCUREMENT,
                "en",
                RepresentationType.SEMANTIC_TEXT);

        SearchExecutionContext context = SearchExecutionContext.builder()
                .request(SearchRequest.builder()
                        .queryText("Viena school renovtion")
                        .modes(Set.of(SearchMode.TRIGRAM))
                        .representationSelectionMode(SearchRepresentationSelectionMode.PRIMARY_ONLY)
                        .build())
                .scope(new SearchDocumentScope(Set.of(), null, null, null, null, null))
                .page(0)
                .size(10)
                .build();

        List<SearchHit> hits = trigramRepository.search(context, 10, 0.10d);
        assertThat(hits).isNotEmpty();
        assertThat(hits.getFirst().getTitle()).isEqualTo("Vienna school renovation framework");
    }
}
