package ru.yandex.autotests.direct.integration.steps;

import org.apache.commons.httpclient.HttpClientError;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.message.BasicNameValuePair;
import ru.yandex.autotests.direct.httpclient.steps.HttpLogSteps;
import ru.yandex.autotests.direct.integration.data.yabs.audit.AuditBannerBean;
import ru.yandex.autotests.direct.integration.data.yabs.audit.AuditOrderResponse;
import ru.yandex.autotests.direct.integration.data.yabs.audit.AuditPhraseBean;
import ru.yandex.autotests.direct.integration.data.yabs.audit.AuditRetargetingBean;
import ru.yandex.autotests.direct.integration.data.yabs.page.PageBannerBean;
import ru.yandex.autotests.direct.integration.data.yabs.page.PageResponse;
import ru.yandex.autotests.direct.integration.httpclient.BsServerRequest;
import ru.yandex.autotests.direct.integration.httpclient.BsServerResponse;
import ru.yandex.autotests.direct.integration.httpclient.BsServerResponseHandler;
import ru.yandex.autotests.direct.utils.config.DirectTestRunProperties;
import ru.yandex.autotests.httpclient.lite.core.BackEndRequestBuilder;
import ru.yandex.autotests.httpclient.lite.core.config.HttpClientConnectionConfig;
import ru.yandex.autotests.httpclient.lite.core.config.HttpStepsConfig;
import ru.yandex.autotests.httpclient.lite.core.exceptions.BackEndClientException;
import ru.yandex.autotests.httpclient.lite.core.steps.BackEndBaseSteps;
import ru.yandex.autotests.irt.testutils.allure.LogSteps;
import ru.yandex.qatools.allure.annotations.Step;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.CoreMatchers.equalTo;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;

/**
 * Created by pashkus on 22.12.15.
 */
public class YabsServerSteps extends BackEndBaseSteps {
    protected final DirectTestRunProperties properties = DirectTestRunProperties.getInstance();
    protected LogSteps log = LogSteps.getLogger(this.getClass());
    protected HttpClientConnectionConfig clientConfig;

    //path to request
    public enum RequestPath {
        AUDIT("audit"),
        PAGE("page"),
        CODE("code");
        public final String param;
        RequestPath(String param) {
            this.param = param;
        }
        @Override
        public String toString(){
            return this.param;
        }
    }

    //Defines pageNo for requests: "http://hostname/page/<pageNo>" or "http://hostname/code/<pageNo>"
    public enum PageNumber {
        STANDARD_WO_YANDEX_SPLITTER ("3932"), //without yandex-splitter (not using now)
        TEST_DEFAULT("3933"),                 //without yandex-splitter + non production json document
        TEST_ALL_BANNERS("3934"),             //page with All Banners
        TEST_FLAT("3935");                    // page for adv network (TargetType=3)
        public final String pageNo;
        PageNumber(String pageNo) { this.pageNo = pageNo; }
        @Override
        public String toString(){
            return this.pageNo;
        }
    }

    //object type to request
    public enum AuditParams {
        ORDER("order-id"),
        BANNER("banner-id");
        public final String param;
        AuditParams(String param) {
            this.param = param;
        }
        @Override
        public String toString(){
            return this.param;
        }
    }

    public YabsServerSteps(String baseHost){
        String host = baseHost == null ? properties.getYabsAuditHost() : baseHost;

        clientConfig = new HttpClientConnectionConfig();
        clientConfig.scheme("http");
        clientConfig.host(host);
        clientConfig.port(properties.getYabsAuditPort());
        clientConfig.timeout(5000);
    }
    public YabsServerSteps(){
        this(null);
    }

    public HttpLogSteps onHttpLogSteps() {
        return getInstance(HttpLogSteps.class, config);
    }

    protected BackEndRequestBuilder getRequestBuilder() {
        return  config.getRequestBuilder();
    }

    public BsServerResponse execute(HttpUriRequest method) {
        try {
            BsServerResponse response = (BsServerResponse) config.getHttpClient().execute(method, config.getHandler());
            onHttpLogSteps().logContext(method, response);
            return response;
        } catch (IOException e) {
            throw new BackEndClientException("Ошибка выполнения запроса", e);
        }
    }

    public BsServerResponse execute(String url) {
        HttpGet httpget;
        try {
            httpget = new HttpGet(new URIBuilder(url).build());
        } catch (URISyntaxException e) {
            throw new HttpClientError("Ошибка преобразования строки '" + url + "' в URI");
        }
        return execute(httpget);
    }

    /* BsServer page/code request params:
        page/<page-id>?
        pageId:  2, 20(all)
        text: String
        reg-id: Integer
        block-origin: 1|0
        directpic = 1|0 - отдавать ли картиночные баннеры
        charset=utf8
        dump-match=1|0 - дебажный вывод кластеризации
   */

    private void initDefaultConfig() {
        init(new HttpStepsConfig()
                .useClientConfig(clientConfig)
                .useHandler(new BsServerResponseHandler())
                .useRequestBuilder(new BackEndRequestBuilder(clientConfig)));
    }

    @Step("Делаем запрос выдачу движка: pageId={1}, keyword={2}, region={3}")
    public BsServerResponse sendYabsServerRequest( RequestPath path, PageNumber pageId,
                                                   String phraseText, Integer regionId,  Boolean showPicBanners ) {
        BsServerRequest request = new BsServerRequest()
                .withRequestType(path, pageId)
                .withText(phraseText)
                .withRegId(regionId);

        if (showPicBanners){ request.withDirectPic(showPicBanners); }
        return sendYabsServerRequest( request );
    }

    public BsServerResponse sendYabsServerRequest( BsServerRequest request  ) {
        clientConfig.path(request.getRequestPath());
        initDefaultConfig();

        HttpGet get = getRequestBuilder().get(request.getRequestParams());
        get.addHeader("Host", properties.getYabsAuditHeaderHost());
        log.info("Send request: " + get.toString());
        BsServerResponse resp = execute(get);
        log.info("BsServer response: " + resp.getResponseContent().toString());
        return resp;
    }

    @Step("Делаем запрос в аудит движка")
    public BsServerResponse sendYabsServerAuditRequestFor(AuditParams paramType, Long objId) {
        clientConfig.path("/" + RequestPath.AUDIT.toString() + "/" + paramType.toString() );
        initDefaultConfig();

        List<NameValuePair> reqParams = new ArrayList<>();
        reqParams.add(new BasicNameValuePair(paramType.toString(), objId.toString()));
        HttpGet get =  getRequestBuilder().get(reqParams);
        get.addHeader("Host", properties.getYabsAuditHeaderHost());
        log.info("Send audit request: " + get.toString());
        BsServerResponse resp = execute(get);
        log.info("Audit response: " + resp.getResponseContent().toString());
        return resp;
    }

    public List<PageBannerBean> getPagePremiumBlock(String keyword, int regId) {
        return sendYabsServerRequest(RequestPath.CODE, PageNumber.TEST_DEFAULT, keyword, regId, false ).asYabsPageBeans().getPremium();
    }

    public List<PageBannerBean> getPageHalfPremiumBlock(String keyword, int regId) {
        return sendYabsServerRequest(RequestPath.CODE, PageNumber.TEST_DEFAULT, keyword, regId, false ).asYabsPageBeans().getHalfPremium();
    }

    public PageResponse getPageResponse(String keyword, int regId) {
        return sendYabsServerRequest(RequestPath.CODE, PageNumber.TEST_DEFAULT, keyword, regId, false ).asYabsPageBeans();
    }

    //Запросы в ручку /audit
    public AuditOrderResponse getAuditBeansForBannerId(long bannerId) {
        BsServerResponse response = sendYabsServerAuditRequestFor(AuditParams.BANNER, bannerId);
        return response.asAuditBeans();
    }

    public AuditOrderResponse getAuditBeansForOrderId(Long orderId){
        BsServerResponse response = sendYabsServerAuditRequestFor(AuditParams.ORDER, orderId);
        return response.asAuditBeans();
    }

    public AuditOrderResponse getOrder( Long orderId ) {
        return getAuditBeansForOrderId(orderId);
    }

    public AuditBannerBean getBanner( Long bannerId ) {
        List<AuditBannerBean> auditBanners = new ArrayList<>();

        auditBanners = getAuditBeansForBannerId(bannerId).getBanners();
        assumeThat("ответ аудита содержит один баннер", auditBanners.size(), equalTo(1));
        return auditBanners.get(0);
    }

    // Делает запрос в аудит и ищет в ответе указанный баннер
    public List<AuditBannerBean> getBanners(int bannerId) {
        return getAuditBeansForBannerId(bannerId).getBanners();
    }

    public AuditPhraseBean getPhrase(long bannerId, long phraseId) {
        return getBanner(bannerId).getPhrase(phraseId);
    }

    public List<AuditPhraseBean> getPhrases(long bannerId) {
        AuditPhraseBean retPhrases = null;
        return getBanner(bannerId).getPhrases();
    }

    public AuditRetargetingBean getRetargeting(long bannerId, int goalContextId){
        return getBanner(bannerId).getRetargeting((long) goalContextId);
    }
}
