package at.procon.dip.search.service;

import at.procon.dip.domain.document.RepresentationType;
import at.procon.dip.domain.document.repository.DocumentTextRepresentationRepository;
import at.procon.dip.search.dto.SearchEngineType;
import at.procon.dip.search.dto.SearchMetricsResponse;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class SearchMetricsService {

    private final DocumentTextRepresentationRepository representationRepository;

    private final AtomicLong totalSearchRequests = new AtomicLong();
    private final AtomicLong totalDebugRequests = new AtomicLong();
    private final AtomicLong totalCollapsedHitsReturned = new AtomicLong();
    private final Map<SearchEngineType, AtomicLong> engineExecutions = new ConcurrentHashMap<>();

    public void recordSearch(Map<SearchEngineType, ?> engineResults, int collapsedHits, boolean debug) {
        totalSearchRequests.incrementAndGet();
        if (debug) {
            totalDebugRequests.incrementAndGet();
        }
        totalCollapsedHitsReturned.addAndGet(collapsedHits);
        engineResults.keySet().forEach(engine -> engineExecutions
                .computeIfAbsent(engine, key -> new AtomicLong())
                .incrementAndGet());
    }

    public SearchMetricsResponse snapshot() {
        Map<SearchEngineType, Long> engineCounts = new EnumMap<>(SearchEngineType.class);
        engineExecutions.forEach((engine, value) -> engineCounts.put(engine, value.get()));

        Map<RepresentationType, Long> representationCounts = new EnumMap<>(RepresentationType.class);
        Arrays.stream(RepresentationType.values())
                .forEach(type -> representationCounts.put(type, representationRepository.countByRepresentationType(type)));

        return SearchMetricsResponse.builder()
                .totalSearchRequests(totalSearchRequests.get())
                .totalDebugRequests(totalDebugRequests.get())
                .totalCollapsedHitsReturned(totalCollapsedHitsReturned.get())
                .engineExecutions(engineCounts)
                .representationCounts(representationCounts)
                .primaryRepresentationCount(representationRepository.countByPrimaryRepresentationTrue())
                .chunkRepresentationCount(representationRepository.countByRepresentationType(RepresentationType.CHUNK))
                .build();
    }
}
