package ru.yandex.webmaster3.core.addurl;

import com.google.common.base.Charsets;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.web.util.UriComponentsBuilder;
import ru.yandex.webmaster3.core.http.HttpConstants;
import ru.yandex.webmaster3.core.metrics.externals.AbstractExternalAPIService;
import ru.yandex.webmaster3.core.metrics.externals.ExternalDependencyMethod;
import ru.yandex.webmaster3.core.util.IdUtils;
import ru.yandex.webmaster3.core.util.JavaMethodWitness;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author Oleg Bazdyrev
 */
public class AddUrlSpamService extends AbstractExternalAPIService {

    private static final Logger log = LoggerFactory.getLogger(AddUrlSpamService.class);

    private String serviceSpamUrl;
    private String serviceRemoveSpamUrl;
    private CloseableHttpClient httpClient;

    private int socketTimeoutMs = 30000;
    private int connectTimeoutMs = HttpConstants.DEFAULT_CONNECT_TIMEOUT;

    public void init() {
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(socketTimeoutMs)
                .setConnectTimeout(connectTimeoutMs)
                .build();

        httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionTimeToLive(30, TimeUnit.SECONDS)
                .build();
    }

    public void destroy() {
        IOUtils.closeQuietly(httpClient);
    }

    @ExternalDependencyMethod("get-banned-owners")
    public List<Pair<String, DateTime>> getBannedOwners() throws RecrawlServiceException {
        return trackQuery(new JavaMethodWitness() {}, ALL_ERRORS_INTERNAL, () -> {
            URI uri = UriComponentsBuilder.fromUriString(serviceSpamUrl).build().toUri();
            HttpGet httpRequest = new HttpGet(uri);
            log.debug("List spam owners: {}", uri);
            try (CloseableHttpResponse httpResponse = httpClient.execute(httpRequest)) {
                int code = httpResponse.getStatusLine().getStatusCode();
                log.debug("List spam owners result: {}", code);
                if (code != HttpStatus.SC_ACCEPTED && code != HttpStatus.SC_OK) {
                    throw new RecrawlServiceException("Unable to get spam owners: status=" + code);
                }
                // парсим результаты
                String data = IOUtils.toString(httpResponse.getEntity().getContent(), Charsets.UTF_8);
                List<Pair<String, DateTime>> result = new ArrayList<>();
                String line;
                BufferedReader reader = new BufferedReader(new StringReader(data));
                while (reader.ready() && (line = reader.readLine()) != null) {
                    String[] parts = line.split(" ");
                    if (parts.length != 2) {
                        continue;
                    }
                    result.add(Pair.of(IdUtils.IDN.toASCII(parts[0]), new DateTime(Long.parseLong(parts[1]) * 1000L)));
                }
                return result;
            } catch (IOException e) {
                throw new RecrawlServiceException("Unable to get spam owners", e);
            }
        });
    }

    @ExternalDependencyMethod("unban-owner")
    public void unbanOwner(String owner) throws RecrawlServiceException {
        trackExecution(new JavaMethodWitness() {}, ALL_ERRORS_INTERNAL, () -> {
            URI uri = UriComponentsBuilder.fromUriString(serviceRemoveSpamUrl).queryParam("owner", owner).build().toUri();
            // TODO мб POST?
            HttpGet httpRequest = new HttpGet(uri);
            log.debug("Unban spam owner {}: {}", owner, uri);
            try (CloseableHttpResponse httpResponse = httpClient.execute(httpRequest)) {
                int code = httpResponse.getStatusLine().getStatusCode();
                log.debug("Unban spam owner result: {}", code);
                if (code != HttpStatus.SC_ACCEPTED && code != HttpStatus.SC_OK) {
                    throw new RecrawlServiceException("Unable to unban spam owner status=" + code);
                }
            } catch (IOException e) {
                throw new RecrawlServiceException("Unable to unban spam owner", e);
            }
        });
    }

    @Required
    public void setServiceSpamUrl(String serviceSpamUrl) {
        this.serviceSpamUrl = serviceSpamUrl;
    }

    @Required
    public void setServiceRemoveSpamUrl(String serviceRemoveSpamUrl) {
        this.serviceRemoveSpamUrl = serviceRemoveSpamUrl;
    }
}
