#include <cstdlib>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
#include <string_view>
#include <utility>

#include "core/device_discovery.h"

namespace {

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

aptt::DeviceInfo MakeDevice(aptt::BackendApi backend,
                            std::string display_name,
                            std::string stable_id) {
  aptt::DeviceInfo device;
  device.backend = backend;
  device.display_name = std::move(display_name);
  device.stable_id = std::move(stable_id);
  device.driver_name = aptt::ToString(backend);
  return device;
}

void TestSnapshotRepresentsEveryBackendWithoutOpeningDevices() {
  aptt::DiscoverySnapshot snapshot;
  snapshot.backend = aptt::BackendApi::kNull;
  snapshot.capture_utc = "2026-06-19T00:00:00Z";
  snapshot.opens_audio_device = false;
  snapshot.initializes_stream = false;
  snapshot.starts_stream = false;

  snapshot.devices.push_back(aptt::MakeDiscoveredDeviceSnapshot(
      MakeDevice(aptt::BackendApi::kMme, "MME Fixture", "waveout:0"),
      aptt::DeviceAvailability::kActive));
  snapshot.devices.push_back(aptt::MakeDiscoveredDeviceSnapshot(
      MakeDevice(aptt::BackendApi::kDirectSound, "DirectSound Fixture",
                 "dsound:{fixture-guid}"),
      aptt::DeviceAvailability::kActive));
  snapshot.devices.push_back(aptt::MakeDiscoveredDeviceSnapshot(
      MakeDevice(aptt::BackendApi::kWasapiShared, "WASAPI Fixture",
                 "wasapi:{fixture-endpoint}"),
      aptt::DeviceAvailability::kActive));
  snapshot.devices.push_back(aptt::MakeDiscoveredDeviceSnapshot(
      MakeDevice(aptt::BackendApi::kAsio, "ASIO Fixture", "asio:{fixture-clsid}"),
      aptt::DeviceAvailability::kUnavailable));
  snapshot.devices.push_back(aptt::MakeDiscoveredDeviceSnapshot(
      MakeDevice(aptt::BackendApi::kKernelStreaming,
                 "Kernel Streaming Fixture",
                 R"(ks:\\?\SWD#MMDEVAPI#{fixture-filter}#pin:3)"),
      aptt::DeviceAvailability::kUnavailable));

  Expect(aptt::DiscoverySnapshotIsSafeDryRun(snapshot),
         "snapshot is dry-run safe");
  Expect(snapshot.devices.size() == 5, "snapshot stores five backend devices");
  Expect(aptt::FindDeviceByStableId(snapshot, "waveout:0").has_value(),
         "MME stable ID is searchable");
  Expect(aptt::FindDeviceByStableId(snapshot, "dsound:{fixture-guid}").has_value(),
         "DirectSound stable ID is searchable");
  Expect(aptt::FindDeviceByStableId(snapshot, "wasapi:{fixture-endpoint}").has_value(),
         "WASAPI stable ID is searchable");
  Expect(aptt::FindDeviceByStableId(snapshot, "asio:{fixture-clsid}").has_value(),
         "ASIO stable ID is searchable");
  Expect(aptt::FindDeviceByStableId(
             snapshot,
             R"(ks:\\?\SWD#MMDEVAPI#{fixture-filter}#pin:3)").has_value(),
         "Kernel Streaming stable ID is searchable");
}

void TestKernelStreamingFieldsRoundtripWithoutOpeningDevices() {
  aptt::DiscoverySnapshot snapshot;
  snapshot.backend = aptt::BackendApi::kKernelStreaming;
  snapshot.capture_utc = "2026-06-20T00:00:00Z";
  snapshot.opens_audio_device = false;
  snapshot.initializes_stream = false;
  snapshot.starts_stream = false;

  aptt::DeviceInfo device = MakeDevice(
      aptt::BackendApi::kKernelStreaming,
      "Kernel Streaming Fixture",
      R"(ks:\\?\SWD#MMDEVAPI#{fixture-filter}#pin:3)");
  auto device_snapshot = aptt::MakeDiscoveredDeviceSnapshot(
      device,
      aptt::DeviceAvailability::kUnavailable);
  device_snapshot.backend_fields["ks_filter_symbolic_link"] =
      R"(\\?\SWD#MMDEVAPI#{fixture-filter})";
  device_snapshot.backend_fields["ks_pin_id"] = "3";
  device_snapshot.backend_fields["ks_pin_dataflow"] = "render";
  device_snapshot.backend_fields["ks_pin_communication"] = "sink";
  device_snapshot.backend_fields["ks_data_range_count"] = "0";
  device_snapshot.backend_fields["ks_data_format_specifier"] =
      "KSDATAFORMAT_SPECIFIER_WAVEFORMATEX";
  device_snapshot.backend_fields["opens_filter"] = "false";
  device_snapshot.backend_fields["creates_pin"] = "false";
  device_snapshot.backend_fields["starts_stream"] = "false";

  aptt::CapabilityProbeRecord record;
  record.kind = aptt::CapabilityProbeKind::kFormatSupport;
  record.support = aptt::CapabilitySupport::kUnsupported;
  record.detail = "fixture model-only KS row";
  record.backend_fields = device_snapshot.backend_fields;
  record.requested_format = aptt::FormatDescriptor{};
  record.requested_format->sample_rate_hz = 48000;
  record.requested_format->sample_type = aptt::SampleType::kFloat32;
  record.requested_format->valid_bits_per_sample = 32;
  record.requested_format->container_bits_per_sample = 32;
  record.requested_format->channels.channel_count = 2;
  record.requested_format->channels.channel_mask = 3;
  device_snapshot.probes.push_back(record);
  snapshot.devices.push_back(device_snapshot);

  const auto parsed = aptt::ParseDiscoverySnapshotJson(
      aptt::SerializeDiscoverySnapshotJson(snapshot));
  Expect(parsed.has_value(), "Kernel Streaming snapshot parses");
  Expect(aptt::DiscoverySnapshotIsSafeDryRun(*parsed),
         "Kernel Streaming snapshot remains dry-run safe");
  Expect(parsed->backend == aptt::BackendApi::kKernelStreaming,
         "Kernel Streaming backend roundtrips");
  const auto found = aptt::FindDeviceByStableId(
      *parsed,
      R"(ks:\\?\SWD#MMDEVAPI#{fixture-filter}#pin:3)");
  Expect(found.has_value(), "Kernel Streaming stable ID roundtrips");
  Expect(found->backend_fields.at("ks_pin_id") == "3",
         "Kernel Streaming pin ID roundtrips");
  Expect(found->backend_fields.at("opens_filter") == "false",
         "Kernel Streaming no-open flag roundtrips");
  Expect(found->probes.front().backend_fields.at("starts_stream") == "false",
         "Kernel Streaming probe no-start flag roundtrips");
}

void TestRoundtripPreservesIdsErrorsAndBackendFields() {
  aptt::DiscoverySnapshot snapshot;
  snapshot.backend = aptt::BackendApi::kWasapiShared;
  snapshot.capture_utc = "2026-06-19T00:00:00Z";

  aptt::DeviceInfo device = MakeDevice(
      aptt::BackendApi::kWasapiShared,
      "USB DAC",
      "wasapi:{0.0.0.00000000}.fixture");
  device.is_default = true;
  device.is_known_problem_device = true;

  auto device_snapshot = aptt::MakeDiscoveredDeviceSnapshot(
      device,
      aptt::DeviceAvailability::kActive);
  device_snapshot.default_roles = {"console", "multimedia"};
  device_snapshot.backend_fields["api_device_id"] =
      "wasapi:{0.0.0.00000000}.fixture";
  device_snapshot.backend_fields["form_factor"] = "speakers";

  aptt::CapabilityProbeRecord probe;
  probe.kind = aptt::CapabilityProbeKind::kFormatSupport;
  probe.support = aptt::CapabilitySupport::kClosestMatch;
  probe.detail = "closest shared-mode match";
  probe.error = aptt::MakeApiError(0x88890008, "AUDCLNT_E_UNSUPPORTED_FORMAT",
                                   "requested format rejected");

  aptt::FormatDescriptor requested;
  requested.sample_rate_hz = 44100;
  requested.sample_type = aptt::SampleType::kInt16;
  requested.valid_bits_per_sample = 16;
  requested.container_bits_per_sample = 16;
  requested.channels.channel_count = 2;
  requested.channels.channel_mask = 3;
  probe.requested_format = requested;

  aptt::FormatDescriptor accepted;
  accepted.sample_rate_hz = 48000;
  accepted.sample_type = aptt::SampleType::kFloat32;
  accepted.channels.channel_count = 2;
  accepted.channels.channel_mask = 3;
  probe.accepted_format = accepted;

  device_snapshot.probes.push_back(probe);
  snapshot.devices.push_back(device_snapshot);

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

  Expect(parsed.has_value(), "serialized snapshot parses");
  Expect(parsed->schema_version == aptt::kDeviceDiscoverySchemaVersion,
         "schema version roundtrips");
  Expect(aptt::DiscoverySnapshotIsSafeDryRun(*parsed),
         "dry-run flags roundtrip as safe");
  Expect(parsed->devices.size() == 1, "device count roundtrips");

  const auto found =
      aptt::FindDeviceByStableId(*parsed, "wasapi:{0.0.0.00000000}.fixture");
  Expect(found.has_value(), "stable ID roundtrips");
  Expect(found->device.is_known_problem_device,
         "known-problem flag roundtrips");
  Expect(found->default_roles.size() == 2, "default roles roundtrip");
  Expect(found->backend_fields.at("form_factor") == "speakers",
         "backend field roundtrips");
  Expect(found->probes.size() == 1, "probe count roundtrips");
  Expect(found->probes.front().support == aptt::CapabilitySupport::kClosestMatch,
         "probe support roundtrips");
  Expect(found->probes.front().error.has_value(), "probe error roundtrips");
  Expect(found->probes.front().error->raw_code == 0x88890008,
         "raw error code roundtrips");
  Expect(found->probes.front().requested_format->sample_rate_hz == 44100,
         "requested format roundtrips");
  Expect(found->probes.front().accepted_format->sample_rate_hz == 48000,
         "accepted format roundtrips");
}

void TestUnsafeFlagsAreDetected() {
  aptt::DiscoverySnapshot snapshot;
  Expect(aptt::DiscoverySnapshotIsSafeDryRun(snapshot),
         "default snapshot is safe dry-run");
  snapshot.opens_audio_device = true;
  Expect(!aptt::DiscoverySnapshotIsSafeDryRun(snapshot),
         "opening an audio device is not a dry-run snapshot");
}

void TestDomainAwareHexFormattingUsesReadable32BitCodes() {
  Expect(aptt::HexCode32ForDomain(
             static_cast<std::int32_t>(0xC00000BBu),
             "ntstatus") == "0xC00000BB",
         "NTSTATUS STATUS_NOT_SUPPORTED uses 32-bit hex");
  Expect(aptt::HexCode32ForDomain(
             static_cast<std::int32_t>(0x8889000Au),
             "hresult") == "0x8889000A",
         "HRESULT AUDCLNT_E_DEVICE_IN_USE uses 32-bit hex");
  Expect(aptt::HexCode32ForDomain(5, "win32") == "0x00000005",
         "Win32 ERROR_ACCESS_DENIED uses 32-bit hex");

  const auto error = aptt::MakeApiErrorForDomain(
      static_cast<std::int32_t>(0xC00000BBu),
      "STATUS_NOT_SUPPORTED",
      "not supported",
      "ntstatus");
  Expect(error.raw_code < 0, "domain-aware error preserves signed raw code");
  Expect(error.raw_code_hex == "0xC00000BB",
         "domain-aware error stores readable raw_code_hex");
}

void TestFixtureParses() {
#ifndef APTT_SOURCE_DIR
#error "APTT_SOURCE_DIR must be defined"
#endif
  const std::filesystem::path fixture_path =
      std::filesystem::path(APTT_SOURCE_DIR) / "tests" / "fixtures" /
      "device_capability_snapshot.json";
  std::ifstream fixture(fixture_path, std::ios::binary);
  Expect(fixture.good(), "device capability fixture exists");

  const std::string json((std::istreambuf_iterator<char>(fixture)),
                         std::istreambuf_iterator<char>());
  const auto parsed = aptt::ParseDiscoverySnapshotJson(json);
  Expect(parsed.has_value(), "fixture parses");
  Expect(aptt::DiscoverySnapshotIsSafeDryRun(*parsed),
         "fixture is dry-run safe");
  Expect(parsed->devices.size() == 5, "fixture has five devices");
  Expect(aptt::FindDeviceByStableId(*parsed, "waveout:0").has_value(),
         "fixture has MME device");
  Expect(aptt::FindDeviceByStableId(*parsed, "dsound:{fixture-guid}").has_value(),
         "fixture has DirectSound device");
  Expect(aptt::FindDeviceByStableId(
             *parsed, "wasapi:{0.0.0.00000000}.fixture").has_value(),
         "fixture has WASAPI device");
  const auto asio = aptt::FindDeviceByStableId(*parsed, "asio:{fixture-clsid}");
  Expect(asio.has_value(), "fixture has ASIO device");
  Expect(asio->discovery_error.has_value(),
         "fixture preserves ASIO discovery error");
  Expect(asio->discovery_error->raw_code == -1,
         "fixture preserves signed raw error code");
  const auto ks = aptt::FindDeviceByStableId(
      *parsed,
      R"(ks:\\?\SWD#MMDEVAPI#{fixture-filter}#pin:3)");
  Expect(ks.has_value(), "fixture has Kernel Streaming device");
  Expect(ks->device.backend == aptt::BackendApi::kKernelStreaming,
         "fixture preserves Kernel Streaming backend");
  Expect(ks->backend_fields.at("opens_filter") == "false",
         "fixture preserves Kernel Streaming no-open flag");
}

}  // namespace

int main() {
  TestSnapshotRepresentsEveryBackendWithoutOpeningDevices();
  TestKernelStreamingFieldsRoundtripWithoutOpeningDevices();
  TestRoundtripPreservesIdsErrorsAndBackendFields();
  TestUnsafeFlagsAreDetected();
  TestDomainAwareHexFormattingUsesReadable32BitCodes();
  TestFixtureParses();

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