package ru.yandex.autotests.directapi.finance.paycampaigns;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import ru.yandex.aqua.annotations.project.Aqua;
import ru.yandex.autotests.direct.utils.money.Currency;
import ru.yandex.autotests.direct.utils.money.Money;
import ru.yandex.autotests.direct.utils.money.MoneyCurrency;
import ru.yandex.autotests.direct.utils.money.MoneyFormat;
import ru.yandex.autotests.directapi.apiclient.config.ProtocolType;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.apiclient.errors.AxisError;
import ru.yandex.autotests.directapi.apiclient.errors.AxisErrorDetails;
import ru.yandex.autotests.directapi.finance.FinanceFeatures;
import ru.yandex.autotests.directapi.finance.FinanceLogins;
import ru.yandex.autotests.directapi.model.Logins;
import ru.yandex.autotests.directapi.model.User;
import ru.yandex.autotests.directapi.model.finances.PayCampElementMap;
import ru.yandex.autotests.directapi.model.finances.PayCampaignsInfoMap;
import ru.yandex.autotests.directapi.model.finances.PayMethod;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.irt.testutils.allure.LogSteps;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

/**
 * Author pavryabov
 * Date 16.04.14
 */
@Aqua.Test
@Features(FinanceFeatures.BUG)
@RunWith(Parameterized.class)
public class PayCampaignsYMTest {
    private LogSteps log = LogSteps.getLogger(this.getClass());

    private static final String AGENCY_LOGIN = Logins.AGENCY_YE_DEFAULT;
    private static final String CLIENT_LOGIN = Logins.CLIENT_FREE_YE_DEFAULT;

    @ClassRule
    public static ApiSteps api = new ApiSteps().version(104).as(AGENCY_LOGIN);

    @ClassRule
    public static SemaphoreRule semaphore = Semaphore.getSemaphore();

    @Rule
    public Trashman trasher = new Trashman(api);

    @Parameterized.Parameter(0)
    public ProtocolType protocol;

    @Parameterized.Parameters(name = "ProtocolType = {0}")
    public static Collection roleValues() {
        return Arrays.asList(new Object[][]{
                {ProtocolType.SOAP},
                {ProtocolType.JSON}
        });
    }

    private static float sum = MoneyCurrency.get(null).getMinInvoiceAmount().floatValue();
    protected static long activeCampaignID1;
    protected static long activeCampaignID2;
    protected static long deletedCampaignID;
    protected static long draftCampaignID;
    protected static long moderatedCampaignID;

    @BeforeClass
    public static void initTest() {
        activeCampaignID1 = api.userSteps.addActiveCampaign(CLIENT_LOGIN, 1);
        activeCampaignID2 = api.userSteps.addActiveCampaign(CLIENT_LOGIN, 1);
        moderatedCampaignID = api.userSteps.addModeratedCampaign(CLIENT_LOGIN);
        draftCampaignID = api.userSteps.addDraftCampaign(CLIENT_LOGIN);
        deletedCampaignID = api.userSteps.campaignSteps().addDefaultTextCampaign(CLIENT_LOGIN);
        api.userSteps.campaignSteps().campaignsDelete(CLIENT_LOGIN, deletedCampaignID);
    }

    @Before
    public void setProtocol() {
        api.protocol(protocol);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6443")
    public void testPayNotMyCampaign() {
        log.info("Попытка оплатить кампанию, на которую нет прав (263) вместе с кампанией, на которую есть права");
        api.userSteps.financeSteps().shouldGetErrorOnPayCampaignsYM(
                new AxisError(54, null),
                new PayCampaignsInfoMap(api.type())
                        .withPayMethod(PayMethod.YM)
                        .withPayments(new PayCampElementMap(api.type())
                                        .withCampaignID(activeCampaignID2)
                                        .withSum(sum),
                                new PayCampElementMap(api.type())
                                        .withCampaignID(263)
                                        .withSum(sum))
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6448")
    public void testPayDeletedCampaign() {
        log.info("Попытка оплаты несуществующей (была удалена) кампании");
        api.userSteps.financeSteps().shouldGetErrorOnPayCampaignsYM(
                new AxisError(1, null),
                new PayCampaignsInfoMap(api.type())
                        .withPayMethod(PayMethod.YM)
                        .withPayments(new PayCampElementMap(api.type())
                                        .withCampaignID(deletedCampaignID)
                                        .withSum(sum),
                                new PayCampElementMap(api.type())
                                        .withCampaignID(activeCampaignID2)
                                        .withSum(sum))
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6446")
    public void testPayDraftCampaign() {
        log.info("Попытка оплаты неактивной кампании");
        api.userSteps.financeSteps().shouldGetErrorOnPayCampaignsYM(
                new AxisError(354, AxisErrorDetails.CAMPAIGN_NOT_MODERATED, draftCampaignID),
                new PayCampaignsInfoMap(api.type())
                        .withPayMethod(PayMethod.YM)
                        .withPayments(new PayCampElementMap(api.type())
                                .withCampaignID(draftCampaignID)
                                .withSum(sum))
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6445")
    public void testSeveralPaysOneCampaign() {
        log.info("Оплата одной кампании дважды в одном вызове");
        api.userSteps.financeSteps().shouldGetErrorOnPayCampaignsYM(
                new AxisError(354, AxisErrorDetails.PAYCAMPELEMENT_CAMPAIGNID_MUST_BE_UNIQUE),
                new PayCampaignsInfoMap(api.type())
                        .withPayMethod(PayMethod.YM)
                        .withPayments(new PayCampElementMap(api.type())
                                        .withCampaignID(activeCampaignID1)
                                        .withSum(sum),
                                new PayCampElementMap(api.type())
                                        .withCampaignID(activeCampaignID1)
                                        .withSum(sum))
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6444")
    public void testPayCampaignZeroSumToPay() {
        log.info("Оплата кампании по кредитному договору на сумму: 0уе");
        api.userSteps.financeSteps().shouldGetErrorOnPayCampaignsYM(
                new AxisError(354, AxisErrorDetails.INVALID_AMOUNT_SPECIFIED_FOR_CAMPAIGN, activeCampaignID1),
                new PayCampaignsInfoMap(api.type())
                        .withPayMethod(PayMethod.YM)
                        .withPayments(new PayCampElementMap(api.type())
                                .withCampaignID(activeCampaignID1)
                                .withSum(0f))
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6452")
    public void testLessThenMinLimitSumPayCampaign() {
        log.info("Оплата кампании на сумму: " + sum);
        api.userSteps.financeSteps().shouldGetErrorOnPayCampaignsYM(
                new AxisError(354, AxisErrorDetails.LOW_AMOUNT_SPECIFIED_FOR_CAMPAIGN_WITH_PLACEHOLDERS,
                        MoneyCurrency.get(Currency.YND_FIXED).getMinTransferRest()
                                .stringValue(MoneyFormat.TWO_DIGITS_POINT_SEPARATED), activeCampaignID1),
                new PayCampaignsInfoMap(api.type())
                        .withPayMethod(PayMethod.YM)
                        .withPayments(new PayCampElementMap(api.type())
                                .withCampaignID(activeCampaignID1)
                                .withSum(Money.valueOf(sum).getPrevious().floatValue()))
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6456")
    public void sendFinanceTokenForYaMoPayment() {
        log.info("Оплата кампании с финансовым токеном");
        api.userSteps.financeSteps().shouldGetErrorOnPayCampaigns(
                new AxisError(360, null),
                new PayCampaignsInfoMap(api.type())
                        .withPayMethod(PayMethod.YM)
                        .withPayments(new PayCampElementMap(api.type())
                                .withCampaignID(activeCampaignID1)
                                .withSum(sum))
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6453")
    public void sendEmptyPaymentToken() {
        log.info("Оплата кампании с пустым платежным токеном");
        api.userSteps.financeSteps().shouldGetErrorOnPayCampaignsYM(
                new AxisError(350, AxisErrorDetails.FINANCIAL_TOKEN_NOT_SUBMITTED),
                new PayCampaignsInfoMap(api.type())
                        .withPayMethod(PayMethod.YM)
                        .withPayments(new PayCampElementMap(api.type())
                                .withCampaignID(activeCampaignID1)
                                .withSum(sum)),
                ""
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6454")
    public void sendInvalidPaymentToken() {
        log.info("Оплата кампании с невалидным платежным токеном");
        api.userSteps.financeSteps().shouldGetErrorOnPayCampaignsYM(
                new AxisError(361, null),
                new PayCampaignsInfoMap(api.type())
                        .withPayMethod(PayMethod.YM)
                        .withPayments(new PayCampElementMap(api.type())
                                .withCampaignID(activeCampaignID1)
                                .withSum(sum)),
                "invalid"
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6455")
    public void sendElsePaymentToken() {
        log.info("Оплата кампании с чужим платежным токеном");
        api.userSteps.financeSteps().shouldGetErrorOnPayCampaignsYM(
                new AxisError(372, AxisErrorDetails.SOMEONE_ELSE_PAYMENT_TOKEN),
                new PayCampaignsInfoMap(api.type())
                        .withPayMethod(PayMethod.YM)
                        .withPayments(new PayCampElementMap(api.type())
                                .withCampaignID(activeCampaignID1)
                                .withSum(sum)),
                User.get(FinanceLogins.FREE_CLIENT_YM).getPaymentToken()
        );
    }
}
