package com.bcxin.backend.domain.system.dispatch;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.bcxin.backend.core.exceptions.SaasBadException;
import com.bcxin.backend.core.exceptions.SaasNofoundException;
import com.bcxin.backend.core.exceptions.SaasUnAuthorizeException;
import com.bcxin.backend.core.utils.RetryUtil;
import com.bcxin.backend.domain.system.configs.DispatchProperties;
import com.bcxin.backend.domain.system.dispatch.requests.DispatchRequestAbstract;
import com.bcxin.backend.domain.system.dispatch.requests.DispatchType;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.Collection;

@Component
public class DataDispatcherImpl implements DataDispatcher {
    private final DispatchProperties dispatchProperties;

    public DataDispatcherImpl(DispatchProperties dispatchProperties) {
        this.dispatchProperties = dispatchProperties;
    }

    @Override
    public void dispatch(DispatchRequestAbstract request) {
        if (!StringUtils.hasLength(this.dispatchProperties.getApi())) {
            return;
        }

        Assert.hasLength(this.dispatchProperties.getApi(), "patch.dispatch.api配置无效!");
        Assert.isTrue(this.dispatchProperties.getCertificates().size() > 0, "patch.dispatch.certificates配置无效!");

        RetryUtil.execute(() -> {
            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
                HttpRequestBase requestBase = this.getHttpRequestBase(request);
                HttpResponse response = httpClient.execute(requestBase);

                int status = response.getStatusLine().getStatusCode();
                if (status == 401) {
                    throw new SaasUnAuthorizeException();
                } else {
                    if (status < 200 || status > 300) {
                        throw new SaasBadException(response.toString());
                    }
                }
            }

            return true;
        });
    }

    protected HttpRequestBase getHttpRequestBase(DispatchRequestAbstract request)
            throws UnsupportedEncodingException {
        Collection<DispatchProperties.Certificate> certificates = this.dispatchProperties.getCertificates()
                .get(request.getConfigKey());
        DispatchProperties.Certificate certificate = getCertificate(request.getDispatchType(), certificates);

        String clientId = certificate.getClientId();
        String secret = certificate.getSecret();

        String authString = String.format("%s:%s", clientId, secret);
        String authStringEnc = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8"));

        HttpPost post = new HttpPost(dispatchProperties.getApi());
        post.setHeader("Authorization", String.format("Basic %s", authStringEnc));
        post.setHeader("Content-Type", "application/json");
        JSONObject body = new JSONObject();
        body.put("routeKey", certificate.getRouteKey());
        //直接推送数据的方式
        body.put("messageType", 1);
        body.put("data", request.getPostData());
        StringEntity entity = new StringEntity(JSONObject.toJSONString(body, SerializerFeature.WriteMapNullValue), "UTF-8");
        post.setEntity(entity);

        return post;
    }

    private DispatchProperties.Certificate getCertificate(DispatchType dispatchType,
                                                          Collection<DispatchProperties.Certificate> certificates) {
        switch (dispatchType) {
            case Created:
                DispatchProperties.Certificate createdCertificate = certificates.stream()
                        .filter(ii -> ii.getMethod().equals("created"))
                        .findFirst().get();
                if (createdCertificate == null) {
                    throw new SaasBadException("created配置无效!");
                }
                return createdCertificate;
            case Edited:
                DispatchProperties.Certificate editedCertificate = certificates.stream()
                        .filter(ii -> ii.getMethod().equals("edited"))
                        .findFirst().get();
                if (editedCertificate == null) {
                    throw new SaasBadException("edited配置无效!");
                }
                return editedCertificate;
            case Deleted:
                DispatchProperties.Certificate deletedCertificate = certificates.stream()
                        .filter(ii -> ii.getMethod().equals("deleted"))
                        .findFirst().get();
                if (deletedCertificate == null) {
                    throw new SaasBadException("deleted!");
                }

                return deletedCertificate;
            default:
                throw new SaasNofoundException();
        }
    }
}
