#include "tile/net/http/http_client.h"

#include "gtest/gtest.h"

#include "tile/base/thread/latch.h"

const std::string url = "http://127.0.0.1:8000/";

TEST(HttpClient, Request) {
  tile::HttpClient client;
  std::vector<tile::Future<
      std::expected<tile::HttpResponse, tile::HttpClient::ErrorCode>>>
      v;
  tile::HttpClient::RequestOptions options;
  options.timeout = std::chrono::seconds(20);

  std::atomic<int> count{0};

  for (int i = 0; i != 1000; ++i) {
    for (auto code : tile::AllHttpStatus) {
      if (static_cast<int>(code) < 200) {
        continue;
      }

      v.emplace_back(
          client.AsyncGet(url + std::to_string(static_cast<int>(code)), options)
              .Then([&](std::expected<tile::HttpResponse,
                                      tile::HttpClient::ErrorCode> &&res) {
                int cnt = count.fetch_add(1) + 1;
                TILE_LOG_INFO_EVERY_SECOND("complete {}", cnt);
                return res;
              }));
    }
  }

  int j = 0;
  for (int i = 0; i != 1000; ++i) {
    for (auto &code : tile::AllHttpStatus) {
      if (static_cast<int>(code) < 200) {
        continue;
      }

      auto resp = tile::future::BlockingGet(std::move(v[j++]));

      EXPECT_TRUE(resp) << tile::HttpClient::ErrorCodeToString(resp.error());
      EXPECT_EQ(resp->status(), code);
    }
  }
}

TEST(HttpClient, RequestNoWait) {
  tile::HttpClient client;
  tile::HttpClient::RequestOptions options;
  options.timeout = std::chrono::seconds(20);
  int cnt = 0;

  for (int i = 0; i != 1000; ++i) {
    for (auto code : tile::AllHttpStatus) {
      if (static_cast<int>(code) < 200) {
        continue;
      }
      ++cnt;
    }
  }

  tile::Latch latch(cnt);
  std::atomic<int> count{0};

  for (int i = 0; i != 1000; ++i) {
    for (auto code : tile::AllHttpStatus) {
      if (static_cast<int>(code) < 200) {
        continue;
      }

      client.AsyncGet(url + std::to_string(static_cast<int>(code)), options)
          .Then([&](std::expected<tile::HttpResponse,
                                  tile::HttpClient::ErrorCode> &&) {
            int cnt = count.fetch_add(1) + 1;
            TILE_LOG_INFO_EVERY_SECOND("complete {}", cnt);
            latch.CountDown();
          });
    }
  }
  latch.Wait();
}
