package ru.soune.nocopy.handler; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import ru.soune.nocopy.dto.BaseRequest; import ru.soune.nocopy.dto.BaseResponse; import ru.soune.nocopy.dto.MessageCode; import ru.soune.nocopy.dto.file.ImageSearchRequest; import ru.soune.nocopy.dto.file.YandexSearchResponse; import ru.soune.nocopy.entity.file.FileEntity; import ru.soune.nocopy.exception.NotValidFieldException; import ru.soune.nocopy.repository.FileEntityRepository; import ru.soune.nocopy.service.file.CheckCounterService; import ru.soune.nocopy.service.search.SearchImageService; import ru.soune.nocopy.service.search.GoogleVisionSearchService; import ru.soune.nocopy.service.tariff.TariffConstants; import ru.soune.nocopy.service.tariff.TariffInfoService; import java.io.IOException; import java.util.*; import java.util.concurrent.TimeoutException; @Slf4j @Component @RequiredArgsConstructor public class ImageFoundRequestHandler implements RequestHandler { private final ObjectMapper objectMapper; private final SearchImageService searchImageService; private final GoogleVisionSearchService googleVisionSearchService; private final CheckCounterService checkCounterService; private final FileEntityRepository fileEntityRepository; private final TariffInfoService tariffInfoService; @Override public BaseResponse handle(BaseRequest request) throws Exception { ImageSearchRequest imageSearchRequest = objectMapper.convertValue(request.getMessageBody(), ImageSearchRequest.class); String fileId = imageSearchRequest.getFileId(); FileEntity fileEntity = fileEntityRepository.findById(fileId) .orElseThrow(() -> { throw new NotValidFieldException("File not found", new BaseResponse(20007, MessageCode.FILE_NOT_FOUND.getCode(), MessageCode.FILE_NOT_FOUND.getDescription(), Map.of("fileId",fileId))); }); // YandexSearchResponse response = yandexSearchService.searchByFileEntity(fileEntity); //TODO uncommited when add billing // GoogleVisionSearchResponse googleVisionSearchResponse = googleVisionSearchService.searchByFileEntity(fileId); String searchResponseYandex; String searchResponseGoogle; List allUniqueImages; try { searchResponseYandex = searchImageService.searchReverseByPublicUrl(fileEntity, "yandex_reverse_image", "visual_matches"); log.info("searchResponseYandex OK"); log.info("searchResponseYandex OK"); log.info("searchResponseYandex OK"); log.info("searchResponseYandex OK"); log.info("searchResponseYandex OK"); log.info("searchResponseYandex OK"); log.info("searchResponseYandex OK"); log.info("searchResponseYandex OK"); log.info("searchResponseYandex OK"); List allYandexImages = searchImageService.getAllImagesWithoutPagination( searchResponseYandex, "visual_matches"); searchResponseGoogle = searchImageService.searchReverseByPublicUrl(fileEntity, "google_lens", "exact_matches"); log.info("searchResponseGoogle OK"); log.info("searchResponseGoogle OK"); log.info("searchResponseGoogle OK"); log.info("searchResponseGoogle OK"); log.info("searchResponseGoogle OK"); log.info("searchResponseGoogle OK"); log.info("searchResponseGoogle OK"); List allGoogleImages = searchImageService.getAllImagesWithoutPagination( searchResponseGoogle, "exact_matches"); allUniqueImages = searchImageService.removeDuplicateUrls(allYandexImages, allGoogleImages); log.info("allUniqueImages OK"); log.info("allUniqueImages OK"); log.info("allUniqueImages OK"); log.info("allUniqueImages OK"); log.info("allUniqueImages OK"); log.info("allUniqueImages OK"); } catch (TimeoutException e) { log.warn("Search timeout for file {}, returning empty results", fileId); return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), "Search completed (partial)", Map.of( "results", List.of(), "total", 0, "searchStatus", "timeout" )); } catch (IOException e) { log.error("Search failed for file {}", fileId, e); return new BaseResponse(request.getMsgId(), 20007, "Search service temporarily unavailable", Map.of("fileId", fileId)); } tariffInfoService.writeOffTokens(fileEntity.getUserId(), TariffConstants.TOKEN_VALUE_FOR_SEARCH); checkCounterService.incrementCheckCount(fileEntity.getUserId(), fileEntity.getMimeType()); int page = imageSearchRequest.getPage() != null ? imageSearchRequest.getPage() : 1; int pageSize = 5; List pagedResults = searchImageService.paginateResults(allUniqueImages, page, pageSize * 2); YandexSearchResponse finalResponse = new YandexSearchResponse(); finalResponse.setImages(pagedResults); finalResponse.setPage(page); finalResponse.setPageSize(pageSize * 2); finalResponse.setTotalResults(allUniqueImages.size()); finalResponse.setTotalPages((int) Math.ceil((double) allUniqueImages.size() / (pageSize * 2))); return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), finalResponse); } }