package ru.yandex.webmaster3.storage.searchurl.download;

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

import lombok.RequiredArgsConstructor;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import ru.yandex.webmaster3.core.codes.YandexHttpStatusUtil;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.download.SearchUrlStatusUtil;
import ru.yandex.webmaster3.core.sitestructure.StructureNodeFilter;
import ru.yandex.webmaster3.storage.searchbase.SearchBaseUpdatesService;
import ru.yandex.webmaster3.storage.searchurl.SearchUrlEventFilter;
import ru.yandex.webmaster3.storage.searchurl.SearchUrlSamplesService;
import ru.yandex.webmaster3.storage.searchurl.samples.dao.SearchUrlEventConditions;
import ru.yandex.webmaster3.storage.searchurl.samples.data.SearchUrlEventSample;
import ru.yandex.webmaster3.storage.searchurl.samples.data.UrlStatusInfo;
import ru.yandex.webmaster3.storage.util.StructureFilterService;
import ru.yandex.webmaster3.storage.util.clickhouse2.condition.Condition;

/**
 * Created by ifilippov5 on 13.02.17.
 */
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class DownloadSearchEventService {

    private final SearchBaseUpdatesService searchBaseUpdatesService;
    private final SearchUrlSamplesService searchUrlSamplesService;
    private final StructureFilterService structureFilterService;
    private final SearchUrlEventConditions searchUrlEventConditions;

    public List<EventUrlCsvRow> getSamples(WebmasterHostId hostId, List<SearchUrlEventFilter> parameterFilters, Long nodeId) {
        List<SearchUrlEventSample> samples = getInternalSamples(hostId, parameterFilters, nodeId);

        return samples.stream()
                .map(sample -> new EventUrlCsvRow(
                        sample.getSearchBaseDate().toString(DateTimeFormat.forPattern("dd.MM.yyyy")),
                        sample.getUrl(),
                        Optional.ofNullable(sample.getStatusInfo()).flatMap(s -> Optional.ofNullable(s.getHttpCode())).flatMap(YandexHttpStatusUtil::yandexHttpStatus2View).orElse("0"),
                        Optional.of(sample).map(SearchUrlEventSample::getStatusInfo).map(UrlStatusInfo::getStatus).map(SearchUrlStatusUtil::getStatusView).orElse(""),
                        Optional.of(sample).map(SearchUrlEventSample::getStatusInfo).map(SearchurlReportUtil::getTarget).orElse(""),
                        Optional.of(sample).map(SearchUrlEventSample::getLastAccess).map(date -> date.toString(DateTimeFormat.forPattern("dd.MM.yyyy"))).orElse(""),
                        Optional.ofNullable(sample.getTitle()).orElse(""),
                        Optional.of(sample).map(SearchUrlEventSample::getEventType).map(SearchurlReportUtil::getEventView).orElse(""),
                        Optional.of(sample).map(SearchUrlEventSample::getStatusInfo).map(UrlStatusInfo::isFromSitemap).map(SearchurlReportUtil::toStringYesNo).orElse("")
                ))
                .collect(Collectors.toList());
    }

    private List<SearchUrlEventSample> getInternalSamples(WebmasterHostId hostId, List<SearchUrlEventFilter> parameterFilters, Long nodeId) {
        List<SearchUrlEventSample> samples = Collections.emptyList();
        Condition condition = searchUrlEventConditions.makeCondition(hostId, parameterFilters, false, searchBaseUpdatesService.getSearchBaseUpdates());
        Condition freshCondition = searchUrlEventConditions.makeCondition(hostId, parameterFilters, true, searchBaseUpdatesService.getSearchBaseUpdates());
        if (nodeId != null) {
            StructureNodeFilter nodeFilter = structureFilterService.getNodeFilter(hostId, nodeId);
            if (nodeFilter == null) {
                //Такой ноды нет, так что "отфильтровали всё"
                return samples;
            }
            SearchUrlEventConditions.PathLikeConditionBuilder condBuilder = SearchUrlEventConditions.pathLikeConditionBuilder();
            for (StructureNodeFilter.Part part : nodeFilter.getFilterParts()) {
                if (part instanceof StructureNodeFilter.StringPart) {
                    condBuilder.append(((StructureNodeFilter.StringPart) part).getValue());
                } else {
                    condBuilder.appendWildcard();
                }
            }
            condition = condition.andThen(condBuilder.build());
        }
        long samplesCount = searchUrlSamplesService.getSearchUrlEventSamplesCount(hostId, condition, freshCondition);
        if (samplesCount == 0) {
            return samples;
        }
        samples = searchUrlSamplesService.getSearchUrlEventSamples(hostId, condition, freshCondition, 0, samplesCount);

        return samples;
    }

}
