package ru.yandex.webmaster3.internal.turbo;

import java.util.EnumSet;
import java.util.Set;

import com.fasterxml.jackson.databind.JsonNode;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.http.RequestQueryProperty;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.http.WriteAction;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.core.turbo.model.TurboHostSettings;
import ru.yandex.webmaster3.core.turbo.model.TurboHostSettingsBlock;
import ru.yandex.webmaster3.core.turbo.model.desktop.TurboDesktopSettings;
import ru.yandex.webmaster3.core.turbo.model.desktop.TurboDesktopSettingsBlock;
import ru.yandex.webmaster3.core.util.WwwUtil;
import ru.yandex.webmaster3.internal.common.InternalAction;
import ru.yandex.webmaster3.internal.common.request.AbstractUserVerifiedHostRequest;
import ru.yandex.webmaster3.internal.common.security.InternalGrant;
import ru.yandex.webmaster3.storage.turbo.service.preview.TurboFeedPreviewService;
import ru.yandex.webmaster3.storage.turbo.service.preview.TurboHostSettingsUploadResponse;
import ru.yandex.webmaster3.storage.turbo.service.preview.TurboHostSettingsUploadResponse.SavedDocumentData;
import ru.yandex.webmaster3.storage.turbo.service.preview.TurboHostSettingsUploadResponse.SavedProductInfo;
import ru.yandex.webmaster3.storage.turbo.service.settings.SetTurboSettingsResponse;
import ru.yandex.webmaster3.storage.turbo.service.settings.TurboSettingsMergerService;
import ru.yandex.webmaster3.storage.turbo.service.settings.TurboSettingsService;

/**
 * Created by Oleg Bazdyrev on 09/01/2020.
 */
@WriteAction
@Description("Сохранение настроек Турбо для домена")
@Category("turbo")
@Component("/turbo/settings/set")
public class SetTurboSettingsAction extends InternalAction<SetTurboSettingsAction.Request, SetTurboSettingsResponse> {

    private TurboFeedPreviewService turboFeedPreviewService;
    private TurboSettingsMergerService turboSettingsMergerService;
    private TurboSettingsService turboSettingsService;

    @Autowired
    public SetTurboSettingsAction(TurboFeedPreviewService turboFeedPreviewService,
                                  TurboSettingsMergerService turboSettingsMergerService,
                                  TurboSettingsService turboSettingsService) {
        super(InternalGrant.TURBO);
        this.turboFeedPreviewService = turboFeedPreviewService;
        this.turboSettingsMergerService = turboSettingsMergerService;
        this.turboSettingsService = turboSettingsService;
    }

    @Override
    public SetTurboSettingsResponse process(Request request) throws WebmasterException {
        WebmasterHostId hostId = request.getHostId();
        String domain = WwwUtil.cutWWWAndM(hostId);
        TurboHostSettings.TurboHostSettingsBuilder settingsBuilder = turboSettingsMergerService.mergeHostSettings(hostId, request.getUserId(),
                request.getSettings(), request.getSettingsBlocks(), true, null);
        TurboDesktopSettings.TurboDesktopSettingsBuilder desktopSettingsBuilder = turboSettingsMergerService.mergeDesktopSettings(hostId, request.getUserId(),
                request.getDesktopSettings(), request.getDesktopSettingsBlocks(), true, null);

        if (request.getSettingsBlocks().contains(TurboHostSettingsBlock.ADVERTISING) ||
                request.getDesktopSettingsBlocks().contains(TurboDesktopSettingsBlock.ADVERTISING)) {
            turboSettingsService.sendNotificationsAboutImportantChanges(domain, request.getUserId(), settingsBuilder, desktopSettingsBuilder);
        }

        if (request.getSettingsBlocks().contains(TurboHostSettingsBlock.PAYMENTS)) {
            turboSettingsService.sendNotificationsAboutImportantCommerceChanges(domain, request.getUserId(), settingsBuilder);
        }

        // сразу отошлем настройки хоста
        TurboHostSettingsUploadResponse hostSettingsResponse = turboFeedPreviewService.uploadHostSettings(
                hostId, settingsBuilder.build(), desktopSettingsBuilder.build(), null, false);
        if (CollectionUtils.isEmpty(hostSettingsResponse.getSavedDocuments())) {
            throw new WebmasterException("Could not upload host newSettings",
                    new WebmasterErrorResponse.TurboErrorResponse(getClass(), null, "Could not upload host newSettings"));
        }
        // сохраним распаршенные значения для секций
        if (settingsBuilder.getCommerceSettings() != null) {
            JsonNode parsedAccordion = hostSettingsResponse.getSavedDocuments().get(0).getData().stream().findAny()
                    .map(SavedDocumentData::getProductInfo).map(SavedProductInfo::getAccordion).orElse(null);
            settingsBuilder.setCommerceSettings(settingsBuilder.getCommerceSettings().withParsedAccordion(parsedAccordion));
        }

        // сохраняем настройки
        if (!request.getSettingsBlocks().isEmpty()) {
            turboSettingsService.updateSettings(domain, settingsBuilder.build(), request.getUserId());
        }
        if (!request.getDesktopSettingsBlocks().isEmpty()) {
            turboSettingsService.updateDesktopSettings(domain, desktopSettingsBuilder.build(), request.getUserId());
        }

        return new SetTurboSettingsResponse.NormalResponse();
    }

    @Getter
    @Setter(onMethod_ = @RequestQueryProperty)
    public static final class Request extends AbstractUserVerifiedHostRequest {
        @Description("Похостовые настройки")
        private TurboHostSettings settings;
        @Description("Настройки Турбо для десктопа")
        private TurboDesktopSettings desktopSettings;
        private Set<TurboHostSettingsBlock> settingsBlocks = EnumSet.noneOf(TurboHostSettingsBlock.class);
        private Set<TurboDesktopSettingsBlock> desktopSettingsBlocks = EnumSet.noneOf(TurboDesktopSettingsBlock.class);
    }

}
