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

import java.util.Comparator;

import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.http.ActionResponse;
import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.core.payments.ServiceMerchantInfo;
import ru.yandex.webmaster3.core.turbo.model.TurboDisplaySettings;
import ru.yandex.webmaster3.core.turbo.model.TurboHostSettings;
import ru.yandex.webmaster3.core.turbo.model.TurboHostSettings.TurboHostSettingsBuilder;
import ru.yandex.webmaster3.core.turbo.model.analytics.AnalyticsSettings;
import ru.yandex.webmaster3.core.turbo.model.commerce.TurboCommerceSettings;
import ru.yandex.webmaster3.core.turbo.model.commerce.TurboCommerceSettings.TurboCommerceSettingsBuilder;
import ru.yandex.webmaster3.core.turbo.model.commerce.TurboPaymentsSettings;
import ru.yandex.webmaster3.core.turbo.model.desktop.TurboDesktopSettings;
import ru.yandex.webmaster3.core.turbo.model.desktop.TurboDesktopSettings.TurboDesktopSettingsBuilder;
import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedType;
import ru.yandex.webmaster3.core.turbo.model.menu.TurboMenuItem;
import ru.yandex.webmaster3.core.util.WwwUtil;
import ru.yandex.webmaster3.storage.abt.AbtService;
import ru.yandex.webmaster3.storage.abt.ExperimentMapperService;
import ru.yandex.webmaster3.storage.turbo.dao.TurboDomainsStateCHDao;
import ru.yandex.webmaster3.storage.turbo.dao.automorda.TurboAutoMordaStatus;
import ru.yandex.webmaster3.storage.turbo.dao.commerce.model.TurboListingsInfo;
import ru.yandex.webmaster3.storage.turbo.service.TurboDomainsStateService.TurboDomainState;
import ru.yandex.webmaster3.storage.turbo.service.TurboFeedsService;
import ru.yandex.webmaster3.storage.turbo.service.settings.TurboSettingsService;
import ru.yandex.webmaster3.storage.turbo.service.validation.TurboParserService;
import ru.yandex.webmaster3.viewer.http.AbstractUserVerifiedHostAction;
import ru.yandex.webmaster3.viewer.http.AbstractUserVerifiedHostRequest;
import ru.yandex.webmaster3.viewer.http.turbo.host.GetTurboSettingsAction.Request;
import ru.yandex.webmaster3.viewer.http.turbo.host.GetTurboSettingsAction.Response;


/**
 * Created by Oleg Bazdyrev on 06/07/2017.
 */
@ReadAction
@Category("turbo")
@Description("Получает текущие настройки хоста для Турбо")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class GetTurboSettingsAction extends AbstractUserVerifiedHostAction<Request, Response> {

    private static final Logger log = LoggerFactory.getLogger(GetTurboSettingsAction.class);

    private final AbtService abtService;
    private final ExperimentMapperService experimentMapperService;
    private final TurboDomainsStateCHDao turboDomainsStateCHDao;
    private final TurboFeedsService turboFeedsService;
    private final TurboParserService turboParserService;
    private final TurboSettingsService turboSettingsService;

    @Override
    public Response process(Request request) {
        // затягиваем настройки из кассандры
        String domain = WwwUtil.cutWWWAndM(request.getHostId());
        TurboHostSettings settings = turboSettingsService.getSettings(domain);
        TurboDesktopSettings desktopSettings = turboSettingsService.getDesktopSettings(domain);
        TurboDomainState domainState = turboDomainsStateCHDao.getDomainState(domain);
        // сортировка рекламы и аналитики
        if (settings.getAnalyticsSettings() != null) {
            settings.getAnalyticsSettings().sort(Comparator.comparing(AnalyticsSettings::getType));
        }
        boolean hasAutoRelatedSamples = !domainState.getAutorelatedSamples().isEmpty();
        TurboAutoMordaStatus autoMordaStatus = domainState.getAutoMordaStatus();
        boolean hasAutoMordaSamples = autoMordaStatus == TurboAutoMordaStatus.OK;
        TurboCommerceSettings commerceSettings = settings.getCommerceSettings();
        boolean hasYmlFeeds = turboFeedsService.getFeeds(domain).stream()
                .anyMatch(tfs -> tfs.getType() == TurboFeedType.YML) || (commerceSettings != null && commerceSettings.isOrderMethodSelected());
        TurboListingsInfo turboListingInfo = domainState.getListingsInfo();
        boolean hasYmlListings = turboListingInfo != null && turboListingInfo.canBeTurnedOn();

        TurboHostSettingsBuilder hsb = new TurboHostSettingsBuilder(settings);
        TurboDesktopSettingsBuilder dsb = new TurboDesktopSettingsBuilder(desktopSettings);

        // обновление статусов по оплатам
        if (commerceSettings != null && commerceSettings.getPaymentsSettings() != null) {
            TurboCommerceSettingsBuilder csb = new TurboCommerceSettingsBuilder(commerceSettings);
            TurboPaymentsSettings paymentsSettings = commerceSettings.getPaymentsSettings();
            try {
                ServiceMerchantInfo merchantInfo = turboParserService.refreshMerchantInfo(
                        domain, paymentsSettings.getToken(), null);
                paymentsSettings = paymentsSettings.withMerchantInfo(merchantInfo);
                csb.setPaymentsSettings(paymentsSettings);
                hsb.setCommerceSettings(csb.build());
            } catch (WebmasterException e) {
                // не падаем полностью при проблемах с оплатами
                log.error("Error refreshing payments settings", e);
            }
        }
        // подмерживаем автоменю
        hsb.setAutoMenuSettings(TurboMenuItem.mergeUserAndAutoMenu(settings.getAutoMenuSettings(), domainState.getCommerceCategories(), false));
        // TODO после полного переезда кастомизации можно будет удалить header-ы из старых мест displaySettings
        hsb.setDisplaySettings(TurboDisplaySettings.builder(settings.getDisplaySettings()).header(settings.getHeader()).build());
        dsb.setDisplaySettings(TurboDisplaySettings.builder(desktopSettings.getDisplaySettings()).header(desktopSettings.getHeader()).build());

        settings = hsb.build();
        desktopSettings = dsb.build();

        if (hasYmlFeeds) {
            // WMC-8085
            settings.getMenuSettings().addAll(0, settings.getTopMenuSettings());
            settings.getTopMenuSettings().clear();
        }

        return new Response(settings, desktopSettings, hasAutoRelatedSamples, hasAutoMordaSamples, autoMordaStatus,
                hasYmlFeeds, hasYmlListings, false);
    }

    public static class Request extends AbstractUserVerifiedHostRequest {

    }

    public static class Response implements ActionResponse.NormalResponse {

        private final TurboHostSettings settings;
        private final TurboDesktopSettings desktopSettings;
        private final boolean hasAutoRelatedSamples;
        private final boolean hasAutoMordaSamples;
        private final TurboAutoMordaStatus autoMordaStatus;
        private final boolean hasYmlFeeds;
        private final boolean hasYmlListings;
        private final boolean canHaveChat;

        public Response(TurboHostSettings settings, TurboDesktopSettings desktopSettings,
                        boolean hasAutoRelatedSamples, boolean hasAutoMordaSamples,
                        TurboAutoMordaStatus autoMordaStatus, boolean hasYmlFeeds,
                        boolean hasYmlListings, boolean canHaveChat) {
            this.settings = settings;
            this.desktopSettings = desktopSettings;
            this.hasAutoRelatedSamples = hasAutoRelatedSamples;
            this.hasAutoMordaSamples = hasAutoMordaSamples;
            this.autoMordaStatus = autoMordaStatus;
            this.hasYmlFeeds = hasYmlFeeds;
            this.hasYmlListings = hasYmlListings;
            this.canHaveChat = canHaveChat;
        }

        @Description("Текущие настройки Турбо для хоста")
        public TurboHostSettings getSettings() {
            return settings;
        }

        @Description("Настройки Турбо для десктопа")
        public TurboDesktopSettings getDesktopSettings() {
            return desktopSettings;
        }

        @Description("Есть ли у хоста примеры ссылок для бесконечной ленты")
        public boolean isHasAutoRelatedSamples() {
            return hasAutoRelatedSamples;
        }

        @Description("Есть ли у хоста примеры автоморд")
        public boolean isHasAutoMordaSamples() {
            return hasAutoMordaSamples;
        }

        @Description("Состояние автоморды")
        public TurboAutoMordaStatus getAutoMordaStatus() {
            return autoMordaStatus;
        }

        @Description("У хоста есть хотя бы один yml-фид")
        public boolean isHasYmlFeeds() {
            return hasYmlFeeds;
        }

        @Description("Есть ли у хоста листинги (можно ли показывать соотв.раздел)")
        public boolean isHasYmlListings() {
            return hasYmlListings;
        }

        public boolean isCanHaveChat() {
            return canHaveChat;
        }
    }
}
