package br.gov.servicos.destaques; import br.gov.servicos.config.ServicosDestaqueConfig; import br.gov.servicos.piwik.PiwikClient; import br.gov.servicos.piwik.PiwikPage; import br.gov.servicos.servico.ServicoRepository; import br.gov.servicos.v3.schema.ServicoXML; import lombok.experimental.FieldDefaults; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toList; import static java.util.stream.Stream.concat; import static java.util.stream.Stream.empty; import static lombok.AccessLevel.PRIVATE; import static org.springframework.data.domain.Sort.Direction.DESC; @Slf4j @Service @FieldDefaults(level = PRIVATE, makeFinal = true) public class ServicosEmDestaque { ServicoRepository servicos; ServicosDestaqueConfig destaques; PiwikClient piwikClient; Boolean destaquesAutomaticos; @Autowired public ServicosEmDestaque( ServicoRepository servicos, ServicosDestaqueConfig destaques, PiwikClient piwikClient, @Value("${flags.destaques.automaticos}") Boolean destaquesAutomaticos ) { this.servicos = servicos; this.destaques = destaques; this.piwikClient = piwikClient; this.destaquesAutomaticos = destaquesAutomaticos; } public List<ServicoXML> servicos(int quantidade) { if (destaquesAutomaticos) { return completaSevicosAteOLimite( concat(servicosMaisAcessados(), buscaDestaquesSeNecessario()), quantidade); } return completaSevicosAteOLimite(buscaDestaquesSeNecessario(), quantidade); } private Stream<ServicoXML> buscaDestaquesSeNecessario() { if (destaques.getServicos().isEmpty()) return empty(); return destaques.getServicos().stream() .map(servicos::findOne) .filter(Objects::nonNull); } private List<ServicoXML> completaSevicosAteOLimite(Stream<ServicoXML> servicosBase, int quantidade) { PageRequest pagina = new PageRequest(0, quantidade, new Sort(DESC, "nome")); Stream<ServicoXML> outrosServicos = servicos.findAll(pagina).getContent() .stream() .filter(s -> !destaques.getServicos().contains(s.getId())); return concat(servicosBase, outrosServicos) .limit(quantidade) .collect(toList()); } private Stream<ServicoXML> servicosMaisAcessados() { log.debug("Piwik: listando serviços mais acessados..."); Stream<ServicoXML> servicos = piwikClient.getPageUrls("week", "yesterday").stream() .sorted(comparing(PiwikPage::getUniqueVisitors)) .map(PiwikPage::getIdServico) .filter(Optional::isPresent) .map(Optional::get) .distinct() .map(this.servicos::findOne) .filter(Objects::nonNull); log.debug("Piwik: serviços mais acessados obtidos"); return servicos; } }