package ru.yandex.qe.dispenser.ws.front;

import java.util.Set;

import javax.inject.Inject;

import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import ru.yandex.qe.dispenser.domain.dictionaries.impl.FrontDictionariesManager;
import ru.yandex.qe.dispenser.domain.dictionaries.model.CampaignProvidersSettingsDictionary;
import ru.yandex.qe.dispenser.domain.dictionaries.model.FrontDictionaries;
import ru.yandex.qe.dispenser.ws.common.domain.errors.ErrorCollection;
import ru.yandex.qe.dispenser.ws.common.domain.errors.TypedError;
import ru.yandex.qe.dispenser.ws.common.domain.result.Result;

@Component
public class FrontDictionariesCollectManager {

    @NotNull
    private final FrontDictionariesManager frontDictionariesManager;

    @Inject
    public FrontDictionariesCollectManager(@NotNull final FrontDictionariesManager frontDictionariesManager) {
        this.frontDictionariesManager = frontDictionariesManager;
    }

    @NotNull
    @Transactional(propagation = Propagation.REQUIRED)
    public Result<FrontDictionaries, ErrorCollection<String, TypedError<String>>> getFrontDictionaries(
            @Nullable final Long campaignId, @NotNull final Set<String> dictionaries) {
        final FrontDictionaries.Builder dictionariesBuilder = FrontDictionaries.builder();
        final ErrorCollection.Builder<String, TypedError<String>> errorsBuilder = ErrorCollection.builder();
        final Set<String> invalidDictionaries = Sets.difference(dictionaries, FrontDictionaries.VALID_DICTIONARIES);
        if (!invalidDictionaries.isEmpty()) {
            errorsBuilder.addError("dictionaries", TypedError.badRequest("Invalid dictionary keys: "
                    + String.join(", ", invalidDictionaries) + "."));
        }
        if (dictionaries.contains(FrontDictionaries.CAMPAIGN_PROVIDERS_SETTINGS)) {
            prepareCampaignProviderSettings(campaignId, dictionariesBuilder, errorsBuilder);
        }
        if (dictionaries.contains(FrontDictionaries.REQUEST_STATUS)) {
            frontDictionariesManager.prepareRequestStatusesDictionary(dictionariesBuilder);
        }
        if (dictionaries.contains(FrontDictionaries.REQUEST_REASON)) {
            frontDictionariesManager.prepareRequestReasonDictionary(dictionariesBuilder);
        }
        if (dictionaries.contains(FrontDictionaries.PROVIDERS_WITH_CAMPAIGNS)) {
            frontDictionariesManager.prepareProvidersWithCampaigns(dictionariesBuilder);
        }
        if (dictionaries.contains(FrontDictionaries.CAMPAIGNS_WITH_BIG_ORDERS)) {
            frontDictionariesManager.prepareCampaignsWithBigOrders(dictionariesBuilder);
        }
        if (dictionaries.contains(FrontDictionaries.SORT_FIELDS)) {
            frontDictionariesManager.prepareSortFields(dictionariesBuilder);
        }
        if (dictionaries.contains(FrontDictionaries.RESOURCES_WITH_CAMPAIGNS)) {
            frontDictionariesManager.prepareResourcesWithCampaigns(dictionariesBuilder);
        }
        if (dictionaries.contains(FrontDictionaries.SEGMENTATIONS_WITH_CAMPAIGNS)) {
            frontDictionariesManager.prepareSegmentationsWithCampaigns(dictionariesBuilder);
        }
        if (dictionaries.contains(FrontDictionaries.UNITS)) {
            frontDictionariesManager.prepareUnits(dictionariesBuilder);
        }
        if (dictionaries.contains(FrontDictionaries.RESOURCES_WITH_UNIT_ALIASES)) {
            frontDictionariesManager.prepareResourcesWithUnitAliases(dictionariesBuilder);
        }
        if (errorsBuilder.hasAnyErrors()) {
            return Result.failure(errorsBuilder.build());
        }
        return Result.success(dictionariesBuilder.build());
    }


    public void prepareCampaignProviderSettings(@Nullable final Long campaignId,
                                                @NotNull final FrontDictionaries.Builder dictionariesBuilder,
                                                @NotNull final ErrorCollection.Builder<String, TypedError<String>> errorsBuilder) {
        final CampaignProvidersSettingsDictionary campaignProvidersSettingsDictionary = frontDictionariesManager.getCampaignProviderSettings(campaignId);
        if (campaignProvidersSettingsDictionary != null) {
            dictionariesBuilder.campaignProvidersSettingsDictionary(campaignProvidersSettingsDictionary);
        } else if (campaignId != null) {
            errorsBuilder.addError("campaignId", TypedError.badRequest("Campaign with id ["
                    + campaignId + "] was not found."));
        } else {
            errorsBuilder
                    .addError(TypedError.badRequest("No campaign is active at this moment."))
                    .addError("campaignId", TypedError.badRequest("Campaign id is required."));
        }
    }
}
