package ru.yandex.webmaster3.storage.antispam.threats;

import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.webmaster3.core.checklist.data.SiteProblemContent;
import ru.yandex.webmaster3.core.checklist.data.SiteProblemState;
import ru.yandex.webmaster3.core.checklist.data.SiteProblemTypeEnum;
import ru.yandex.webmaster3.core.data.WebmasterHostGeneration;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.storage.antispam.threats.dao.OwnerThreatsCHDao;
import ru.yandex.webmaster3.storage.checklist.data.AbstractProblemInfo;
import ru.yandex.webmaster3.storage.checklist.data.RealTimeSiteProblemInfo;
import ru.yandex.webmaster3.storage.checklist.service.SiteProblemsProvider;

/**
 * Created by Oleg Bazdyrev on 26/12/2019.
 */
@Component("threatsProblemsProvider")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class ThreatsProblemsProvider implements SiteProblemsProvider {
    private static final Set<SiteProblemTypeEnum> SUPPORTED_PROBLEM_TYPES =
            Collections.unmodifiableSet(EnumSet.of(SiteProblemTypeEnum.THREATS));

    private final OwnerThreatsCHDao mdbOwnerThreatsCHDao;

    @NotNull
    @Override
    public List<AbstractProblemInfo> listProblems(@NotNull WebmasterHostId hostId, UUID generationId) {
        OwnerThreatsCHDao.HostThreats hostThreats = mdbOwnerThreatsCHDao.getHostWithThreats(hostId);
        return getAbstractProblemInfos(hostId, hostThreats);
    }


    @Override
    public Map<WebmasterHostId, List<? extends AbstractProblemInfo>> listProblems(List<WebmasterHostGeneration> hosts) {
        List<WebmasterHostId> hostIds = hosts.stream()
                .map(WebmasterHostGeneration::getHostId)
                .collect(Collectors.toList());
        return mdbOwnerThreatsCHDao.getHostWithThreats(hostIds)
                .entrySet().stream().map(entry -> Maps.immutableEntry(entry.getKey(),
                        getAbstractProblemInfos(entry.getKey(), entry.getValue())))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    @NotNull
    private List<AbstractProblemInfo> getAbstractProblemInfos(@NotNull WebmasterHostId hostId,
                                                              OwnerThreatsCHDao.HostThreats hostThreats) {
        if (hostThreats.getThreats().isEmpty()) {
            return Collections.singletonList(new RealTimeSiteProblemInfo(hostId, null, null, null,
                    SiteProblemState.ABSENT,
                    SiteProblemTypeEnum.THREATS, null, 0));
        }
        DateTime actualSince = hostThreats.getActualSince();
        RealTimeSiteProblemInfo problemInfo = new RealTimeSiteProblemInfo(hostId, actualSince, actualSince,
                actualSince, SiteProblemState.PRESENT,
                SiteProblemTypeEnum.THREATS, new SiteProblemContent.Threats(), 0);
        return Collections.singletonList(problemInfo);
    }

    @Override
    public AbstractProblemInfo getProblem(@NotNull WebmasterHostId hostId, @Nullable UUID generationId,
                                          @NotNull SiteProblemTypeEnum problemType) {
        if (problemType != SiteProblemTypeEnum.THREATS) {
            return null;
        }
        return Iterables.getFirst(listProblems(hostId, generationId), null);
    }

    @NotNull
    public Set<SiteProblemTypeEnum> getSupportedProblemTypes() {
        return SUPPORTED_PROBLEM_TYPES;
    }
}
