package com.arms.api.search.service;

import com.arms.api.search.model.dto.SimilaritySearchRequestDTO;
import com.arms.api.search.model.dto.SimilaritySearchResponseDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.vectorstore.filter.FilterExpressionBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class SimilaritySearchServiceImpl implements SimilaritySearchService {

    private final VectorStore vectorStore;  // global-config 에서 미리 설정된 OpenSearch VectorStore 빈 주입

    @Override
    public List<SimilaritySearchResponseDTO> search(String query) {
        log.info("[SimilaritySearch] query: {}", query);
        List<Document> documents = vectorStore.similaritySearch(query);
        return toResponseList(documents);
    }

    @Override
    public List<SimilaritySearchResponseDTO> search(SimilaritySearchRequestDTO request) {
        log.info("[SimilaritySearch] request: {}", request);

        SearchRequest.Builder builder = SearchRequest.builder()
                .query(request.getQuery())
                .topK(request.getTopK())
                .similarityThreshold(request.getSimilarityThreshold());

        // 메타데이터 필터: filterKey + filterValue 둘 다 있을 때만 적용
        if (StringUtils.hasText(request.getFilterKey()) && StringUtils.hasText(request.getFilterValue())) {
            FilterExpressionBuilder fb = new FilterExpressionBuilder();
            builder.filterExpression(fb.eq(request.getFilterKey(), request.getFilterValue()).build());
        }

        List<Document> documents = vectorStore.similaritySearch(builder.build());
        return toResponseList(documents);
    }

    private List<SimilaritySearchResponseDTO> toResponseList(List<Document> documents) {
        return documents.stream()
                .map(doc -> SimilaritySearchResponseDTO.builder()
                        .id(doc.getId())
                        .content(doc.getText())           // M8: getText() 사용
                        .score(doc.getScore() != null ? doc.getScore() : 0.0)
                        .metadata(doc.getMetadata())
                        .build())
                .collect(Collectors.toList());
    }
}
