package su.xserver.iikocon.test;

import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.HttpResponse;
import io.vertx.ext.web.client.WebClient;

public class IikoOlapClient {

  private final WebClient webClient;
  private final String baseUrl;
  private final String login;
  private final String password;

  // Конструктор клиента
  public IikoOlapClient(Vertx vertx, String baseUrl, String login, String password) {
    this.webClient = WebClient.create(vertx);
    this.baseUrl = baseUrl;
    this.login = login;
    this.password = password;
  }

  // Основной метод для получения OLAP-отчета
  public Future<JsonObject> getOlapReport(JsonObject reportRequest) {
    Promise<JsonObject> promise = Promise.promise();

    // 1. Аутентификация
    authenticate()
      .compose(this::getOrganizations) // 2. Получение организаций
      .compose(orgId -> executeReport(reportRequest, orgId)) // 3. Запрос отчета
      .onSuccess(promise::complete)
      .onFailure(promise::fail);

    return promise.future();
  }

  // Аутентификация и получение токена
  private Future<String> authenticate() {
    Promise<String> promise = Promise.promise();

    JsonObject authRequest = new JsonObject()
      .put("login", login)
      .put("password", password);

    webClient.post(443, baseUrl, "/resto/api/auth")
      .ssl(true)
      .putHeader("Content-Type", "application/json")
      .sendJson(authRequest)
      .onSuccess(response -> {
        if (response.statusCode() == 200) {
          String token = response.bodyAsJsonObject().getString("token");
          promise.complete(token);
        } else {
          promise.fail("Authentication failed: " + response.statusMessage());
        }
      })
      .onFailure(promise::fail);

    return promise.future();
  }

  // Получение ID организации (для отчета)
  private Future<String> getOrganizations(String token) {
    Promise<String> promise = Promise.promise();

    webClient.get(443, baseUrl, "/resto/api/organizations")
      .ssl(true)
      .putHeader("Authorization", "Bearer " + token)
      .send()
      .onSuccess(response -> {
        if (response.statusCode() == 200) {
          // Берем ID первой организации из списка
          String orgId = response.bodyAsJsonArray()
            .getJsonObject(0)
            .getString("id");
          promise.complete(orgId);
        } else {
          promise.fail("Failed to get organizations: " + response.statusMessage());
        }
      })
      .onFailure(promise::fail);

    return promise.future();
  }

  // Выполнение запроса OLAP-отчета
  private Future<JsonObject> executeReport(JsonObject reportRequest, String organizationId) {
    Promise<JsonObject> promise = Promise.promise();

    // Добавляем ID организации в тело запроса
    JsonObject fullRequest = reportRequest.copy()
      .put("organizationId", organizationId);

    webClient.post(443, baseUrl, "/resto/api/v2/reports/olap")
      .ssl(true)
      .putHeader("Content-Type", "application/json")
      .sendJson(fullRequest)
      .onSuccess(response -> {
        if (response.statusCode() == 200) {
          promise.complete(response.bodyAsJsonObject());
        } else {
          promise.fail("OLAP report request failed: " + response.statusMessage());
        }
      })
      .onFailure(promise::fail);

    return promise.future();
  }
}
