package ru.yandex.autotests.direct.web.pages.statistic;


import java.util.Date;
import java.util.List;
import java.util.function.Predicate;

import org.hamcrest.Matcher;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

import ru.yandex.autotests.direct.web.data.SelectInputMethod;
import ru.yandex.autotests.direct.web.data.statistic.NewReportFilterInfoWeb;
import ru.yandex.autotests.direct.web.data.statistic.NewReportInfoWeb;
import ru.yandex.autotests.direct.web.data.statistic.StatisticType;
import ru.yandex.autotests.direct.web.objects.banners.BannerPhraseInfoWeb;
import ru.yandex.autotests.direct.web.objects.statistic.StatisticMinusPhraseInfoWeb;
import ru.yandex.autotests.direct.web.pages.statistic.blocks.StatisticSearchQueriesRowBlock;
import ru.yandex.autotests.direct.web.pages.statistic.blocks.StatisticsAddMinusPhrasesPopup;
import ru.yandex.autotests.direct.web.pages.statistic.blocks.StatisticsAddPhrasePopup;
import ru.yandex.autotests.direct.web.pages.statistic.blocks.StatisticsWizardBannerPreviewPopup;
import ru.yandex.autotests.direct.web.util.DirectWebError;
import ru.yandex.autotests.direct.web.util.WebDriverUtils;
import ru.yandex.autotests.direct.web.webelements.bem.CalendarInputBEM;
import ru.yandex.autotests.direct.web.webelements.bem.CheckBoxBEM;
import ru.yandex.autotests.direct.web.webelements.bem.SelectBEM;
import ru.yandex.qatools.allure.webdriver.annotations.NamedUrl;
import ru.yandex.qatools.allure.webdriver.annotations.NamedUrls;
import ru.yandex.qatools.allure.webdriver.pages.BasePageObject;
import ru.yandex.qatools.htmlelements.annotations.Name;
import ru.yandex.qatools.htmlelements.element.Button;
import ru.yandex.qatools.htmlelements.element.Link;
import ru.yandex.qatools.htmlelements.element.TextInput;
import ru.yandex.qatools.htmlelements.matchers.WebElementMatchers;

import static java.util.stream.Collectors.toList;
import static org.apache.commons.lang3.StringUtils.join;
import static org.hamcrest.MatcherAssert.assertThat;
import static ru.yandex.autotests.direct.web.steps.BackendSteps.toBoolean;
import static ru.yandex.autotests.direct.web.util.WebElementsActions.fillSelect;
import static ru.yandex.autotests.direct.web.util.WebElementsActions.fillTextInput;
import static ru.yandex.autotests.direct.web.util.WebElementsActions.getVisibleElement;
import static ru.yandex.autotests.direct.web.util.WebElementsActions.setCheckboxState;

/**
 * @author Roman Kuhta (kuhtich@yandex-team.ru)
 */
@NamedUrls({
        @NamedUrl(name = "campaign.stat", url = "/registered/main.pl?cmd=showCampStat&cid={1}&interface=std"),
        @NamedUrl(name = "campaign.stat.for.login",
                url = "/registered/main.pl?cmd=showCampStat&cid={1}&ulogin={2}&interface=std"),
        @NamedUrl(name = "campaign.stat.light", url = "cmd=showCampStat&detail=Yes&cid={1}" +
                "&showCampStat=cmd&types=days&target_all=1"),
        @NamedUrl(name = "campaign.stat.light.for.login", url = "/registered/main.pl?c" +
                "md=showCampStat&detail=Yes&cid={1}&ulogin={2}&showCampStat=cmd&types=days&target_all=1"),
        @NamedUrl(name = "campaign.stat.with.params", url = "/registered/main.pl?cmd=showCampStat&cid={1}&{2}"),
        @NamedUrl(name = "all.campaigns.stat.for.login",
                url = "/registered/main.pl?cmd=showCampStat&ulogin={1}&stat_type=campdate"),
        @NamedUrl(name = "wizard.for.campaign.and.login",
                url = "/registered/main.pl?cmd=showCampStat&cid={1}&ulogin={2}&stat_type=custom&target_all=1")
})
public class ShowCampStatPage extends BasePageObject {


    @Name("Табы типов статистики")
    @FindBy(xpath = ".//div[contains(@class,'p-campaign-stat__tabs')]//li[contains(@class,'tabs-menu__tab')]/a")
    private List<Link> statisticTabs;

    @Name("Табы типов статистики по всем кампаниям")
    @FindBy(css = "div.p-campaign-stat__tabs .link")
    private List<Link> statisticAllCampaignsTabs;

    @Name("Статистика с")
    @FindBy(css = "span.b-date-range-picker__start")
    private CalendarInputBEM dateFrom;

    @Name("Статистика по")
    @FindBy(css = "span.b-date-range-picker__finish")
    private CalendarInputBEM dateTo;

    @Name("Включить группировку по дням")
    @FindBy(id = "group_by_date")
    private CheckBoxBEM groupByDate;

    @Name("Группировка")
    @FindBy(name = "group")
    private SelectBEM filterGroup;

    @Name("Данные по цели")
    @FindBy(name = "goals")
    private SelectBEM goalData;

    @Name("Площадки всего")
    @FindBy(id = "target_all")
    private CheckBoxBEM sitesTotal;

    @Name("На поиске")
    @FindBy(id = "target_0")
    private CheckBoxBEM sitesSearch;

    @Name("На тематических площадках")
    @FindBy(id = "target_1")
    private CheckBoxBEM sitesContext;

    @Name("НДС")
    @FindBy(id = "with_nds")
    private CheckBoxBEM vat;

    @Name("Детальная статистика по объявлениям")
    @FindBy(id = "show_banners_stat")
    private CheckBoxBEM showBannerStatInDetail;

    @Name("Отображать в виде сквозного списка")
    @FindBy(name = "through_list")
    private CheckBoxBEM showAsList;

    @Name("Площадки")
    @FindBy(name = "target_type")
    private SelectBEM sites;

    @Name("Чекбокс 'Подробно'")
    @FindBy(name = "use_page_id")
    private CheckBoxBEM showUsePageId;

    @Name("Показать строк на странице ")
    @FindBy(id = "onpage")
    private SelectBEM linesPerPage;

    @Name("Метки")
    @FindBy(id = "group_by_tag")
    private CheckBoxBEM groupByTag;

    @Name("Фильтр меток")
    @FindBy(name = "filter_tag")
    private TextInput filterTag;

    @Name("Группы")
    @FindBy(id = "group_by_adgroup")
    private CheckBoxBEM groupByADGroup;

    @Name("Фильтр групп")
    @FindBy(name = "filter_adgroup")
    private TextInput filterADGroup;

    @Name("Баннеры")
    @FindBy(id = "group_by_banner")
    private CheckBoxBEM groupByBanner;

    @Name("Фильтр баннеров")
    @FindBy(name = "filter_banner")
    private TextInput filterBanner;

    @Name("Площадки")
    @FindBy(id = "group_by_page")
    private CheckBoxBEM groupByPage;

    @Name("Фильтр площадок")
    @FindBy(name = "filter_page")
    private TextInput filterPage;

    @Name("Выбор площадки")
    @FindBy(name = "filter_page_target")
    private SelectBEM filterPageTarget;

    @Name("Подробно")
    @FindBy(name = "use_page_id")
    private CheckBoxBEM filterPageInDetail;

    @Name("Фразы")
    @FindBy(id = "group_by_phrase")
    private CheckBoxBEM groupByPhrase;

    @Name("Фльтр фраз")
    @FindBy(name = "filter_phrase")
    private TextInput filterPhrase;

    @Name("Условия ретаргетинга")
    @FindBy(id = "group_by_retargeting")
    private CheckBoxBEM groupByRetargeting;

    @Name("Фильтр условий ретаргетинга")
    @FindBy(name = "filter_retargeting")
    private TextInput filterRetargeting;

    @Name("Регионы")
    @FindBy(id = "group_by_geo")
    private CheckBoxBEM groupByGeo;

    @Name("Фильтр регионов")
    @FindBy(name = "filter_geo")
    private TextInput filterGeo;

    @Name("Позиция")
    @FindBy(id = "group_by_position")
    private CheckBoxBEM groupByPosition;

    @Name("Выбор позиции")
    @FindBy(id = "filter_position")
    private SelectBEM filterPosition;

    @Name("Изображение")
    @FindBy(id = "group_by_image")
    private CheckBoxBEM groupByImage;

    @Name("Выбор фильтра по изображению")
    @FindBy(id = "filter_image")
    private SelectBEM filterImage;

    @Name("Показать")
    @FindBy(css = ".b-statistics-form__submit-button")
    private Button show;

    @Name("Показать дополнительные настройки")
    @FindBy(css = ".b-statistics-form__show-button")
    private WebElement showAdditionalParameters;

    @Name("Список строк для статистики по поисковым запросам")
    List<StatisticSearchQueriesRowBlock> statisticSearchQueriesRows;

    @Name("Попап добавления фраз")
    private StatisticsAddPhrasePopup addPhrasePopup;

    @Name("Попап добавления минус-фраз")
    private StatisticsAddMinusPhrasesPopup addMinusWordPopup;

    @Name("Показать график")
    @FindBy(css = ".b-charts-manager__switcher")
    private Button showPlotButton;

    @Name("Чек-бокс добавления всех Поисковых запросов")
    @FindBy(xpath = ".//div[contains(@class, 'b-stat-table__head')]/span//input")
    private List<CheckBoxBEM> allSearchQueriesCheckBox;

    @Name("Список ссылок на баннеры для статистики по мастеру отчетов")
    @FindBy(xpath = ".//a[contains(@class, 'b-stat-banner-preview__banner')]")
    private List<Link> statisticsWizardBannerLinks;

    private StatisticsWizardBannerPreviewPopup statisticsWizardBannerPreviewPopup;

    @Name("график по статистке")
    @FindBy(css = ".b-charts-manager__chart")
    private WebElement chartStatisticsBlock;

    @Name("Добавить в ключевые фразы")
    @FindBy(css = ".p-campaign-stat__add-plus-phrases")
    private WebElement addPlusPhraseButton;

    @Name("Добавить в минус-фразы")
    @FindBy(css = ".p-campaign-stat__add-minus-phrases")
    private WebElement addMinusWordButton;

    private Link getTab(StatisticType statisticType) {
        for (Link statisticTab : statisticTabs) {
            if (statisticTab.getReference().contains(statisticType.getLinkPart())) {
                return statisticTab;
            }
        }
        throw new DirectWebError("Таб не найден: " + statisticType.toString());
    }

    private Link getTabAllCampaigns(StatisticType statisticType) {
        for (Link statisticAllCampaignsTab : statisticAllCampaignsTabs) {
            System.out.println("class=" + statisticAllCampaignsTab.getWrappedElement().getAttribute("class"));
            System.out.println("text=" + statisticAllCampaignsTab.getText());
            System.out.println("href=" + statisticAllCampaignsTab.getReference());
            if (statisticAllCampaignsTab.getReference().contains(statisticType.getLinkPart())) {
                return statisticAllCampaignsTab;
            }
        }
        throw new DirectWebError("Таб не найден: " + statisticType.toString());
    }

    public void clickTab(StatisticType type) {
        getTab(type).click();
    }

    public void clickAllCampaignsTab(StatisticType type) {
        getTabAllCampaigns(type).click();
    }

    public void clickShow() {
        show.click();
    }

    public StatisticsAddPhrasePopup onAddPhrasePopup() {
        addPhrasePopup.setConfig(config);
        return addPhrasePopup;
    }

    public StatisticsAddMinusPhrasesPopup onAddMinusPhrasePopup() {
        addMinusWordPopup.setConfig(config);
        return addMinusWordPopup;
    }

    public void clickSavePhrasesButtonInPopup() {
        onAddPhrasePopup().clickSave();
    }

    public void clickAddPlusPhraseButton() {
        addPlusPhraseButton.click();
    }

    public void setCheckBoxForAllSearchQueries(Boolean isSelected) {
        getAllSearchQueriesCheckBox().set(isSelected);
    }

    public void clickAddMinusPhraseButton() {
        addMinusWordButton.click();
    }

    public void fillStatisticRequestInfo(NewReportInfoWeb info) {
        if (WebElementMatchers.isDisplayed().matches(showAdditionalParameters)) {
            showAdditionalParameters.click();
        }
        fillDateFrom(info.getStartDate());
        fillDateTo(info.getEndDate());
        fillSelect(filterGroup, info.getGroupByDate(), SelectInputMethod.BY_VALUE);
        fillSelect(goalData, info.getGoal(), SelectInputMethod.BY_VALUE);
        setCheckboxState(sitesTotal, info.getSitesTotal());
        setCheckboxState(sitesSearch, info.getSitesSearch());
        setCheckboxState(sitesContext, info.getSitesContext());
        fillSelect(sites, info.getSites(), SelectInputMethod.BY_VALUE);
        setCheckboxState(vat, toBoolean(info.getIncludeVat()));
        setCheckboxState(showUsePageId, info.getShowUsePageId());
        setCheckboxState(showBannerStatInDetail, info.getShowBannerStatInDetail());
        setCheckboxState(showAsList, info.getShowAsList());
        fillSelect(linesPerPage, info.getLinesPerPage(), SelectInputMethod.BY_VALUE);
        fillFilterParameters(info.getNewReportFilterInfoWeb());
    }

    private void fillDateFrom(Date date) {
        if (date == null) {
            return;
        }
        dateFrom.fillDate(date);
    }

    private void fillDateTo(Date date) {
        if (date == null) {
            return;
        }
        dateTo.fillDate(date);
    }

    private void fillFilterParameters(NewReportFilterInfoWeb filter) {
        if (filter == null) {
            return;
        }
        fillFilter(groupByTag, filterTag, filter.getTags());
        fillFilter(groupByADGroup, filterADGroup, filter.getAdGroups());
        fillFilter(groupByBanner, filterBanner, filter.getBanner());
        if (filter.getPageName() != null) {
            fillFilter(groupByPage, filterPage, filter.getPageName());
            fillSelect(filterPageTarget, filter.getPageType(), SelectInputMethod.BY_VALUE);
            setCheckboxState(filterPageInDetail, filter.getSitesInDetail());
        }
        fillFilter(groupByPhrase, filterPhrase, filter.getPhrase());
        fillFilter(groupByRetargeting, filterRetargeting, filter.getStatGoals());
        fillFilter(groupByGeo, filterGeo, filter.getGeo());
        if (filter.getPositionType() != null) {
            groupByPosition.select();
            fillSelect(filterPosition, filter.getPositionType(), SelectInputMethod.BY_VALUE);
        } else {
            groupByPosition.deselect();
        }
        if (filter.getWithImage() != null) {
            groupByImage.select();
            fillSelect(filterImage, filter.getWithImage(), SelectInputMethod.BY_VALUE);
        } else {
            groupByImage.deselect();
        }
        if (filter.getGroupByDate() != null) {
            groupByDate.select();
            fillSelect(filterGroup, filter.getGroupByDate(), SelectInputMethod.BY_VALUE);
        } else {
            groupByDate.deselect();
        }
    }

    private void fillFilter(CheckBoxBEM checkBox, TextInput filterInput, List values) {
        if (values == null) {
            return;
        }
        if (values.size() > 0) {
            checkBox.select();
            fillTextInput(filterInput, join(values, ","));
        } else {
            checkBox.deselect();
        }
    }

    public void clickOnShowPlotButton() {
        showPlotButton.click();
    }

    public void checkChartStatisticsBlock(Matcher<WebElement> matcher) {
        assertThat("блок График по статистики", chartStatisticsBlock, matcher);
    }

    private Link getStatisticsWizardBannerLink(Long bannerId) {
        for (Link bannerLink : statisticsWizardBannerLinks) {
            if (bannerLink.getText().contains(bannerId.toString())) {
                return bannerLink;
            }
        }
        return null;
    }

    public void clickOnStatisticsWizardBannerLink(Long bannerId) {
        Link bannerLink = getStatisticsWizardBannerLink(bannerId);
        if (bannerLink == null) {
            throw new DirectWebError("Не найден баннер " + bannerId);
        } else {
            bannerLink.click();
        }
    }

    public void openImagePopupOnStatisticsWizardTab() {
        statisticsWizardBannerPreviewPopup.clickOnOpenImagePopup();
    }

    public List<BannerPhraseInfoWeb> getRowFromSearchQueries() {
        return statisticSearchQueriesRows.stream()
                .map(StatisticSearchQueriesRowBlock::getBean).collect(toList());
    }


    public void setCheckboxForPhrase(Predicate<BannerPhraseInfoWeb> predicate, Boolean state) {
        setFloaterVisibility(WebElementVisibilityState.HIDDEN);
        statisticSearchQueriesRows.stream()
                .filter(x -> predicate.test(x.getBean()))
                .forEach(x -> x.setCheckbox(state));
        setFloaterVisibility(WebElementVisibilityState.VISIBLE);
    }

    private void setFloaterVisibility(WebElementVisibilityState state) {
        for (WebElement webElement : config.getDriver().findElements(By.cssSelector(".b-floater__content"))) {
            WebDriverUtils.setElementVisibility(config.getDriver(), webElement, state);
        }
    }

    public void fillPhraseParameters(List<BannerPhraseInfoWeb> phraseInfoList) {
        onAddPhrasePopup().fillPhraseParameters(phraseInfoList);
        takeScreenshot();
        onAddPhrasePopup().clickSave();
    }

    public void fillMinusPhraseParameters(List<StatisticMinusPhraseInfoWeb> minusPhraseInfoList) {
        onAddMinusPhrasePopup().fillMinusPhraseParameters(minusPhraseInfoList);
    }

    private CheckBoxBEM getAllSearchQueriesCheckBox() {
        return getVisibleElement(allSearchQueriesCheckBox);
    }
}
