package ru.yandex.webmaster3.storage.turbo.dao.scc;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nullable;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.RequiredArgsConstructor;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.feeds.feed.NativeFeedSccStatus;
import ru.yandex.webmaster3.core.turbo.model.TurboHostSettings;
import ru.yandex.webmaster3.core.turbo.model.commerce.TurboCommerceSettings;
import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedSettings;
import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedState;
import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedType;
import ru.yandex.webmaster3.core.util.WwwUtil;
import ru.yandex.webmaster3.storage.turbo.dao.TurboDomainSettingsYDao;
import ru.yandex.webmaster3.storage.turbo.dao.TurboDomainsStateCHDao;
import ru.yandex.webmaster3.storage.turbo.dao.TurboFeedsSettingsYDao;

/**
 * ishalaru
 * 23.09.2020
 **/
@Service
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class TurboSccService {
    private static final int MAXIMUM_SIZE = 20000;
    private static final int CACHE_TURBO_SCC_STATUS_EXPIRATION_MINUTES = 2;
    public static final DateTime SCC_DEADLINE = new DateTime(2021, 1, 31, 0, 0);

    private final TurboDomainsStateCHDao turboDomainsStateCHDao;
    private final TurboDomainSettingsYDao turboDomainSettingsYDao;
    private final TurboFeedsSettingsYDao turboFeedsService;

    private final LoadingCache<String, FrontModerationStatus> turboStatusCache = CacheBuilder.newBuilder()
            .expireAfterWrite(CACHE_TURBO_SCC_STATUS_EXPIRATION_MINUTES, TimeUnit.MINUTES)
            .maximumSize(MAXIMUM_SIZE)
            .build(CacheLoader.from(this::loadStatus));

    private FrontModerationStatus loadStatus(String domain) {
        // premoderationResult and bannedScc
        final TurboHostSettings settings = turboDomainSettingsYDao.getSettings(domain);
        List<TurboFeedSettings> feeds = turboFeedsService.getFeeds(domain);

        return getFrontModerationStatus(settings, feeds);
    }

    public FrontModerationStatus getStatus(WebmasterHostId hostId) {
        return getStatus(WwwUtil.cutWWWAndM(hostId.getPunycodeHostname()));
    }

    public FrontModerationStatus getStatus(String domain) {
        return turboStatusCache.getUnchecked(domain);
    }

    public FrontModerationStatus getFrontModerationStatus(String domain) {
        return loadStatus(domain);
    }

    public static FrontModerationStatus getFrontModerationStatus(
            @Nullable TurboHostSettings settings,
            List<TurboFeedSettings> feedSettings) {

        boolean isCartUrlEnabled = Optional.ofNullable(settings)
                .map(TurboHostSettings::getCommerceSettings)
                .map(TurboCommerceSettings::isCartUrlEnabled)
                .orElse(false);
        List<TurboFeedSettings> ymlFeeds = feedSettings.stream()
                .filter(x -> x.getState() != TurboFeedState.DELETED)
                .filter(x -> x.getType() == TurboFeedType.YML)
                .toList();
        if (isCartUrlEnabled) {
            return FrontModerationStatus.OUTER_CART;
        }
        if (ymlFeeds.isEmpty()) {
            return FrontModerationStatus.UNKNOWN;
        }
        boolean hasFailedFeeds = false;
        boolean hasBannedFeeds = false;
        boolean hasAllSuccessFeeds = true;
        boolean hasTurnedOnFeed = false;
        for (TurboFeedSettings ymlFeed : ymlFeeds) {
            if (ymlFeed.isActive()) {
                hasTurnedOnFeed = true;
            }
            if (ymlFeed.getStatus() == NativeFeedSccStatus.FAILED) {
                hasFailedFeeds = true;
            }
            if (!(ymlFeed.getStatus() == NativeFeedSccStatus.SUCCESS ||
                    ymlFeed.getStatus() == NativeFeedSccStatus.UNKNOWN)) {
                hasAllSuccessFeeds = false;
            }
            if (ymlFeed.getStatus() == NativeFeedSccStatus.BANNED) {
                hasBannedFeeds = true;
            }
        }
        if (hasBannedFeeds) {
            return FrontModerationStatus.BANNED;
        } else if (hasFailedFeeds) {
            return FrontModerationStatus.FAILED;
        } else if (!hasTurnedOnFeed) {
            return FrontModerationStatus.UNKNOWN;
        } else if (hasAllSuccessFeeds) {
            return FrontModerationStatus.PASS;
        } else {
            return FrontModerationStatus.IN_PROGRESS;
        }
    }

    public enum FrontModerationStatus {
        @Description("Проверка еще не производилась")
        UNKNOWN,
        @Description("Все хорошо, проверки пройдены.")
        PASS,
        @Description("Плохо, и магазин сам должен будет переотрправить не перемодерацию")
        FAILED,
        @Description("Забанен, может повторно пройти модерацию только обратившись в поддержку")
        BANNED,
        @Description("На проверке в Скк")
        IN_PROGRESS,
        @Description("Внешняя корзина")
        OUTER_CART,
        // статус нужен только для отключения внешних корзин
        @Description("Сломанная внешняя корзина")
        INVALID_OUTER_CART;
    }

}
