package ru.yandex.autotests.directapi.reports.currency;

import java.math.BigDecimal;
import java.math.RoundingMode;

import com.yandex.direct.api.v5.general.YesNoEnum;
import com.yandex.direct.api.v5.reports.DateRangeTypeEnum;
import com.yandex.direct.api.v5.reports.FieldEnum;
import com.yandex.direct.api.v5.reports.FormatEnum;
import com.yandex.direct.api.v5.reports.ReportTypeEnum;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;

import ru.yandex.aqua.annotations.project.Aqua;
import ru.yandex.autotests.direct.utils.money.Money;
import ru.yandex.autotests.directapi.darkside.Logins;
import ru.yandex.autotests.directapi.darkside.connection.Semaphore;
import ru.yandex.autotests.directapi.model.api5.reports.ReportDefinitionMap;
import ru.yandex.autotests.directapi.model.api5.reports.ReportsData;
import ru.yandex.autotests.directapi.model.api5.reports.ReportsLine;
import ru.yandex.autotests.directapi.model.api5.reports.SelectionCriteriaMap;
import ru.yandex.autotests.directapi.reports.ReportsFeatures;
import ru.yandex.autotests.directapi.reports.ReportsLogins;
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.allure.annotations.Issue;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;

/**
 * Created by pavryabov on 13.07.16.
 * https://st.yandex-team.ru/TESTIRT-9653
 */
@Aqua.Test
@Description("Проверка денежных полей для клиента, работающего в рублях")
@Issue("https://st.yandex-team.ru/DIRECT-54092")
@Features(ReportsFeatures.ONLINE_CUSTOM_REPORT)
public class CurrencyFieldsRubClientMoneyFieldsTest {

    private static final String CLIENT = ReportsLogins.CLIENT_RUB_WITH_STAT;
    private static final BigDecimal COST = BigDecimal.valueOf(2099.19);
    private static final BigDecimal REVENUE = new BigDecimal(7975);

    private static final FieldEnum[] FIELDS = new FieldEnum[]{
            FieldEnum.COST,
            FieldEnum.CLICKS,
            FieldEnum.CONVERSIONS,
            FieldEnum.AVG_CPC,
            FieldEnum.COST_PER_CONVERSION,
            FieldEnum.REVENUE,
            FieldEnum.PROFIT
    };

    @ClassRule
    public static ApiSteps api = new ApiSteps().as(Logins.LOGIN_SUPER).clientLogin(CLIENT);

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

    private static ReportsData reportsDataInCurrency;
    private static ReportsData reportsDataInMicros;
    private static ReportsLine reportLineInCurrency;
    private static ReportsLine reportLineInMicros;

    @BeforeClass
    public static void beforeClass() {
        ReportDefinitionMap reportDefinitionMap = new ReportDefinitionMap()
                .withFieldNames(FIELDS)
                .withDateRangeType(DateRangeTypeEnum.CUSTOM_DATE)
                .withUniqueReportName()
                .withReportType(ReportTypeEnum.CUSTOM_REPORT)
                .withFormat(FormatEnum.TSV)
                .withIncludeVAT(YesNoEnum.YES)
                .withIncludeDiscount(YesNoEnum.NO)
                .withSelectionCriteria(new SelectionCriteriaMap()
                        .withDateFrom("2020-04-01")
                        .withDateTo("2020-04-02"));
        reportsDataInCurrency = api.returnMoneyInMicros(false).userSteps.reportsSteps().callReportsXml(reportDefinitionMap);
        assumeThat("в отчете вернулась одна строка", reportsDataInCurrency.getReportsLines(), hasSize(1));
        reportsDataInMicros = api.returnMoneyInMicros(true).userSteps.reportsSteps().callReportsXml(reportDefinitionMap.withUniqueReportName());
        assumeThat("в отчете вернулась одна строка", reportsDataInMicros.getReportsLines(), hasSize(1));
        reportLineInCurrency = reportsDataInCurrency.getReportsLines().get(0);
        reportLineInMicros = reportsDataInMicros.getReportsLines().get(0);
    }

    @Test
    public void checkCostInRub() {
        assertThat("значение в поле Cost соответствует ожидаемому",
                reportLineInCurrency.getCost(), equalTo(COST.setScale(2)));
    }

    @Test
    public void checkAvgCpcInRub() {
        assertThat("значение в поле AvgCpc соответствует ожидаемому",
                reportLineInCurrency.getAvgCpc(),
                equalTo(reportLineInCurrency.getCost()
                        .divide(BigDecimal.valueOf(reportLineInCurrency.getClicks()), 2, RoundingMode.HALF_UP)));
    }

    @Test
    public void checkCostPerConversionInRub() {
        assertThat("значение в поле CostPerConversion соответствует ожидаемому",
                reportLineInCurrency.getCostPerConversion(),
                equalTo(reportLineInCurrency.getCost()
                        .divide(BigDecimal.valueOf(reportLineInCurrency.getConversions()), 2, RoundingMode.HALF_UP)));
    }

    @Test
    public void checkRevenueInRub() {
        assertThat("значение в поле Revenue соответствует ожидаемому",
                reportLineInCurrency.getRevenue(), equalTo(REVENUE.setScale(2)));
    }

    @Test
    public void checkCostInMicros() {
        assertThat("значение в поле Cost соответствует ожидаемому",
                reportLineInMicros.getCost(),
                equalTo(Money.valueOf(reportLineInCurrency.getCost()).bidLong().bigDecimalValue().setScale(0)));
    }

    @Test
    public void checkAvgCpcInMicros() {
        assertThat("значение в поле AvgCpc соответствует ожидаемому",
                reportLineInMicros.getAvgCpc(),
                equalTo(Money.valueOf(reportLineInCurrency.getAvgCpc()).bidLong().bigDecimalValue().setScale(0)));
    }

    @Test
    public void checkCostPerConversionInMicros() {
        assertThat("значение в поле CostPerConversion соответствует ожидаемому",
                reportLineInMicros.getCostPerConversion(),
                equalTo(Money.valueOf(reportLineInCurrency.getCostPerConversion()).bidLong().bigDecimalValue().setScale(0)));
    }

    @Test
    public void checkRevenueInMicros() {
        assertThat("значение в поле Revenue соответствует ожидаемому",
                reportLineInMicros.getRevenue(),
                equalTo(Money.valueOf(reportLineInCurrency.getRevenue()).bidLong().bigDecimalValue().setScale(0)));
    }
}
