#include "torlinkc/sources/eztv.hpp"

#include <nlohmann/json.hpp>

#include "torlinkc/sources/magnet.hpp"
#include "torlinkc/util/net.hpp"

using nlohmann::json;

namespace torlinkc {

namespace {

std::string trim(const std::string& s) {
  auto first = s.find_first_not_of(" \t\r\n");
  if (first == std::string::npos) return "";
  auto last = s.find_last_not_of(" \t\r\n");
  return s.substr(first, last - first + 1);
}

}  // namespace

Source eztvSource() {
  Source s;
  s.id = "eztv";
  s.label = "EZTV";
  s.groups = {SourceGroup::TV};
  s.homepage = "https://eztvx.to";
  s.reportsHealth = true;
  s.search = [](const std::string& query, const SearchOptions& opts) -> std::vector<TorrentResult> {
    if (!trim(query).empty()) return {};

    FetchOptions fetchOpts;
    fetchOpts.retries = 1;
    fetchOpts.stopToken = opts.stopToken;
    HttpResponse res = fetchResilient("https://eztvx.to/api/get-torrents?limit=100&page=1", fetchOpts);
    if (!res.ok()) throw HttpError(res.status, "EZTV returned " + std::to_string(res.status));

    const json root = json::parse(res.body);
    std::vector<TorrentResult> out;
    for (const auto& t : root.value("torrents", json::array())) {
      std::string hash = t.value("hash", "");
      for (auto& c : hash) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
      std::string name = t.value("title", "");
      if (name.empty()) name = t.value("filename", "");
      if (name.empty()) name = hash;

      std::string magnet = t.value("magnet_url", "");
      if (magnet.empty() && !hash.empty()) magnet = buildMagnet(hash, name);
      if (magnet.empty() || hash.empty()) continue;

      TorrentResult r;
      r.infoHash = hash;
      r.name = name;
      // size_bytes is sometimes a JSON string, sometimes a number.
      if (auto it = t.find("size_bytes"); it != t.end()) {
        if (it->is_string()) {
          try {
            r.sizeBytes = std::stoll(it->get<std::string>());
          } catch (...) {
          }
        } else if (it->is_number()) {
          r.sizeBytes = it->get<std::int64_t>();
        }
      }
      r.seeders = t.value("seeds", 0);
      r.leechers = t.value("peers", 0);
      r.source = "eztv";
      r.magnet = magnet;
      if (auto it = t.find("date_released_unix"); it != t.end() && it->is_number()) {
        r.added = it->get<std::int64_t>();
      }
      out.push_back(std::move(r));
    }
    return out;
  };
  return s;
}

}  // namespace torlinkc
