package ru.yandex.autotests.directapi.agencyclients.add;

import com.yandex.direct.api.v5.agencyclients.AddResponse;
import com.yandex.direct.api.v5.general.YesNoEnum;
import com.yandex.direct.api.v5.generalclients.ClientSettingAddEnum;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;

import ru.yandex.aqua.annotations.project.Aqua;
import ru.yandex.autotests.direct.db.models.jooq.ppc.tables.records.ClientsOptionsRecord;
import ru.yandex.autotests.direct.db.models.jooq.ppc.tables.records.UsersRecord;
import ru.yandex.autotests.direct.db.steps.UsersSteps;
import ru.yandex.autotests.direct.db.steps.base.DirectDbStepsException;
import ru.yandex.autotests.directapi.agencyclients.AgencyClientsFeatures;
import ru.yandex.autotests.directapi.agencyclients.AgencyClientsLogins;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.apiclient.errors.Api5Error;
import ru.yandex.autotests.directapi.apiclient.errors.Api5ErrorDetails;
import ru.yandex.autotests.directapi.model.api5.agencyclients.AddRequestMap;
import ru.yandex.autotests.directapi.model.api5.generalclients.ClientSettingAddItemMap;
import ru.yandex.autotests.directapi.model.api5.generalclients.NotificationAddMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.not;
import static org.junit.Assume.assumeFalse;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;

@Aqua.Test
@Features(AgencyClientsFeatures.ADD)
@Description("Проверка успешного добавления")
public class SuccessAddTest {
    private static final String AGENCY_LOGIN = AgencyClientsLogins.AGENCY_RUB;
    private static final String SUBCLIENT_LOGIN_BASE = "at-agency-clients-test";
    private static final String CREATE_WITHOUT_WALLET = "create_without_wallet";

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

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

    @BeforeClass
    public static void initTest() {
        api.userSteps.clientFakeSteps().enableToCreateSubClients(AGENCY_LOGIN);
    }

    @Test
    public void loginAndClientIdShouldBeReturnedOnSuccessAdd() {
        String login = AddRequestMap.generateLogin(SUBCLIENT_LOGIN_BASE);
        AddResponse response = api.userSteps.agencyClientsStepsV5().agencyClientsAdd(
                new AddRequestMap().withDefault(login)
        );
        assertThat("Ответ возвращается для логина из запроса", response, allOf(
                hasProperty("login", equalTo(login)),
                hasProperty("clientId", not(nullValue()))
        ));
    }

    @Test
    public void dbRecordOfUserShouldBeCreatedOnSuccessAdd() {
        String login = AddRequestMap.generateLogin(SUBCLIENT_LOGIN_BASE);
        boolean userAlreadyExist = true;
        try {
            api.userSteps.getDirectJooqDbSteps().useShardForLogin(login);
        } catch (DirectDbStepsException ex) {
            userAlreadyExist = false;
        }
        assumeFalse("Предполагается, что пользователя с таки логином нет в базе", userAlreadyExist);

        AddResponse response = api.userSteps.agencyClientsStepsV5().agencyClientsAdd(
                new AddRequestMap().withDefault(login)
        );
        UsersSteps usersSteps = api.userSteps.getDirectJooqDbSteps().useShardForLogin(login).usersSteps();
        UsersRecord usersRecord = usersSteps.getUser(login);
        assertThat("Созданный пользователь есть в базе",
                usersRecord, hasProperty("clientid", equalTo(response.getClientId())));
        assertThat("У созданного пользователя корректный email",
                usersRecord, hasProperty("email", equalTo(NotificationAddMap.DEFAULT_EMAIL)));
    }

    @Test
    public void agencyCanCreateCampaignForNewSubclient() {
        String login = AddRequestMap.generateLogin(SUBCLIENT_LOGIN_BASE);
        AddResponse response = api.userSteps.agencyClientsStepsV5()
                .agencyClientsAdd(new AddRequestMap().withDefault(login), AGENCY_LOGIN);
        assumeThat("Ответ возвращается для логина из запроса", response,
                hasProperty("login", equalTo(login)));

        Long campaign = api.userSteps.addActiveCampaign(login, 1);
        assertThat("Кампания создалась", campaign, notNullValue());
    }

    @Test
    public void agencyCanCreateSharedAccountForNewSubclientSmoke() {
        String login = AddRequestMap.generateLogin(SUBCLIENT_LOGIN_BASE);
        AddResponse response = api.userSteps.agencyClientsStepsV5()
                .agencyClientsAdd(new AddRequestMap().withDefault(login), AGENCY_LOGIN);
        assumeThat("Ответ возвращается для логина из запроса", response,
                hasProperty("login", equalTo(login)));
        Long campaign = api.userSteps.addActiveCampaign(login, 1);
        assumeThat("Кампания создалась", campaign, notNullValue());
        api.userSteps.financeSteps().enableAndGetSharedAccount(login);
    }
    @Test
    public void agencyCanCreateSubclientWithoutWallet() {
        String login = AddRequestMap.generateLogin(SUBCLIENT_LOGIN_BASE);
        ClientSettingAddItemMap settings = new ClientSettingAddItemMap(
                ClientSettingAddEnum.SHARED_ACCOUNT_ENABLED, YesNoEnum.NO );

        api.userSteps.agencyClientsStepsV5().setAgencyOptions(AGENCY_LOGIN,true, true);

        AddResponse response = api.userSteps.agencyClientsStepsV5()
                .agencyClientsAdd(new AddRequestMap().withDefault(login).withSettings(settings), AGENCY_LOGIN);
        Long clientId = response.getClientId();
        ClientsOptionsRecord clientOpt = api.userSteps.getDirectJooqDbSteps()
                .useShardForLogin(response.getLogin())
                .clientsOptionsSteps().getClientOptions(clientId);
        assertThat("Флаг выставлен", clientOpt.getClientFlags(),
                containsString(CREATE_WITHOUT_WALLET));
    }

    @Test
    public void agencyCanCreateSubclientWithoutWalletDefault() {
        String login = AddRequestMap.generateLogin(SUBCLIENT_LOGIN_BASE);

        api.userSteps.agencyClientsStepsV5().setAgencyOptions(AGENCY_LOGIN, true, false);

        AddResponse response = api.userSteps.agencyClientsStepsV5()
                .agencyClientsAdd(new AddRequestMap().withDefault(login), AGENCY_LOGIN);
        Long clientId = response.getClientId();
        ClientsOptionsRecord clientOpt = api.userSteps.getDirectJooqDbSteps()
                .useShardForLogin(response.getLogin())
                .clientsOptionsSteps().getClientOptions(clientId);
        assertThat("Флаг выставлен", clientOpt.getClientFlags(),
                containsString(CREATE_WITHOUT_WALLET));
    }

    @Test
    public void agencyCanCreateSubclientWithoutWalletOverrideDefault() {
        String login = AddRequestMap.generateLogin(SUBCLIENT_LOGIN_BASE);

        api.userSteps.agencyClientsStepsV5().setAgencyOptions(AGENCY_LOGIN, true, false);

        ClientSettingAddItemMap settings = new ClientSettingAddItemMap(
                ClientSettingAddEnum.SHARED_ACCOUNT_ENABLED, YesNoEnum.YES);
        AddResponse response = api.userSteps.agencyClientsStepsV5()
                .agencyClientsAdd(new AddRequestMap().withDefault(login).withSettings(settings), AGENCY_LOGIN);
        Long clientId = response.getClientId();
        ClientsOptionsRecord clientOpt = api.userSteps.getDirectJooqDbSteps()
                .useShardForLogin(response.getLogin())
                .clientsOptionsSteps().getClientOptions(clientId);
        assertThat("Флаг не выставлен", clientOpt.getClientFlags(),
                not(containsString(CREATE_WITHOUT_WALLET)));
    }

    @Test
    public void agencyCanNotCreateSubclientWithoutWallet() {
        String login = AddRequestMap.generateLogin(SUBCLIENT_LOGIN_BASE);
        ClientSettingAddItemMap settings = new ClientSettingAddItemMap(
                ClientSettingAddEnum.SHARED_ACCOUNT_ENABLED, YesNoEnum.NO);

        api.userSteps.agencyClientsStepsV5().setAgencyOptions(AGENCY_LOGIN, false, true);

        api.userSteps.agencyClientsStepsV5()
                .expectErrorOnAgencyClientsAdd(new AddRequestMap().withDefault(login).withSettings(settings),
                        new Api5Error(54, Api5ErrorDetails.NO_RIGHTS_TO_SHARED_ACCOUNT_ENABLED));
    }

}
