#include <cstdlib>
#include <iostream>
#include <string_view>
#include <vector>

#include "backends/wasapi_endpoint_discovery.h"

namespace {

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

void TestStateMapping() {
  Expect(aptt::WasapiAvailabilityFromStateMask(0x00000001u) ==
             aptt::DeviceAvailability::kActive,
         "active endpoint state maps");
  Expect(aptt::WasapiAvailabilityFromStateMask(0x00000002u) ==
             aptt::DeviceAvailability::kDisabled,
         "disabled endpoint state maps");
  Expect(aptt::WasapiAvailabilityFromStateMask(0x00000004u) ==
             aptt::DeviceAvailability::kNotPresent,
         "not-present endpoint state maps");
  Expect(aptt::WasapiAvailabilityFromStateMask(0x00000008u) ==
             aptt::DeviceAvailability::kUnplugged,
         "unplugged endpoint state maps");
  Expect(aptt::WasapiStateMaskLabel(0x00000002u | 0x00000008u) ==
             "disabled|unplugged",
         "combined state label maps");
}

void TestDataFlowAndFormFactorLabels() {
  Expect(aptt::WasapiDataFlowLabel(0) == "render", "render flow label");
  Expect(aptt::WasapiDataFlowLabel(1) == "capture", "capture flow label");
  Expect(aptt::WasapiDataFlowLabel(2) == "all", "all flow label");
  Expect(aptt::WasapiDataFlowLabel(99) == "unknown", "unknown flow label");

  Expect(aptt::WasapiFormFactorLabel(1) == "speakers", "speakers form factor");
  Expect(aptt::WasapiFormFactorLabel(3) == "headphones",
         "headphones form factor");
  Expect(aptt::WasapiFormFactorLabel(8) == "spdif", "spdif form factor");
  Expect(aptt::WasapiFormFactorLabel(99) == "unknown", "unknown form factor");
}

void TestEndpointSnapshotIsDiscoveryOnly() {
  const auto snapshot = aptt::MakeWasapiEndpointSnapshot(
      "wasapi:{fixture-endpoint}",
      "Fixture USB DAC",
      0x00000001u,
      0,
      1,
      std::vector<std::string>{"console", "multimedia"});

  Expect(snapshot.device.backend == aptt::BackendApi::kWasapiShared,
         "snapshot uses WASAPI shared backend identity");
  Expect(snapshot.device.stable_id == "wasapi:{fixture-endpoint}",
         "endpoint ID preserved");
  Expect(snapshot.device.display_name == "Fixture USB DAC",
         "friendly name preserved");
  Expect(snapshot.device.is_default, "default role marks default");
  Expect(snapshot.availability == aptt::DeviceAvailability::kActive,
         "availability preserved");
  Expect(snapshot.default_roles.size() == 2, "default roles preserved");
  Expect(snapshot.backend_fields.at("id_kind") == "wasapi-endpoint-id",
         "backend ID kind preserved");
  Expect(snapshot.backend_fields.at("data_flow") == "render",
         "data flow backend field preserved");
  Expect(snapshot.backend_fields.at("form_factor") == "speakers",
         "form factor backend field preserved");
  Expect(snapshot.probes.size() == 1, "discovery-only probe exists");
  Expect(snapshot.probes.front().kind == aptt::CapabilityProbeKind::kDiscoveryOnly,
         "probe is discovery-only");
  Expect(snapshot.probes.front().backend_fields.at("opens_audio_device") == "false",
         "probe records no audio device open");
  Expect(snapshot.probes.front().backend_fields.at("initializes_stream") == "false",
         "probe records no stream initialization");
  Expect(snapshot.probes.front().backend_fields.at("starts_stream") == "false",
         "probe records no stream start");
}

void TestSnapshotRoundtripsThroughCommonModel() {
  aptt::DiscoverySnapshot discovery;
  discovery.backend = aptt::BackendApi::kWasapiShared;
  discovery.devices.push_back(aptt::MakeWasapiEndpointSnapshot(
      "wasapi:{fixture-endpoint}",
      "Fixture USB DAC",
      0x00000001u,
      0,
      3,
      std::vector<std::string>{"console"}));

  const auto parsed = aptt::ParseDiscoverySnapshotJson(
      aptt::SerializeDiscoverySnapshotJson(discovery));

  Expect(parsed.has_value(), "WASAPI discovery snapshot parses");
  Expect(aptt::DiscoverySnapshotIsSafeDryRun(*parsed),
         "WASAPI enumeration snapshot remains dry-run safe");
  const auto device =
      aptt::FindDeviceByStableId(*parsed, "wasapi:{fixture-endpoint}");
  Expect(device.has_value(), "endpoint ID roundtrips");
  Expect(device->backend_fields.at("form_factor") == "headphones",
         "form factor roundtrips");
}

}  // namespace

int main() {
  TestStateMapping();
  TestDataFlowAndFormFactorLabels();
  TestEndpointSnapshotIsDiscoveryOnly();
  TestSnapshotRoundtripsThroughCommonModel();

  std::cout << "WASAPI endpoint discovery tests passed\n";
  return 0;
}
