package ru.yandex.webmaster3.monitoring.queue.threats;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;

import ru.yandex.webmaster3.core.solomon.HandleCommonMetricsService;
import ru.yandex.webmaster3.core.solomon.Indicators;
import ru.yandex.webmaster3.core.solomon.SolomonSensor;
import ru.yandex.webmaster3.monitoring.common.YtQueueUtils;
import ru.yandex.webmaster3.storage.util.yt.YtException;
import ru.yandex.webmaster3.storage.util.yt.YtNode;
import ru.yandex.webmaster3.storage.util.yt.YtPath;
import ru.yandex.webmaster3.storage.util.yt.YtService;

/**
 * Created by leonidrom on 19/06/2017.
 */
public class ThreatsMonitoringService {
    private static final Logger log = LoggerFactory.getLogger(ThreatsMonitoringService.class);

    private static final String SECTION_LABEL_VALUE = "threats";
    private static final String ANTISPAM_SNAPSHOTS_QUEUE_TYPE = "antispam_snapshots_queue";
    private static final String ANTISPAM_EXPORT_QUEUE_TYPE = "antispam_export_queue";
    private static final String ANTIVIR_SNAPSHOTS_QUEUE_TYPE = "antivir_snapshots_queue";
    private static final String ANTIVIR_EXPORT_QUEUE_TYPE = "antivir_export_queue";
    private static final String PREPARED_QUEUE_TYPE = "prepared_queue";
    private static final int AVERAGE_SENSORS_SIZE = 500;

    @Autowired
    private HandleCommonMetricsService handleCommonMetricsService;
    @Autowired
    private YtService ytService;

    @Value("${webmaster3.monitoring.solomon.threats.enabled}")
    private boolean enabled;
    @Value("${webmaster3.monitoring.solomon.threats.refresh-interval}")
    private long refreshIntervalSeconds;

    @Value("${external.yt.service.arnold}://home/antispam/export/webmaster/threats")
    private YtPath ytThreatsAntispamSnapshotsPath;
    @Value("${external.yt.service.arnold}://home/antivir/prod/export/urls_for_webmaster")
    private YtPath ytThreatsAntivirSnapshotsPath;
    @Value("${external.yt.service.arnold}://home/webmaster/prod/antiall/snapshot")
    private YtPath ytThreatsPreparedPath;
    @Value("${external.yt.service.arnold.root.default}/export/antispam")
    private YtPath ytThreatsAntispamExportPath;
    @Value("${external.yt.service.arnold.root.default}/export/antivir")
    private YtPath ytThreatsAntivirExportPath;

    @Scheduled(cron = "${webmaster3.monitoring.solomon.threats.refresh-cron}")
    private void push() throws Exception {
        if (!enabled) {
            log.warn("Threats monitoring service disabled");
            return;
        }

        List<SolomonSensor> sensors = new ArrayList<>();
        log.info("Check for threats stats");

        // Data age sensors
        sensors.add(SolomonSensor.createAligned(refreshIntervalSeconds,
                getYtTableAgeInSeconds(ytThreatsPreparedPath))
                .withLabel(SolomonSensor.LABEL_SECTION, SECTION_LABEL_VALUE)
                .withLabel(SolomonSensor.LABEL_DATA_TYPE, PREPARED_QUEUE_TYPE)
                .withLabel(SolomonSensor.LABEL_INDICATOR, Indicators.DATA_AGE));

        sensors.add(SolomonSensor.createAligned(refreshIntervalSeconds,
                getYtTableAgeInSeconds(ytThreatsAntispamSnapshotsPath))
                .withLabel(SolomonSensor.LABEL_SECTION, SECTION_LABEL_VALUE)
                .withLabel(SolomonSensor.LABEL_DATA_TYPE, ANTISPAM_SNAPSHOTS_QUEUE_TYPE)
                .withLabel(SolomonSensor.LABEL_INDICATOR, Indicators.DATA_AGE));

        sensors.add(SolomonSensor.createAligned(refreshIntervalSeconds,
                getYtTableAgeInSeconds(ytThreatsAntivirSnapshotsPath))
                .withLabel(SolomonSensor.LABEL_SECTION, SECTION_LABEL_VALUE)
                .withLabel(SolomonSensor.LABEL_DATA_TYPE, ANTIVIR_SNAPSHOTS_QUEUE_TYPE)
                .withLabel(SolomonSensor.LABEL_INDICATOR, Indicators.DATA_AGE));


        // Number of tables sensors
        sensors.add(SolomonSensor.createAligned(refreshIntervalSeconds, getYtTablesCount(ytThreatsAntispamExportPath))
                .withLabel(SolomonSensor.LABEL_SECTION, SECTION_LABEL_VALUE)
                .withLabel(SolomonSensor.LABEL_DATA_TYPE, ANTISPAM_EXPORT_QUEUE_TYPE)
                .withLabel(SolomonSensor.LABEL_INDICATOR, Indicators.QUEUE_SIZE));

        sensors.add(SolomonSensor.createAligned(refreshIntervalSeconds, getYtTablesCount(ytThreatsAntivirExportPath))
                .withLabel(SolomonSensor.LABEL_SECTION, SECTION_LABEL_VALUE)
                .withLabel(SolomonSensor.LABEL_DATA_TYPE, ANTIVIR_EXPORT_QUEUE_TYPE)
                .withLabel(SolomonSensor.LABEL_INDICATOR, Indicators.QUEUE_SIZE));


        handleCommonMetricsService.handle(sensors, AVERAGE_SENSORS_SIZE);
    }

    private long getYtTableAgeInSeconds(YtPath ytPath) throws YtException, InterruptedException {
        return ytService.withoutTransactionQuery(cypressService -> {
            YtNode node = cypressService.getNode(ytPath);
            if (node == null) {
                return 0L;
            }
            return (System.currentTimeMillis() - node.getUpdateTime().getMillis()) / 1000L;
        });
    }

    private int getYtTablesCount(YtPath ytPath) throws YtException, InterruptedException {
        return YtQueueUtils.getQueueStats(ytService, ytPath,
                YtQueueUtils.ALL_TABLES_FILTER, YtQueueUtils.UNIX_TIMESTAMP_EXTRACTOR).tablesCount;
    }


}
