package ru.yandex.webmaster3.viewer.http.turbo.dashboard;

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

import lombok.RequiredArgsConstructor;
import org.joda.time.Duration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.autodoc.common.doc.annotation.Category;
import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.checklist.data.SiteProblemState;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.turbo.model.TurboAutoRelatedSettings;
import ru.yandex.webmaster3.core.turbo.model.TurboHostSettings;
import ru.yandex.webmaster3.core.turbo.model.autoparser.AutoparserToggleState;
import ru.yandex.webmaster3.core.turbo.model.commerce.TurboBitrixSettings;
import ru.yandex.webmaster3.core.turbo.model.commerce.TurboCommerceSettings;
import ru.yandex.webmaster3.core.turbo.model.commerce.TurboPaymentsSettings;
import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedSettings;
import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedType;
import ru.yandex.webmaster3.core.turbo.model.statistics.TurboClicksStatistics;
import ru.yandex.webmaster3.core.turbo.model.statistics.TurboDomainStatistics;
import ru.yandex.webmaster3.core.turbo.model.statistics.TurboHostStatisticsType;
import ru.yandex.webmaster3.core.util.IdUtils;
import ru.yandex.webmaster3.core.util.WwwUtil;
import ru.yandex.webmaster3.core.util.json.JsonMapping;
import ru.yandex.webmaster3.storage.abt.AbtService;
import ru.yandex.webmaster3.storage.abt.model.Experiment;
import ru.yandex.webmaster3.storage.cache.DashboardCacheService;
import ru.yandex.webmaster3.storage.cache.DashboardType;
import ru.yandex.webmaster3.storage.checklist.service.SiteProblemsService;
import ru.yandex.webmaster3.storage.turbo.dao.TurboDomainsStateCHDao;
import ru.yandex.webmaster3.storage.turbo.dao.TurboDomainsStateHelper;
import ru.yandex.webmaster3.storage.turbo.dao.TurboDomainsWithAcceptedOfferYDao;
import ru.yandex.webmaster3.storage.turbo.dao.api.TurboApiHostTasksYDao;
import ru.yandex.webmaster3.storage.turbo.dao.automorda.TurboAutoMordaStatus;
import ru.yandex.webmaster3.storage.turbo.dao.statistics.TurboDomainStatisticsYDao;
import ru.yandex.webmaster3.storage.turbo.service.TurboClickStatisticsService;
import ru.yandex.webmaster3.storage.turbo.service.TurboDomainsStateService.TurboDomainState;
import ru.yandex.webmaster3.storage.turbo.service.TurboFeedsService;
import ru.yandex.webmaster3.storage.turbo.service.TurboSearchUrlsStatisticsService;
import ru.yandex.webmaster3.storage.turbo.service.settings.TurboSettingsService;
import ru.yandex.webmaster3.viewer.http.AbstractUserVerifiedHostAction;

import static ru.yandex.webmaster3.storage.abt.model.Experiment.TURBO_TEASER_FOR_NO_STORE_WITH_RSS;
import static ru.yandex.webmaster3.storage.abt.model.Experiment.TURBO_TEASER_FOR_STORE_WITH_YML;

/**
 * @author avhaliullin
 */
@ReadAction
@Description("Ручка для отображения турбо-статистики на дашборде сайта")
@Component("/dashboard/turbo/info")
@Category(("turbo"))
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class GetTurboDashboardInfoAction extends AbstractUserVerifiedHostAction<GetTurboDashboardInfoRequest, GetTurboDashboardInfoResponse> {
    public static final String SER_VER = "v8";

    private final AbtService abtService;
    private final DashboardCacheService dashboardCacheService;
    private final SiteProblemsService siteProblemsService;
    private final TurboApiHostTasksYDao turboApiHostTasksYDao;
    private final TurboClickStatisticsService turboClickStatisticsService;
    private final TurboDomainsStateCHDao turboDomainsStateCHDao;
    private final TurboDomainStatisticsYDao turboDomainStatisticsYDao;
    private final TurboDomainsWithAcceptedOfferYDao turboDomainsWithAcceptedOfferYDao;
    private final TurboFeedsService turboFeedsService;
    private final TurboSearchUrlsStatisticsService turboSearchUrlsStatisticsService;
    private final TurboSettingsService turboSettingsService;

    @Override
    public GetTurboDashboardInfoResponse process(GetTurboDashboardInfoRequest request) {
        String domain = WwwUtil.cutWWWAndM(request.getHostId());
        WebmasterHostId hostId = IdUtils.urlToHostId(domain);
        Optional<GetTurboDashboardInfoResponse> cacheOpt = dashboardCacheService.getDataUnchecked(
                hostId, DashboardType.TURBO, SER_VER, bytes -> JsonMapping.readValue(bytes, GetTurboDashboardInfoResponse.class));
        if (cacheOpt.isPresent()) {
            return cacheOpt.get();
        }
        Map<String, String> experiments = abtService.getHostExperiments(hostId);
        boolean offerAccepted = turboDomainsWithAcceptedOfferYDao.contains(hostId);
        final TurboSearchUrlsStatisticsService.TurboDomainStats turboInfo = turboSearchUrlsStatisticsService.getTurboInfo(domain);
        // только поле domain и automordaStatus automordaSample
        TurboDomainState domainState = turboDomainsStateCHDao.getDomainState(domain, TurboDomainsStateHelper.getAutomordaFields());
        TurboAutoMordaStatus autoMordaStatus = domainState.getAutoMordaStatus();
        boolean hasAutoparsedPages = turboInfo.getAutoparserToggleState() != AutoparserToggleState.ABSENT;
        long autoparsedPages = 0L;
        if (hasAutoparsedPages) {
            List<TurboDomainStatistics> statistics = turboDomainStatisticsYDao.getStatistics(domain);
            autoparsedPages = statistics.stream()
                    .filter(s -> s.getSource().isAutoparser() && s.getType() == TurboHostStatisticsType.PERSISTED)
                    .mapToLong(TurboDomainStatistics::getValue).sum();
        }
        boolean autoparserEnabled = turboInfo.getAutoparserToggleState() == AutoparserToggleState.ON;
        boolean hasApiSources = turboApiHostTasksYDao.hasTasks(hostId);
        Set<TurboFeedType> activeSourceTypes = turboFeedsService.getFeeds(domain).stream()
                .filter(TurboFeedSettings::isActive).map(TurboFeedSettings::getType).collect(Collectors.toSet());


        int turboProblemsCount =
                (int) siteProblemsService.listProblemsForHost(hostId, null).stream()
                        .filter(p -> p.getState() == SiteProblemState.PRESENT && p.getProblemType().isTurboProblem())
                        .count();

        int turboShopProblemsCount =
                (int) siteProblemsService.listProblemsForHost(hostId, null).stream()
                        .filter(p -> p.getState() == SiteProblemState.PRESENT &&
                                p.getProblemType().isTurboShopProblem(turboInfo.getTurboShopSearchUrls() > 0))
                        .count();

        int turboContentProblemsCount =
                (int) siteProblemsService.listProblemsForHost(hostId, null).stream()
                        .filter(p -> p.getState() == SiteProblemState.PRESENT &&
                                p.getProblemType().isTurboContentProblem(turboInfo.getTurboContentSearchUrls() > 0))
                        .count();

        boolean analyticsConfigured = false;
        boolean advertisementConfigured = false;
        boolean autoRelatedEnabled = false;
        boolean autoMordaEnabled = false;
        boolean hasTurboSources = (autoparserEnabled && autoparsedPages > 0) || hasApiSources || !activeSourceTypes.isEmpty();
        boolean hasShopTurboSources = activeSourceTypes.stream().anyMatch(TurboFeedType::isYml);
        boolean hasContentTurboSources = activeSourceTypes.stream().anyMatch(x -> !x.isYml());
        Optional<TurboHostSettings> settings = Optional.of(turboSettingsService.getSettings(domain));
        if (hasTurboSources) {
            analyticsConfigured = settings.map(s -> !s.getAnalyticsSettings().isEmpty()).orElse(false);
            advertisementConfigured = settings.map(s -> !s.getAdvertisingSettings().isEmpty()).orElse(false);
            autoRelatedEnabled = settings.map(TurboHostSettings::getAutoRelated).orElse(false) ||
                    settings.map(TurboHostSettings::getAutoRelatedSettings).map(TurboAutoRelatedSettings::isEnabled).orElse(false);
            autoMordaEnabled = settings.map(TurboHostSettings::getAutoMorda).orElse(false);
        }
        // clicks
        TurboClicksStatistics clicksStats = turboClickStatisticsService.turboClickStatistics(domain);

        boolean autoMordaAvailableButOff = autoMordaStatus == TurboAutoMordaStatus.OK && !autoMordaEnabled;

        // WMC-8236
        boolean isShowTeaserForStoreWithYmlFeedsWithoutTurbo = experiments.containsKey(TURBO_TEASER_FOR_STORE_WITH_YML.name());
        boolean isShowTeaserForNoStoreWithRssFeedsWithoutTurbo = experiments.containsKey(TURBO_TEASER_FOR_NO_STORE_WITH_RSS.name());

        var builder = GetTurboDashboardInfoResponse.builder()
                .turboOfferAccepted(offerAccepted)
                .autoparsedPagesCount(autoparsedPages)
                .autoparserEnabled(autoparserEnabled)
                .hasTurboSources(hasTurboSources)
                .turboPagesOnSearch(turboInfo.getTurboSearchUrls())
                .totalTurboPages(turboInfo.getTurboUrls())
                .turboProblemsCount(turboProblemsCount)
                .advertisementConfigured(advertisementConfigured)
                .analyticsConfigured(analyticsConfigured)
                .hasApiSources(hasApiSources)
                .hasRssSources(activeSourceTypes.contains(TurboFeedType.RSS))
                .hasYmlSources(activeSourceTypes.contains(TurboFeedType.YML))
                .autoRelatedEnabled(autoRelatedEnabled)
                .totalClicks(clicksStats == null ? 0 : clicksStats.getTotalClicks())
                .turboClicks(clicksStats == null ? 0 : clicksStats.getTurboClicks())
                .autoparsedClicks(clicksStats == null ? 0 : clicksStats.getAutoparsedClicks())
                .autoMordaAvailableButOff(autoMordaAvailableButOff)
                .showTeaserForStoreWithYmlFeedsWithoutTurbo(isShowTeaserForStoreWithYmlFeedsWithoutTurbo)
                .showTeaserForNoStoreWithRssFeedsWithoutTurbo(isShowTeaserForNoStoreWithRssFeedsWithoutTurbo)

                .hasTurboShopSources(hasShopTurboSources)
                .hasTurboContentSources(hasContentTurboSources)
                .turboShopPagesOnSearch(turboInfo.getTurboShopSearchUrls())
                .turboContentPagesOnSearch(turboInfo.getTurboContentSearchUrls())
                .turboShopProblemsCount(turboShopProblemsCount)
                .turboContentProblemsCount(turboContentProblemsCount)
                ;

        // WMC-8913 -- турбо-корзина, оплаты, битрикс
        Optional<TurboCommerceSettings> commerceSettings = settings.map(TurboHostSettings::getCommerceSettings);
        builder.turboCartEnabled(commerceSettings.map(TurboCommerceSettings::isTurboCartEnabled).orElse(false));
        builder.paymentsEnabled(commerceSettings.map(TurboCommerceSettings::getPaymentsSettings).map(TurboPaymentsSettings::isEnabled).orElse(false));
        builder.bitrixEnabled(commerceSettings.map(TurboCommerceSettings::getBitrixSettings).map(TurboBitrixSettings::isEnabled).orElse(false));
        builder.hasBitrixCMS(experiments.containsKey(Experiment.CMS_BITRIX.name()));

        var resp = builder.build();

        dashboardCacheService.saveData(hostId, DashboardType.TURBO, SER_VER, JsonMapping.writeValueAsBytes(resp), Duration.standardMinutes(5));
        return resp;
    }

}
