package ru.yandex.webmaster3.storage.checklist.dao;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import ru.yandex.webmaster3.core.checklist.data.SiteProblemStorageType;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.storage.checklist.service.SiteProblemStorageService;

/**
 * ishalaru
 * 26.04.2021
 **/
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class ChecklistPageSamplesService {
    private static final List<SiteProblemStorageType> STORAGE_TYPES = List.of(SiteProblemStorageType.values());
    private final ChecklistPageSamplesYDao checklistPageSamplesYDao;
    private final SiteProblemStorageService siteProblemStorageService;
    private final ValidateSiteProblemService validateSiteProblemService;

    /**
     * Семплы - это относительные урлы
     */
    public void saveSamples(final WebmasterHostId hostId, ChecklistSamplesType type, List<String> samples) {
        if (!validateSiteProblemService.hostInWebmaster(hostId, type.getProblemType())) {
            return;
        }

        var problemHostId = siteProblemStorageService.toProblemHostId(hostId, type.getProblemType());
        if (samples.isEmpty()) {
            checklistPageSamplesYDao.deleteSamples(problemHostId, type);
        } else {
            checklistPageSamplesYDao.insertSamples(problemHostId, type, samples);
        }
    }

    public void saveSamples(final Map<ChecklistSamplesType, Map<WebmasterHostId, List<String>>> sampleMap) {
        for (Map.Entry<ChecklistSamplesType, Map<WebmasterHostId, List<String>>> entry : sampleMap.entrySet()) {
            for (Map.Entry<WebmasterHostId, List<String>> list : entry.getValue().entrySet()) {
                saveSamples(list.getKey(), entry.getKey(), list.getValue());
            }
        }
    }

    public void saveSamples(Map<WebmasterHostId, List<String>> samplesMap, ChecklistSamplesType type) {
        samplesMap = samplesMap.entrySet().stream()
                .filter(e -> validateSiteProblemService.hostInWebmaster(e.getKey(), type.getProblemType()))
                .collect(Collectors.toMap(e -> siteProblemStorageService.toProblemHostId(e.getKey(), type.getProblemType()), Map.Entry::getValue, (a, b) -> b));
        List<WebmasterHostId> removeList = new ArrayList<>();
        List<Pair<WebmasterHostId, List<String>>> insertList = new ArrayList<>();
        for (Map.Entry<WebmasterHostId, List<String>> entry : samplesMap.entrySet()) {
            if (entry.getValue().isEmpty()) {
                removeList.add(entry.getKey());
            } else {
                insertList.add(Pair.of(entry.getKey(), entry.getValue()));
            }
        }
        checklistPageSamplesYDao.deleteSamples(removeList, type);
        checklistPageSamplesYDao.insertSamples(insertList, type);
    }

    public void saveSamplesWithTTL(final WebmasterHostId hostId, ChecklistSamplesType type, List<String> samples) {
        if (!validateSiteProblemService.hostInWebmaster(hostId, type.getProblemType())) {
            return;
        }

        var problemHostId = siteProblemStorageService.toProblemHostId(hostId, type.getProblemType());
        if (samples.isEmpty()) {
            checklistPageSamplesYDao.deleteSamples(problemHostId, type);
        } else {
            checklistPageSamplesYDao.insertSamplesWithTTL(problemHostId, type, samples);
        }
    }

    public List<String> getSamples(WebmasterHostId hostId, ChecklistSamplesType type) {
        var problemHostId = siteProblemStorageService.toProblemHostId(hostId, type.getProblemType());
        return checklistPageSamplesYDao.getSamples(problemHostId, type);
    }

    public Set<ChecklistSamplesType> getExistedSamplesTypes(WebmasterHostId hostId) {
        Map<WebmasterHostId, Set<SiteProblemStorageType>> typeByHost =
                STORAGE_TYPES.stream().collect(Collectors.toMap(type -> siteProblemStorageService.toProblemHostId(hostId, type), Set::of, Sets::union));

        return typeByHost.entrySet().stream()
                .flatMap(entry -> checklistPageSamplesYDao.getExistedSamplesTypes(entry.getKey()).stream()
                        .filter(problemHostId -> entry.getValue().contains(problemHostId.getProblemType().getStorageType())))
                .collect(Collectors.toSet());
    }
}
