#include <doctest/doctest.h>

#include <nlohmann/json.hpp>

#include "torlinkc/sources/bittorrented.hpp"

using namespace torlinkc;
using nlohmann::json;

TEST_CASE("mapBittorrentedResults maps a well-formed row") {
  json results = json::array({{
      {"torrent_infohash", "ABCDEF0123456789ABCDEF0123456789ABCDEF01"},
      {"torrent_name", "Some Movie 2024"},
      {"torrent_total_size", 1234567},
      {"torrent_seeders", 10},
      {"torrent_leechers", 2},
      {"torrent_file_count", 3},
      {"torrent_created_at", "2024-01-15T00:00:00Z"},
  }});
  auto out = mapBittorrentedResults(results, "bittorrented");
  REQUIRE(out.size() == 1);
  CHECK(out[0].infoHash == "abcdef0123456789abcdef0123456789abcdef01");
  CHECK(out[0].name == "Some Movie 2024");
  CHECK(out[0].sizeBytes == 1234567);
  CHECK(out[0].seeders == 10);
  CHECK(out[0].leechers == 2);
  REQUIRE(out[0].numFiles.has_value());
  CHECK(*out[0].numFiles == 3);
  CHECK(out[0].source == "bittorrented");
  CHECK(out[0].magnet.find("xt=urn:btih:abcdef0123456789abcdef0123456789abcdef01") != std::string::npos);
  REQUIRE(out[0].added.has_value());
}

TEST_CASE("mapBittorrentedResults drops rows with a missing or malformed info hash") {
  json results = json::array({
      {{"torrent_infohash", "tooshort"}, {"torrent_name", "a"}},
      {{"torrent_name", "no hash field"}},
      {{"torrent_infohash", ""}, {"torrent_name", "empty hash"}},
  });
  CHECK(mapBittorrentedResults(results, "bittorrented").empty());
}

TEST_CASE("mapBittorrentedResults falls back to the info hash as the name when torrent_name is missing") {
  json results = json::array({{{"torrent_infohash", std::string(40, 'a')}}});
  auto out = mapBittorrentedResults(results, "bittorrented");
  REQUIRE(out.size() == 1);
  CHECK(out[0].name == std::string(40, 'a'));
}

TEST_CASE("mapBittorrentedResults treats null seeders/leechers as zero rather than dropping the row") {
  json results = json::array({{
      {"torrent_infohash", std::string(40, 'b')},
      {"torrent_name", "n"},
      {"torrent_seeders", nullptr},
      {"torrent_leechers", nullptr},
  }});
  auto out = mapBittorrentedResults(results, "bittorrented");
  REQUIRE(out.size() == 1);
  CHECK(out[0].seeders == 0);
  CHECK(out[0].leechers == 0);
}
