#include "commit_request.hpp"
#include "json_commit_request_parser.hpp"
#include "test_data.hpp"

#include <nanobench.h>
#include <string>

using namespace weaseldb::test_data;

// JSON test data is now provided by test_data.hpp

int main() {
  // One-shot parsing benchmarks
  auto bench = ankerl::nanobench::Bench()
                   .title("CommitRequest One-Shot Parsing")
                   .unit("byte")
                   .warmup(100);

  bench.batch(SIMPLE_JSON.size());
  // Simple JSON parsing
  bench.run("Simple JSON (3 fields)", [&] {
    CommitRequest request;
    JsonCommitRequestParser parser;
    std::string mutable_json = SIMPLE_JSON;
    auto result =
        parser.parse(request, mutable_json.data(), mutable_json.size());
    ankerl::nanobench::doNotOptimizeAway(result);
    ankerl::nanobench::doNotOptimizeAway(request.leader_id());
  });

  bench.batch(MEDIUM_JSON.size());
  // Medium complexity JSON parsing
  bench.run("Medium JSON (2 preconditions, 2 operations)", [&] {
    CommitRequest request;
    JsonCommitRequestParser parser;
    std::string mutable_json = MEDIUM_JSON;
    auto result =
        parser.parse(request, mutable_json.data(), mutable_json.size());
    ankerl::nanobench::doNotOptimizeAway(result);
    ankerl::nanobench::doNotOptimizeAway(request.leader_id());
  });

  bench.batch(COMPLEX_JSON.size());
  // Complex JSON parsing
  bench.run("Complex JSON (3 preconditions, 5 operations)", [&] {
    CommitRequest request;
    JsonCommitRequestParser parser;
    std::string mutable_json = COMPLEX_JSON;
    auto result =
        parser.parse(request, mutable_json.data(), mutable_json.size());
    ankerl::nanobench::doNotOptimizeAway(result);
    ankerl::nanobench::doNotOptimizeAway(request.leader_id());
  });

  // Large batch operations
  for (int num_ops : {10, 50, 100, 500}) {
    std::string large_json = generate_large_json(num_ops);
    bench.batch(large_json.size());
    bench.run("Large JSON (" + std::to_string(num_ops) + " operations)", [&] {
      CommitRequest request;
      JsonCommitRequestParser parser;
      std::string mutable_json = large_json;
      auto result =
          parser.parse(request, mutable_json.data(), mutable_json.size());
      ankerl::nanobench::doNotOptimizeAway(result);
      ankerl::nanobench::doNotOptimizeAway(request.leader_id());
    });
  }

  // Streaming parsing benchmarks
  auto streaming_bench = ankerl::nanobench::Bench()
                             .title("CommitRequest Streaming Parsing")
                             .unit("byte")
                             .batch(MEDIUM_JSON.size())
                             .warmup(50);

  // Streaming with different chunk sizes
  for (int chunk_size : {1, 8, 32, 128, 512}) {
    streaming_bench.run(
        "Streaming Medium JSON (chunk size " + std::to_string(chunk_size) + ")",
        [&] {
          CommitRequest request;
          JsonCommitRequestParser parser;
          std::string mutable_json = MEDIUM_JSON;

          parser.begin_streaming_parse(request);

          size_t offset = 0;
          CommitRequestParser::ParseStatus status =
              CommitRequestParser::ParseStatus::Incomplete;

          while (offset < mutable_json.size() &&
                 status == CommitRequestParser::ParseStatus::Incomplete) {
            size_t len = std::min(static_cast<size_t>(chunk_size),
                                  mutable_json.size() - offset);
            status = parser.parse_chunk(mutable_json.data() + offset, len);
            offset += len;
          }

          if (status == CommitRequestParser::ParseStatus::Incomplete) {
            status = parser.finish_streaming_parse();
          }

          ankerl::nanobench::doNotOptimizeAway(status);
          ankerl::nanobench::doNotOptimizeAway(request.leader_id());
        });
  }

  return 0;
}
