#include <cstdlib>
#include <iostream>
#include <map>
#include <string_view>

#include "core/high_load_diagnostics.h"

namespace {

void Expect(bool condition, std::string_view message) {
  if (!condition) {
    std::cerr << "FAILED: " << message << "\n";
    std::exit(1);
  }
}

aptt::PlaybackConfig HighLoadConfig() {
  aptt::PlaybackConfig config;
  config.high_load_diagnostics_enabled = true;
  config.high_load_risk_acknowledged = true;
  config.high_load_render_delay_ms = 30;
  config.high_load_delay_every_callbacks = 2;
  return config;
}

void TestHighLoadActivationAndCadence() {
  auto config = HighLoadConfig();
  Expect(aptt::HighLoadDiagnosticsActive(config), "high-load is active");
  Expect(aptt::HighLoadDelayDue(config, 0), "first callback is delayed");
  Expect(!aptt::HighLoadDelayDue(config, 1), "cadence skips callback one");
  Expect(aptt::HighLoadDelayDue(config, 2), "cadence delays callback two");

  config.high_load_diagnostics_enabled = false;
  Expect(!aptt::HighLoadDiagnosticsActive(config), "disabled high-load inactive");
  Expect(!aptt::HighLoadDelayDue(config, 2), "disabled high-load has no delay");
}

void TestZeroCadenceFallsBackToEveryCallback() {
  auto config = HighLoadConfig();
  config.high_load_delay_every_callbacks = 0;
  Expect(aptt::HighLoadDelayDue(config, 0), "zero cadence delays callback zero");
  Expect(aptt::HighLoadDelayDue(config, 1), "zero cadence delays callback one");
}

void TestExpectedIntervalThreshold() {
  auto config = HighLoadConfig();
  Expect(aptt::HighLoadDelayLikelyLate(config, 20.0),
         "30 ms delay is late for 20 ms interval");
  Expect(!aptt::HighLoadDelayLikelyLate(config, 40.0),
         "30 ms delay is not late for 40 ms interval");
  Expect(!aptt::HighLoadDelayLikelyLate(config, 0.0),
         "zero expected interval is not counted late");
}

void TestLateCallbackCounting() {
  auto config = HighLoadConfig();
  aptt::RealtimeStats stats;
  stats.callback_count = 3;
  stats.expected_callback_interval_ms = 20.0;
  stats.underrun_count = 5;
  aptt::CountHighLoadLateCallbackIfNeeded(config, stats);
  Expect(stats.underrun_count == 6, "late high-load callback increments underrun");

  stats.callback_count = 4;
  aptt::CountHighLoadLateCallbackIfNeeded(config, stats);
  Expect(stats.underrun_count == 6, "non-cadence callback does not increment");
}

void TestDiagnosticFieldsIncludeAcknowledgement() {
  const auto config = HighLoadConfig();
  std::map<std::string, std::string> fields;
  aptt::AddHighLoadDiagnosticFields(config, fields);
  Expect(fields["high_load_mode"] == "true", "high-load mode is logged");
  Expect(fields["high_load_risk_acknowledged"] == "true",
         "risk acknowledgement is logged");
  Expect(fields["high_load_mechanism"] == "bounded_render_callback_delay",
         "mechanism is logged");
}

}  // namespace

int main() {
  TestHighLoadActivationAndCadence();
  TestZeroCadenceFallsBackToEveryCallback();
  TestExpectedIntervalThreshold();
  TestLateCallbackCounting();
  TestDiagnosticFieldsIncludeAcknowledgement();

  std::cout << "High-load diagnostics tests passed\n";
  return 0;
}
