#include <cstdlib>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <string_view>
#include <vector>

#include "backends/kernel_streaming_discovery.h"
#include "backends/kernel_streaming_pcm_backend.h"
#include "core/dop_generator.h"

namespace {

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

std::string ReadTextFile(const std::filesystem::path& path) {
  std::ifstream stream(path, std::ios::binary);
  Expect(stream.good(), "test source file is readable");
  return std::string(std::istreambuf_iterator<char>(stream),
                     std::istreambuf_iterator<char>());
}

aptt::PlaybackConfig MakeKernelStreamingPcmConfig() {
  aptt::PlaybackConfig config;
  config.backend = aptt::BackendApi::kKernelStreaming;
  config.device.backend = aptt::BackendApi::kKernelStreaming;
  config.device.display_name = "Fixture KS pin";
  config.device.stable_id = aptt::KernelStreamingStableId(
      R"(\\?\SWD#MMDEVAPI#{fixture-filter})",
      3);
  config.device.driver_name = "KS/AVStream";
  config.device.is_known_problem_device = true;
  config.format =
      aptt::KernelStreamingPcmCandidate(48000, aptt::SampleType::kFloat32, 2);
  config.duration_ms = 1000;
  config.hold_mode = aptt::HoldMode::kKeepWarmAfterStop;
  config.release_cooldown_ms = 1000;
  return config;
}

aptt::FormatDescriptor MakePcmFormat(aptt::SampleType sample_type,
                                     std::uint32_t valid_bits,
                                     std::uint32_t container_bits) {
  auto config = MakeKernelStreamingPcmConfig();
  config.format.sample_type = sample_type;
  config.format.valid_bits_per_sample = valid_bits;
  config.format.container_bits_per_sample = container_bits;
  return config.format;
}

void TestKernelStreamingPolicyDefaultsAreConservative() {
  const auto config = MakeKernelStreamingPcmConfig();
  const auto policy = aptt::MakeKernelStreamingPcmPolicy(config);

  Expect(policy.requires_explicit_filter_pin,
         "explicit KS filter/pin identity is required");
  Expect(policy.requires_fresh_capability_evidence,
         "fresh KS capability evidence is required");
  Expect(policy.keep_warm_after_signal,
         "keep-warm silence is the default KS stop policy");
  Expect(!policy.release_after_drain,
         "KS release after drain is not the default");
  Expect(!policy.uses_reset_on_normal_stop,
         "KS normal stop does not use reset");
  Expect(policy.packet_duration_ms > 0,
         "KS packet duration is explicit");
}

void TestKernelStreamingFormatGateAcceptsPcmAndDopCarrier() {
  auto config = MakeKernelStreamingPcmConfig();
  Expect(aptt::IsKernelStreamingPcmPlaybackFormat(config.format),
         "float32 PCM is accepted");
  Expect(aptt::IsKernelStreamingPlaybackFormat(config.format),
         "float32 PCM is accepted by the combined KS playback gate");

  config.format = MakePcmFormat(aptt::SampleType::kInt16, 16, 16);
  Expect(aptt::IsKernelStreamingPcmPlaybackFormat(config.format),
         "int16 PCM is accepted");

  config.format = MakePcmFormat(aptt::SampleType::kInt24Packed, 24, 24);
  Expect(aptt::IsKernelStreamingPcmPlaybackFormat(config.format),
         "packed 24-bit PCM is accepted");

  config.format = MakePcmFormat(aptt::SampleType::kInt24In32, 24, 32);
  Expect(aptt::IsKernelStreamingPcmPlaybackFormat(config.format),
         "24-in-32 PCM is accepted");

  config.format = MakePcmFormat(aptt::SampleType::kInt32, 32, 32);
  Expect(aptt::IsKernelStreamingPcmPlaybackFormat(config.format),
         "int32 PCM is accepted");

  config.format.signal_mode = aptt::SignalMode::kDop;
  Expect(!aptt::IsKernelStreamingPcmPlaybackFormat(config.format),
         "DoP is outside the KS PCM-only playback gate");

  aptt::DopConfig dop;
  dop.dsd_rate_multiplier = 64;
  dop.channel_count = 2;
  config.format = aptt::MakeDopCarrierFormat(dop);
  Expect(aptt::IsKernelStreamingDopCarrierFormat(config.format),
         "exact DSD64 DoP 24-in-32 carrier is accepted");
  Expect(aptt::IsKernelStreamingPlaybackFormat(config.format),
         "DoP carrier is accepted by the combined KS playback gate");
  Expect(!aptt::IsKernelStreamingPcmPlaybackFormat(config.format),
         "DoP carrier is still not treated as PCM");

  config.format.sample_rate_hz = 48000;
  Expect(!aptt::IsKernelStreamingDopCarrierFormat(config.format),
         "DoP carrier requires exact DSD-rate-derived sample rate");
  Expect(!aptt::IsKernelStreamingPlaybackFormat(config.format),
         "wrong-rate DoP carrier is rejected by the combined KS gate");
}

void TestKernelStreamingPcmByteConversionUsesSharedPcmRules() {
  const std::vector<float> samples = {-1.0F, 0.0F, 1.0F, 0.5F};

  const auto int16 = aptt::ConvertFloat32InterleavedToKernelStreamingPcmBytes(
      samples,
      2,
      MakePcmFormat(aptt::SampleType::kInt16, 16, 16));
  Expect(int16.size() == 8, "KS int16 conversion writes 2 bytes per sample");
  Expect(int16[0] == 0x00 && int16[1] == 0x80,
         "KS int16 conversion is little-endian signed PCM");

  const auto packed24 =
      aptt::ConvertFloat32InterleavedToKernelStreamingPcmBytes(
          samples,
          2,
          MakePcmFormat(aptt::SampleType::kInt24Packed, 24, 24));
  Expect(packed24.size() == 12,
         "KS packed 24-bit conversion writes 3 bytes per sample");

  const auto int24_in_32 =
      aptt::ConvertFloat32InterleavedToKernelStreamingPcmBytes(
          samples,
          2,
          MakePcmFormat(aptt::SampleType::kInt24In32, 24, 32));
  Expect(int24_in_32.size() == 16,
         "KS 24-in-32 conversion writes 4 bytes per sample");
  Expect(int24_in_32[0] == 0x00,
         "KS 24-in-32 leaves the low byte padded");

  const auto invalid =
      aptt::ConvertFloat32InterleavedToKernelStreamingPcmBytes(
          {0.0F, 0.0F, 0.0F},
          2,
          MakePcmFormat(aptt::SampleType::kInt16, 16, 16));
  Expect(invalid.empty(), "KS conversion rejects misaligned samples");
}

void TestKernelStreamingDataRangeMatchIsNotGenericSupportedFormat() {
  aptt::CapabilityProbeRecord data_range;
  data_range.kind = aptt::CapabilityProbeKind::kFormatSupport;
  data_range.support = aptt::CapabilitySupport::kSupported;
  data_range.requested_format =
      aptt::KernelStreamingPcmCandidate(48000, aptt::SampleType::kFloat32, 2);
  data_range.accepted_format = data_range.requested_format;
  data_range.backend_fields["ks_result_level"] = "data_range_match";

  Expect(!aptt::IsKernelStreamingConfirmedPlaybackProbe(data_range),
         "data_range_match is candidate evidence, not generic confirmed support");

  auto pin_verified = data_range;
  pin_verified.backend_fields["ks_result_level"] = "pin_create_verified";
  Expect(aptt::IsKernelStreamingConfirmedPlaybackProbe(pin_verified),
         "pin_create_verified is generic confirmed support");

  auto start_verified = data_range;
  start_verified.backend_fields["ks_result_level"] = "start_verified";
  Expect(aptt::IsKernelStreamingConfirmedPlaybackProbe(start_verified),
         "start_verified is generic confirmed support");
}

void TestKernelStreamingInitializeRequiresExplicitPinBeforeApiUse() {
  auto config = MakeKernelStreamingPcmConfig();
  config.device.stable_id = R"(ks:\\?\SWD#MMDEVAPI#{fixture-filter})";

  aptt::KernelStreamingPcmBackend backend;
  const auto result = backend.initialize(config);

  Expect(!result.ok, "initialize without KS pin fails");
  Expect(backend.lifecycle_state() == aptt::DeviceLifecycleState::kDiscovered,
         "missing KS pin fails before reserving a device");
  Expect(backend.diagnostic_events().empty(),
         "missing KS pin emits no real-device lifecycle events");
}

void TestKernelStreamingRejectsInvalidDopCarrierBeforeApiUse() {
  auto config = MakeKernelStreamingPcmConfig();
  aptt::DopConfig dop;
  dop.dsd_rate_multiplier = 64;
  dop.channel_count = 2;
  config.format = aptt::MakeDopCarrierFormat(dop);
  config.format.sample_rate_hz = 48000;

  aptt::KernelStreamingPcmBackend backend;
  const auto result = backend.initialize(config);

  Expect(!result.ok, "invalid KS DoP carrier fails validation");
  Expect(backend.lifecycle_state() == aptt::DeviceLifecycleState::kDiscovered,
         "invalid KS DoP carrier fails before reserving a device");
  Expect(backend.diagnostic_events().empty(),
         "invalid KS DoP carrier emits no real-device lifecycle events");
}

void TestKernelStreamingResetIsDisabled() {
  aptt::KernelStreamingPcmBackend backend;
  const auto result = backend.reset();

  Expect(!result.ok, "KS reset is disabled");
  Expect(result.error.message.find("disabled") != std::string::npos,
         "KS reset failure explains stop/hold/release lifecycle");
}

void TestKernelStreamingFaultedBackendCanBeReleased() {
  auto config = MakeKernelStreamingPcmConfig();
  config.device.stable_id =
      aptt::KernelStreamingStableId(R"(\\?\APTT_NONEXISTENT_KS_FILTER)", 3);
  config.release_cooldown_ms = 0;

  aptt::KernelStreamingPcmBackend backend;
  const auto initialize = backend.initialize(config);

  Expect(!initialize.ok,
         "nonexistent KS filter fails initialization without hardware");
  Expect(backend.lifecycle_state() == aptt::DeviceLifecycleState::kFaulted,
         "failed KS initialization enters Faulted after reservation");

  const auto release = backend.shutdown();
  Expect(release.ok,
         "faulted KS backend can still release closed handles");
  Expect(backend.lifecycle_state() == aptt::DeviceLifecycleState::kReleased,
         "faulted KS backend transitions to Released after force release");

  bool saw_faulted_release = false;
  for (const auto& event : backend.diagnostic_events()) {
    if (event.lifecycle_from == aptt::DeviceLifecycleState::kFaulted &&
        event.lifecycle_to == aptt::DeviceLifecycleState::kReleased) {
      saw_faulted_release = true;
    }
  }
  Expect(saw_faulted_release,
         "faulted release lifecycle is logged");
}

void TestKernelStreamingRunningSilenceRestartMessageRequiresRelease() {
  const std::string_view message =
      aptt::KernelStreamingRunningSilenceRestartRequiredMessage();
  Expect(message ==
             "\x4B\x53\xE4\xBF\x9D\xE6\x8C\x81\xE4\xB8\xAD\xE3\x82\xB9"
             "\xE3\x83\x88\xE3\x83\xAA\xE3\x83\xBC\xE3\x83\xA0\xE3\x81\x8B"
             "\xE3\x82\x89\xE3\x81\xAE\xE5\x8D\xB3\xE6\x99\x82\xE4\xBF\xA1"
             "\xE5\x8F\xB7\xE5\x86\x8D\xE9\x96\x8B\xE3\x81\xAF\xE6\x9C\xAA"
             "\xE5\xAF\xBE\xE5\xBF\x9C\xE3\x81\xA7\xE3\x81\x99\xE3\x80\x82"
             "\xE4\xBF\x9D\xE6\x8C\x81\xE4\xB8\xAD\xE3\x83\x87\xE3\x83\x90"
             "\xE3\x82\xA4\xE3\x82\xB9\xE3\x82\x92\xE8\xA7\xA3\xE6\x94\xBE"
             "\xE3\x81\x97\xE3\x81\xA6\xE3\x81\x8B\xE3\x82\x89\xE5\x86\x8D"
             "\xE5\xAE\x9F\xE8\xA1\x8C\xE3\x81\x97\xE3\x81\xA6\xE3\x81\x8F"
             "\xE3\x81\xA0\xE3\x81\x95\xE3\x81\x84\xE3\x80\x82",
         "KS RunningSilence restart message requires release before rerun");
}

void TestKernelStreamingCancellationUsesDuplicatedWin32Handle() {
#if defined(APTT_SOURCE_DIR)
  const auto source = ReadTextFile(
      std::filesystem::path(APTT_SOURCE_DIR) /
      "src/backends/kernel_streaming_pcm_backend.cpp");
  Expect(source.find("native_handle()") == std::string::npos,
         "KS cancellation must not use std::thread::native_handle");
  Expect(source.find("DuplicateHandle") != std::string::npos,
         "KS cancellation registers a duplicated Win32 thread handle");
  Expect(source.find("APTT_KS_CANCEL_THREAD_HANDLE_UNAVAILABLE") !=
             std::string::npos,
         "KS cancellation logs unavailable duplicated handle path");
  Expect(source.find("cancel_synchronous_io_attempted") != std::string::npos,
         "KS cancellation evidence preserves attempted field");
  Expect(source.find("join_timeout_is_authoritative") != std::string::npos,
         "KS cancellation evidence preserves authoritative join-timeout field");
#endif
}

void TestKernelStreamingWaveRtPathUsesNotificationBuffer() {
#if defined(APTT_SOURCE_DIR)
  const auto source = ReadTextFile(
      std::filesystem::path(APTT_SOURCE_DIR) /
      "src/backends/kernel_streaming_pcm_backend.cpp");
  Expect(source.find("KSPROPERTY_RTAUDIO_BUFFER_WITH_NOTIFICATION") !=
             std::string::npos,
         "KS WaveRT path requests a notification-capable cyclic buffer");
  Expect(source.find("KSPROPERTY_RTAUDIO_REGISTER_NOTIFICATION_EVENT") !=
             std::string::npos,
         "KS WaveRT path registers a notification event");
  Expect(source.find("RenderWaveRtCyclicBufferLoop") != std::string::npos,
         "KS WaveRT cyclic buffer render loop is implemented");
  Expect(source.find("KSPROPERTY_RTAUDIO_SETWRITEPACKET") ==
             std::string::npos,
         "KS WaveRT path does not require SETWRITEPACKET for Lynx");
#endif
}

void TestRealBackendsRequireReleaseBeforeRunningSilenceRerun() {
#if defined(APTT_SOURCE_DIR)
  const std::vector<std::filesystem::path> backend_sources = {
      "src/backends/mme_pcm_backend.cpp",
      "src/backends/directsound_pcm_backend.cpp",
      "src/backends/wasapi_shared_pcm_backend.cpp",
      "src/backends/wasapi_exclusive_pcm_backend.cpp",
      "src/backends/asio_pcm_backend.cpp",
      "src/backends/asio_native_dsd_backend.cpp",
  };
  for (const auto& relative_path : backend_sources) {
    const auto source = ReadTextFile(
        std::filesystem::path(APTT_SOURCE_DIR) / relative_path);
    Expect(source.find("resumed without") == std::string::npos,
           "real backend must not silently resume signal from RunningSilence");
    Expect(source.find("RunningSilence restart requires explicit release") !=
               std::string::npos,
           "real backend documents release-before-rerun policy");
  }
#endif
}

}  // namespace

int main() {
  TestKernelStreamingPolicyDefaultsAreConservative();
  TestKernelStreamingFormatGateAcceptsPcmAndDopCarrier();
  TestKernelStreamingPcmByteConversionUsesSharedPcmRules();
  TestKernelStreamingDataRangeMatchIsNotGenericSupportedFormat();
  TestKernelStreamingInitializeRequiresExplicitPinBeforeApiUse();
  TestKernelStreamingRejectsInvalidDopCarrierBeforeApiUse();
  TestKernelStreamingResetIsDisabled();
  TestKernelStreamingFaultedBackendCanBeReleased();
  TestKernelStreamingRunningSilenceRestartMessageRequiresRelease();
  TestKernelStreamingCancellationUsesDuplicatedWin32Handle();
  TestKernelStreamingWaveRtPathUsesNotificationBuffer();
  TestRealBackendsRequireReleaseBeforeRunningSilenceRerun();

  std::cout << "Kernel Streaming PCM backend tests passed\n";
  return 0;
}
