package cz.moneta.test.harness.connectors.wso2;

import cz.moneta.test.harness.connectors.rest.BaseRestConnector;
import cz.moneta.test.harness.connectors.rest.RemoteRestCallRequest;
import cz.moneta.test.harness.connectors.rest.ResponseHandler;
import cz.moneta.test.harness.connectors.rest.RestConnector;
import cz.moneta.test.harness.context.ConfigAccessor;
import org.apache.commons.lang3.tuple.Pair;

import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.Invocation;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.Response;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;

@Deprecated
public class RemoteWso2Connector extends BaseRestConnector implements RestConnector {

    private final WebTarget target;

    public RemoteWso2Connector(ConfigAccessor store) {
        try {
            Client client = createHttpClient("RemoteWso2Connector");
            this.target = Optional.ofNullable(store.getConfig("selenium.grid.shared.url"))
                    .map(client::target)
                    .map(t -> t.path("grid/admin"))
                    .map(t -> t.path(Wso2ConnectorServlet.class.getSimpleName()))
                    .orElseThrow(() -> new IllegalStateException("Failed to initialize remote Wso2 connector."));
        } catch (Exception e) {
            throw new IllegalStateException("Failed to initialize remote Wso2 connector.", e);
        }
    }

    @Override
    public <T> Pair<Integer, T> get(String path, Map<String, Object> properties, GenericType<T> responseType,
                                    Map<String, Object> headers) {
        RemoteRestCallRequest get = new RemoteRestCallRequest(path, properties, headers);
        return sendAndReceive("call-get", get, responseType);
    }

    @Override
    public <T> Pair<Integer, T> post(String path, Entity<?> request, GenericType<T> responseType, Map<String, Object> headers) {
        RemoteRestCallRequest post = new RemoteRestCallRequest(path, request, headers);
        return sendAndReceive("call-post", post, responseType);
    }

    @Override
    public <T> Pair<Integer, T> delete(String path, Map<String, Object> properties, GenericType<T> responseType,
                                       Map<String, Object> headers) {
        RemoteRestCallRequest delete = new RemoteRestCallRequest(path, properties, headers);
        return sendAndReceive("call-delete", delete, responseType);
    }

    @Override
    public <T> Pair<Integer, T> patch(String path, Entity<?> request, GenericType<T> responseType, Map<String, Object> headers) {
        RemoteRestCallRequest patch = new RemoteRestCallRequest(path, request, headers);
        return sendAndReceive("call-patch", patch, responseType);
    }

    @Override
    public RestConnector registerResponseHandler(
            ResponseHandler<Pair<Invocation.Builder, Function<Invocation.Builder, Response>>, Response> responseHandler) {
        throw new UnsupportedOperationException("RemoteWso2Connector#registerResponseHandler not implemented");
    }

    @SuppressWarnings("unchecked")
    private <T> Pair<Integer, T> sendAndReceive(String method, RemoteRestCallRequest request, GenericType<T> responseType) {
        Response response = target.path(method)
                .request()
                .post(Entity.json(request));
        return Pair.of(response.getStatus(), response.readEntity(responseType));
    }

}
