package ru.yandex.direct.web.entity.adgroup.controller;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;

import ru.yandex.direct.core.entity.campaign.service.accesschecker.CampaignSubObjectAccessCheckerFactory;
import ru.yandex.direct.core.entity.campaign.service.validation.CampaignAccessType;
import ru.yandex.direct.dbutil.model.ClientId;
import ru.yandex.direct.validation.result.Defect;
import ru.yandex.direct.web.core.exception.WebBadRequestException;

import static java.util.Collections.singletonList;
import static ru.yandex.direct.core.entity.campaign.service.validation.CampaignDefects.campaignNoRights;
import static ru.yandex.direct.core.entity.campaign.service.validation.CampaignDefects.campaignNotFound;

@Component
public class AdGroupControllerHelper {
    private final CampaignSubObjectAccessCheckerFactory campaignSubObjectAccessCheckerFactory;

    public AdGroupControllerHelper(CampaignSubObjectAccessCheckerFactory campaignSubObjectAccessCheckerFactory) {
        this.campaignSubObjectAccessCheckerFactory = campaignSubObjectAccessCheckerFactory;
    }

    /**
     * Параметр campaignId отправляется фронтом, хотя и не является пользовательским полем,
     * поэтому проверяем только что он принадлежит указанному клиенту и если это не так,
     * отдаем 400.
     * <p>
     * Так же проверяем, что у оператора есть права на указанную кампанию,
     * в противном случае отдаем 403 (так как в интерфейсе клиент не задает campaignId).
     */
    public void checkRequestParams(long operatorUid, ClientId clientId, long campaignId,
                                   CampaignAccessType accessType) {
        Defect defect = campaignSubObjectAccessCheckerFactory
                .newCampaignChecker(operatorUid, clientId, singletonList(campaignId))
                .createValidator(accessType)
                .getAccessConstraint()
                .apply(campaignId);
        if (defect == null) {
            return;
        }

        if (defect.equals(campaignNotFound())) {
            throw new WebBadRequestException(
                    "client (clientId = %s) doesn't have campaign (campaignId = %s)",
                    clientId, campaignId);
        } else if (defect.equals(campaignNoRights())) {
            throw new AccessDeniedException(String.format(
                    "operator (uid = %s) doesn't have access to campaign (campaignId = %s)",
                    operatorUid, campaignId));
        } else {
            throw new RuntimeException("Error code: " + defect.defectId().getCode());
        }
    }
}
