package ru.yandex.webmaster3.worker.user;

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

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.storage.abt.AbtService;
import ru.yandex.webmaster3.storage.abt.model.ExperimentInfo;
import ru.yandex.webmaster3.storage.events.data.WMCEvent;
import ru.yandex.webmaster3.storage.events.data.WMCEventContent;
import ru.yandex.webmaster3.storage.events.data.WMCEventType;
import ru.yandex.webmaster3.storage.events.data.events.RetranslateToUsersEvent;
import ru.yandex.webmaster3.storage.events.service.WMCEventsObserver;
import ru.yandex.webmaster3.storage.events.service.WMCEventsService;
import ru.yandex.webmaster3.storage.spam.ISpamHostFilter;
import ru.yandex.webmaster3.storage.user.service.UserHostsService;

/**
 * @author avhaliullin
 */
@Slf4j
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class HostToUsersEventRetranslatorObserver implements WMCEventsObserver {

    private final AbtService abtService;
    private final ISpamHostFilter fastSpamHostFilter;
    private final UserHostsService userHostsService;
    private final WMCEventsService wmcEventsService;

    @Value("${webmaster3.storage.yndxRobotWebmasterVrfr.id}")
    private Long yndxRobotFakeVerification;

    @Override
    public boolean observe(WMCEvent event) {
        WMCEventContent content = event.getContent();
        if (!(content instanceof RetranslateToUsersEvent)) {
            return false;
        }

        var retranslateEvent = (RetranslateToUsersEvent) content;
        var payload = retranslateEvent.getPayload();
        WMCEventType payloadType = payload.getType();
        List<WebmasterHostId> payloadHostIds = payload.getHostIds();
        WebmasterHostId payloadHostId = payload.getHostId();
        log.info("HostToUsersEventRetranslatorObserver. Type={} HostIds={}", payloadType, payloadHostIds);
        if (payload.getHostId() == null || fastSpamHostFilter.checkHost(payload.getHostId())) {
            log.info("Ignoring message for spam host {}", payload.getHostId());
            return false;
        }

        var experiment = retranslateEvent.getExperiment();
        var excludedUsers = retranslateEvent.getExcludedUsers();
        Set<Long> users = payloadHostIds.stream().map(userHostsService::listUsersVerifiedHost)
                .flatMap(map -> map.keySet().stream()).collect(Collectors.toSet());
        Map<Long, String> experimentsGroup = experiment == null ? Map.of() : abtService.getExperimentGroup(experiment, payloadHostId, users);
        List<WMCEventContent> newEvents = users.stream()
                .filter(uid -> !yndxRobotFakeVerification.equals(uid))
                .filter(uid -> !excludedUsers.contains(uid))
                .filter(uid -> experiment == null || experimentsGroup.containsKey(uid))
                .map(uid -> {
                    ExperimentInfo experimentInfo = experiment == null ? null : new ExperimentInfo(experiment.getName(), experimentsGroup.get(uid));
                    return payload.withUser(uid).setExperimentInfo(experimentInfo);
                })
                .collect(Collectors.toList());
        wmcEventsService.addEventContents(newEvents);
        log.info("Event {} for host {} retranslated to {} users", payloadType, payloadHostId, users.size());


        return true;
    }
}
