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


import java.util.Arrays;
import java.util.List;

import com.yandex.direct.api.v5.campaigns.CampaignGetItem;
import org.apache.commons.lang.ArrayUtils;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;

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.tags.TagDictionary;
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.common.api45.APIPort_PortType;
import ru.yandex.autotests.directapi.common.api45.Account;
import ru.yandex.autotests.directapi.common.api45.CreateNewSubclientResponse;
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.finances.PayCampElementMap;
import ru.yandex.autotests.directapi.model.finances.PayMethod;
import ru.yandex.autotests.directapi.model.finances.PaymentMap;
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.Tag;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.assertThat;

/**
 * User: mariabye
 * Date: 13.11.13
 * <p>
 * https://jira.yandex-team.ru/browse/DIRECT-25544
 */
@Aqua.Test
@Features(FinanceFeatures.ACCOUNT_MANAGEMENT)
@Tag(TagDictionary.TRUNK)
public class PayedCampaignStatusTest {
    private LogSteps log = LogSteps.getLogger(this.getClass());

    public static String selfClient = FinanceLogins.CLIENT_TO_CHECK_DRAFT_PAYMENT;
    public static String agencyLogin = FinanceLogins.AGENCY_INVOICE_2;

    @ClassRule
    public static ApiSteps api = new ApiSteps().version(104).wsdl(APIPort_PortType.class);

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

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

    Money minInvoiceAmount = MoneyCurrency.get(Currency.RUB).getMinInvoiceAmount().addVAT();
    private static Account selfAccount;
    private static Account subClientAccount;

    @BeforeClass
    public static void setAccount() {
        api.as(Logins.SUPER_LOGIN).userSteps.financeSteps().verifySharedAccount(selfClient);
        selfAccount = api.userSteps.enableAndGetAccount(selfClient);
        api.userSteps.balanceSteps().setClientOverdraft(selfAccount.getLogin());
        CreateNewSubclientResponse subClient = api.as(agencyLogin).userSteps.clientSteps()
                .createNewAgencySubClient("create", agencyLogin, Currency.RUB);
        String subClientLogin = subClient.getLogin();
        api.userSteps.addDraftCampaign(subClientLogin);
        api.userSteps.financeSteps().enableSharedAccount(subClientLogin);
        subClientAccount = api.userSteps.financeSteps().getAccount(subClientLogin);
    }

    @After
    public void unArchiveCampaign() {
        List<CampaignGetItem> campaigns = api.as(selfClient).userSteps.campaignSteps().getCampaigns(selfClient);
        long[] campaignIDs = ArrayUtils.toPrimitive(
                campaigns.stream().map(item -> item.getId()).toArray(Long[]::new));
        Arrays.sort(campaignIDs);
        api.userSteps.campaignSteps().campaignsUnarchive(campaignIDs[0]);
        campaignIDs = ArrayUtils.remove(campaignIDs, 0);
        if (campaignIDs.length > 0) {
            api.userSteps.campaignSteps().campaignsDelete(ArrayUtils.toObject(campaignIDs));
        }
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5945")
    public void selfClientNoRightInvoiceForDraftCampaigns() {
        api.as(selfClient).userSteps.financeSteps()
                .shouldGetErrorsOnAMInvoice(selfAccount.getAccountID(), minInvoiceAmount.floatValue(), Currency.RUB,
                        new AxisError(354,
                                AxisErrorDetails.UNABLE_TO_PAY_ACCOUNT, selfAccount.getAccountID()));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5946")
    public void selfClientNoRightInvoiceForArchiveCampaigns() {
        List<CampaignGetItem> campaigns = api.as(selfClient).userSteps.campaignSteps().getCampaigns(selfClient);
        Long[] campaignIDs = campaigns.stream().map(item -> item.getId()).toArray(Long[]::new);
        api.userSteps.campaignSteps().campaignsSuspend(campaignIDs);
        api.userSteps.campaignSteps().campaignsArchive(campaignIDs);
        api.as(selfClient).userSteps.financeSteps()
                .shouldGetErrorsOnAMInvoice(selfAccount.getAccountID(), minInvoiceAmount.floatValue(), Currency.RUB,
                        new AxisError(354,
                                AxisErrorDetails.UNABLE_TO_PAY_ACCOUNT, selfAccount.getAccountID()));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5947")
    public void selfClientNoRightDepositForDraftCampaigns() {
        api.as(selfClient).userSteps.financeSteps()
                .shouldGetErrorsOnAMDeposit(
                        new PaymentMap[]{
                                new PaymentMap(api.type())
                                        .withCurrency(Currency.RUB)
                                        .withAmount(minInvoiceAmount.floatValue())
                                        .withAccountID(selfAccount.getAccountID())
                                        .withOrigin(PayMethod.OVERDRAFT)},
                        new AxisError(354,
                                AxisErrorDetails.UNABLE_TO_PAY_ACCOUNT, selfAccount.getAccountID()));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5948")
    public void selfClientNoRightDepositForArchiveCampaigns() {
        List<CampaignGetItem> campaigns = api.as(selfClient).userSteps.campaignSteps().getCampaigns(selfClient);
        Long[] campaignIDs = campaigns.stream().map(item -> item.getId()).toArray(Long[]::new);
        api.userSteps.campaignSteps().campaignsSuspend(campaignIDs);
        api.userSteps.campaignSteps().campaignsArchive(campaignIDs);
        api.as(selfClient).userSteps.financeSteps()
                .shouldGetErrorsOnAMDeposit(
                        new PaymentMap[]{
                                new PaymentMap(api.type())
                                        .withCurrency(Currency.RUB)
                                        .withAmount(minInvoiceAmount.floatValue())
                                        .withAccountID(selfAccount.getAccountID())
                                        .withOrigin(PayMethod.OVERDRAFT)},
                        new AxisError(354,
                                AxisErrorDetails.UNABLE_TO_PAY_ACCOUNT, selfAccount.getAccountID()));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5949")
    public void agencyHasRightInvoiceForDraftCampaigns() {
        log.info("Оплата агентством счет, к которому привязаны только черновики");
        String requestID = api.as(agencyLogin).userSteps.financeSteps()
                .getInvoiceRequestID(subClientAccount.getAccountID(), minInvoiceAmount.floatValue(), Currency.RUB);
        assertThat("Не выставлен счет", requestID, greaterThan("0"));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5950")
    public void agencyHasRightCreateInvoiceForDraftCampaign() {
        api.as(agencyLogin);
        long campaignID = api.userSteps.addDraftCampaign(subClientAccount.getLogin());

        String requestID = api.userSteps.financeSteps().getRequestID(
                new PayCampElementMap(api.type())
                        .withCampaignID(campaignID)
                        .withCurrency(Currency.RUB)
                        .withSum(minInvoiceAmount.floatValue())
        );

        assertThat("Не выставлен счет", requestID, greaterThan("0"));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5951")
    public void agencyCreateInvoiceForDeletedCampaign() {
        api.as(agencyLogin).clientLogin(subClientAccount.getLogin());
        long campaignID = api.userSteps.addDraftCampaign(subClientAccount.getLogin());
        api.userSteps.campaignSteps().campaignsDelete(campaignID);
        api.userSteps.financeSteps().shouldGetErrorOnCreateInvoice(
                new AxisError(1),
                new PayCampElementMap(api.type())
                        .withCampaignID(campaignID)
                        .withCurrency(Currency.RUB)
                        .withSum(400f)
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5952")
    public void agencyCreateInvoiceForArchivedCampaign() {
        api.as(agencyLogin).clientLogin(subClientAccount.getLogin());
        long campaignID = api.userSteps.addDraftCampaign();
        api.userSteps.campaignSteps().campaignsSuspend(campaignID);
        api.userSteps.campaignSteps().campaignsArchive(campaignID);
        String requestID = api.userSteps.financeSteps().getRequestID(
                new PayCampElementMap(api.type())
                        .withCampaignID(campaignID)
                        .withCurrency(Currency.RUB)
                        .withSum(minInvoiceAmount.floatValue())
        );
        assertThat("Не выставлен счет", requestID, greaterThan("0"));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5953")
    public void clientCreateInvoiceForDraftCampaign() {
        api.as(selfClient);
        Long campaignID = api.userSteps.campaignSteps().getCampaigns(selfClient).get(0).getId();
        api.userSteps.financeSteps().shouldGetErrorOnCreateInvoice(
                new AxisError(354,
                        AxisErrorDetails.UNABLE_TO_PAY_ACCOUNT, selfAccount.getAccountID()),
                new PayCampElementMap(api.type())
                        .withCurrency(Currency.RUB)
                        .withCampaignID(campaignID)
                        .withSum(400f)
        );
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5954")
    public void clientCreateInvoiceForArchivedCampaign() {
        api.as(selfClient);
        Long campaignID = api.userSteps.campaignSteps().getCampaigns(selfClient).get(0).getId();
        api.userSteps.campaignSteps().campaignsSuspend(campaignID);
        api.userSteps.campaignSteps().campaignsArchive(campaignID);
        api.userSteps.financeSteps().shouldGetErrorOnCreateInvoice(
                new AxisError(354,
                        AxisErrorDetails.UNABLE_TO_PAY_ACCOUNT, selfAccount.getAccountID()),
                new PayCampElementMap(api.type())
                        .withCurrency(Currency.RUB)
                        .withCampaignID(campaignID)
                        .withSum(400f)
        );
    }


    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5955")
    public void clientCreateInvoiceForDraftIfModeratedExists() {
        api.as(selfClient);
        long campaignID = api.userSteps.campaignSteps().getCampaigns(selfClient).get(0).getId();
        api.userSteps.addModeratedCampaign(selfClient);
        String requestID = api.userSteps.financeSteps().getRequestID(
                new PayCampElementMap(api.type())
                        .withCampaignID(campaignID)
                        .withCurrency(Currency.RUB)
                        .withSum(minInvoiceAmount.floatValue())
        );
        assertThat("Не выставлен счет", requestID, greaterThan("0"));
    }
}
