#include <cstdlib>
#include <iostream>
#include <string>
#include <string_view>

#include "backends/asio_driver_discovery.h"

#ifndef APTT_ENABLE_ASIO
#define APTT_ENABLE_ASIO 0
#endif

namespace {

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

void TestBuildGateIsExplicit() {
#if APTT_ENABLE_ASIO
  Expect(aptt::IsAsioSdkEnabled(), "ASIO SDK gate reports enabled");
#else
  Expect(!aptt::IsAsioSdkEnabled(), "ASIO SDK gate is disabled by default");
#endif
  Expect(aptt::CurrentProcessBitness() == 32 ||
             aptt::CurrentProcessBitness() == 64,
         "process bitness is recorded");
  Expect(!aptt::AsioRegistryViewForProcess().empty(),
         "registry view label is available");
}

void TestDisabledSnapshotIsSafeDryRun() {
#if !APTT_ENABLE_ASIO
  const auto snapshot = aptt::EnumerateAsioDrivers();

  Expect(snapshot.backend == aptt::BackendApi::kAsio,
         "disabled snapshot is for ASIO");
  Expect(aptt::DiscoverySnapshotIsSafeDryRun(snapshot),
         "disabled ASIO discovery is a safe dry run");
  Expect(snapshot.enumeration_error.has_value(),
         "disabled ASIO discovery explains why it is unavailable");
  Expect(snapshot.enumeration_error->symbol == "APTT_ENABLE_ASIO_OFF",
         "disabled ASIO discovery records build gate");
  Expect(snapshot.devices.size() == 1,
         "disabled ASIO discovery exposes one status record");
  const auto& device = snapshot.devices.front();
  Expect(device.availability == aptt::DeviceAvailability::kUnavailable,
         "disabled ASIO status is unavailable");
  Expect(device.backend_fields.at("asio_enabled") == "false",
         "disabled ASIO status records gate");
  Expect(device.backend_fields.at("opens_driver") == "false",
         "disabled ASIO status does not open a driver");
  Expect(device.backend_fields.at("creates_buffers") == "false",
         "disabled ASIO status does not create buffers");
  Expect(device.backend_fields.at("opens_control_panel") == "false",
         "disabled ASIO status does not open the control panel");
#endif
}

void TestDriverSnapshotPreservesRegistryMetadataWithoutPlayback() {
  const auto snapshot = aptt::MakeAsioDriverSnapshot(
      "Fixture ASIO Driver",
      "{01234567-89AB-CDEF-0123-456789ABCDEF}",
      "C:\\Fixture\\asio_driver.dll",
      "Fixture ASIO Description");

  Expect(snapshot.device.backend == aptt::BackendApi::kAsio,
         "fixture ASIO driver uses ASIO backend");
  Expect(snapshot.device.stable_id ==
             "asio:{01234567-89AB-CDEF-0123-456789ABCDEF}",
         "stable ID is derived from CLSID");
  Expect(snapshot.backend_fields.at("registry_name") == "Fixture ASIO Driver",
         "registry name is preserved");
  Expect(snapshot.backend_fields.at("driver_path") ==
             "C:\\Fixture\\asio_driver.dll",
         "driver path is preserved");
  Expect(snapshot.backend_fields.at("opens_driver") == "false",
         "driver snapshot does not instantiate the driver");
  Expect(snapshot.backend_fields.at("creates_buffers") == "false",
         "driver snapshot does not create buffers");
  Expect(snapshot.backend_fields.at("opens_control_panel") == "false",
         "driver snapshot does not open the control panel");
  Expect(!snapshot.probes.empty(), "driver info probe is present");
  Expect(snapshot.probes.front().kind == aptt::CapabilityProbeKind::kDriverInfo,
         "probe kind records driver info");
}

}  // namespace

int main() {
  TestBuildGateIsExplicit();
  TestDisabledSnapshotIsSafeDryRun();
  TestDriverSnapshotPreservesRegistryMetadataWithoutPlayback();

  std::cout << "ASIO driver discovery tests passed\n";
  return 0;
}
