#include "backends/mme_pcm_backend.h"

#include <algorithm>
#include <atomic>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <limits>
#include <mutex>
#include <sstream>
#include <thread>
#include <utility>

#include "backends/audio_thread_scheduling.h"
#include "backends/mme_device_discovery.h"
#include "core/high_load_diagnostics.h"
#include "core/pcm_sample_conversion.h"
#include "core/signal_generator.h"

#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#include <mmsystem.h>
#include <mmreg.h>
#ifndef WAVE_FORMAT_IEEE_FLOAT
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
#endif
#endif

namespace aptt {
namespace {

constexpr int kMmeInvalidArgument = 0x30001;
constexpr int kMmeInvalidState = 0x30002;
constexpr int kMmeNotInitialized = 0x30003;
constexpr int kMmeResetNotNeeded = 0x30004;
constexpr int kMmeNotImplemented =
    static_cast<int>(static_cast<std::int32_t>(0x80004001u));

OperationResult ValidateConfigForPlayback(const PlaybackConfig& config) {
  if (config.backend != BackendApi::kMme) {
    return OperationResult::Failure(
        kMmeInvalidArgument,
        "MME PCM playback requires BackendApi::kMme");
  }
  if (config.device.stable_id.empty()) {
    return OperationResult::Failure(
        kMmeInvalidArgument,
        "MME PCM playback requires an explicit waveOut device ID");
  }
  if (!MmeDeviceIdFromStableId(config.device.stable_id)) {
    return OperationResult::Failure(
        kMmeInvalidArgument,
        "MME PCM playback requires an mme:waveout:N or mme:wave-mapper ID");
  }
  if (!IsMmePcmPlaybackFormat(config.format)) {
    return OperationResult::Failure(
        kMmeInvalidArgument,
        "MME playback requires a renderable PCM format");
  }
  if (config.format.sample_rate_hz == 0 ||
      config.format.channels.channel_count == 0) {
    return OperationResult::Failure(
        kMmeInvalidArgument,
        "MME PCM playback requires a non-zero sample rate and channel count");
  }
  return OperationResult::Success();
}

std::uint64_t DurationFrames(const PlaybackConfig& config) {
  if (config.continuous) {
    return std::numeric_limits<std::uint64_t>::max();
  }
  return std::max<std::uint64_t>(
      1,
      (static_cast<std::uint64_t>(config.format.sample_rate_hz) *
       config.duration_ms) /
          1000);
}

std::string FormatSummary(const FormatDescriptor& format) {
  std::ostringstream summary;
  summary << format.sample_rate_hz << " Hz "
          << format.channels.channel_count << " ch "
          << ToString(format.sample_type) << " valid_bits="
          << format.valid_bits_per_sample << " container_bits="
          << format.container_bits_per_sample;
  return summary.str();
}

#if defined(_WIN32)
constexpr GUID kWaveSubtypePcm = {
    0x00000001,
    0x0000,
    0x0010,
    {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
};

constexpr GUID kWaveSubtypeIeeeFloat = {
    0x00000003,
    0x0000,
    0x0010,
    {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
};

bool RequiresExtensibleWaveFormat(const FormatDescriptor& descriptor) {
  return descriptor.sample_type == SampleType::kInt24In32 ||
         descriptor.channels.channel_mask != 0;
}

WAVEFORMATEXTENSIBLE WaveFormatFromDescriptor(
    const FormatDescriptor& descriptor) {
  WAVEFORMATEXTENSIBLE wave{};
  wave.Format.wFormatTag = RequiresExtensibleWaveFormat(descriptor)
                               ? WAVE_FORMAT_EXTENSIBLE
                               : descriptor.sample_type == SampleType::kFloat32
                                     ? WAVE_FORMAT_IEEE_FLOAT
                                     : WAVE_FORMAT_PCM;
  wave.Format.nChannels = static_cast<WORD>(descriptor.channels.channel_count);
  wave.Format.nSamplesPerSec = descriptor.sample_rate_hz;
  wave.Format.wBitsPerSample =
      static_cast<WORD>(descriptor.container_bits_per_sample);
  wave.Format.nBlockAlign =
      static_cast<WORD>((wave.Format.nChannels * wave.Format.wBitsPerSample) / 8);
  wave.Format.nAvgBytesPerSec =
      wave.Format.nSamplesPerSec * wave.Format.nBlockAlign;
  if (wave.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
    wave.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
    wave.Samples.wValidBitsPerSample =
        static_cast<WORD>(descriptor.valid_bits_per_sample);
    wave.dwChannelMask = descriptor.channels.channel_mask;
    wave.SubFormat = descriptor.sample_type == SampleType::kFloat32
                         ? kWaveSubtypeIeeeFloat
                         : kWaveSubtypePcm;
  } else {
    wave.Format.cbSize = 0;
  }
  return wave;
}
#endif

}  // namespace

MmePcmPolicy MakeMmePcmPolicy(const PlaybackConfig& config) {
  MmePcmPolicy policy;
  policy.keep_warm_after_signal = config.hold_mode == HoldMode::kKeepWarmAfterStop;
  policy.release_after_drain = config.hold_mode == HoldMode::kReleaseAfterDrain;
  policy.buffer_count = std::max<std::uint32_t>(2, config.mme_buffer_count);
  policy.buffer_duration_ms =
      std::max<std::uint32_t>(1, config.mme_buffer_duration_ms);
  policy.release_cooldown_ms = config.release_cooldown_ms == 0
                                   ? 1
                                   : config.release_cooldown_ms;
  return policy;
}

bool IsMmePcmPlaybackFormat(const FormatDescriptor& format) {
  return IsRenderablePcmFormat(format);
}

struct MmePcmBackend::Impl {
  ~Impl() {
    const auto result = Shutdown();
#if defined(_WIN32)
    if (!result.ok) {
      render_thread_stop_ = true;
      if (completion_event_ != nullptr) {
        SetEvent(completion_event_);
      }
      if (render_thread_.joinable()) {
        render_thread_.join();
      }
      (void)ReleaseHandles();
    }
#endif
  }

  BackendApi Api() const { return BackendApi::kMme; }

  DeviceList EnumerateDevices() {
    DeviceList devices;
    const auto snapshot = EnumerateMmeWaveOutDevices();
    devices.reserve(snapshot.devices.size());
    for (const auto& device_snapshot : snapshot.devices) {
      devices.push_back(device_snapshot.device);
    }
    return devices;
  }

  FormatProbeResult ProbeFormats(const DeviceInfo& device) {
    FormatProbeResult result;
    result.requested = MmeDefaultPcmCandidates().front();
    const auto device_id = MmeDeviceIdFromStableId(device.stable_id);
    if (!device_id) {
      result.rejection_reasons.push_back(
          "MME format probe requires an explicit waveOut stable ID");
      return result;
    }

    MmeFormatProbeRequest request;
    request.device_id = *device_id;
    request.candidate_formats = MmeDefaultPcmCandidates();
    const auto snapshot = ProbeMmeWaveOutFormats(request);
    for (const auto& probe : snapshot.probes) {
      if (probe.accepted_format) {
        result.supported_formats.push_back(*probe.accepted_format);
      }
      if (probe.error) {
        result.rejection_reasons.push_back(probe.error->message);
      }
    }
    return result;
  }

  OperationResult Initialize(const PlaybackConfig& config) {
    auto validation = ValidateConfigForPlayback(config);
    if (!validation.ok) {
      SetLastError(validation.error);
      return validation;
    }

    Shutdown();

    {
      std::scoped_lock lock(state_mutex_, stats_mutex_, events_mutex_);
      config_ = config;
      policy_ = MakeMmePcmPolicy(config_);
      stats_ = {};
      events_.clear();
      sequence_ = 0;
      state_ = DeviceLifecycleState::kDiscovered;
      signal_frame_target_ = DurationFrames(config_);
      signal_frames_written_ = 0;
      force_silence_ = false;
      release_requested_ = false;
      render_thread_stop_ = false;
      generator_.ResetPhase();
      last_error_ = {};
    }

    if (!TransitionTo(DeviceLifecycleState::kReserved,
                      "selected MME waveOut device reserved")) {
      return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
    }

#if !defined(_WIN32)
    TransitionTo(DeviceLifecycleState::kFaulted,
                 "MME playback is not available");
    return Fail(kMmeNotImplemented, "MME playback is available only on Windows");
#else
    const auto parsed_device_id = MmeDeviceIdFromStableId(config_.device.stable_id);
    if (!parsed_device_id) {
      TransitionTo(DeviceLifecycleState::kFaulted,
                   "MME stable ID parse failed");
      return Fail(kMmeInvalidArgument, "invalid MME stable ID");
    }

    completion_event_ = CreateEventW(nullptr, FALSE, FALSE, nullptr);
    if (completion_event_ == nullptr) {
      TransitionTo(DeviceLifecycleState::kFaulted,
                   "MME completion event creation failed");
      return Fail(static_cast<int>(::GetLastError()),
                  "failed to create MME completion event");
    }

    wave_format_ = WaveFormatFromDescriptor(config_.format);
    const MMRESULT open_result = waveOutOpen(
        &wave_out_,
        static_cast<UINT>(*parsed_device_id),
        &wave_format_.Format,
        reinterpret_cast<DWORD_PTR>(completion_event_),
        0,
        CALLBACK_EVENT);
    if (open_result != MMSYSERR_NOERROR || wave_out_ == nullptr) {
      TransitionTo(DeviceLifecycleState::kFaulted,
                   "waveOutOpen failed");
      ReleaseHandles();
      return Fail(static_cast<int>(open_result),
                  "failed to open MME waveOut device for playback");
    }

    const auto prepare = PrepareBuffers();
    if (!prepare.ok) {
      TransitionTo(DeviceLifecycleState::kFaulted,
                   "MME buffer preparation failed");
      ReleaseHandles();
      return prepare;
    }

    if (!TransitionTo(DeviceLifecycleState::kPrepared,
                      "MME waveOut buffers prepared once")) {
      ReleaseHandles();
      return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
    }
    AddInitializationEvent();
    return OperationResult::Success();
#endif
  }

  OperationResult Start() {
#if !defined(_WIN32)
    return Fail(kMmeNotImplemented, "MME playback is available only on Windows");
#else
    const auto current = GetState();
    if (current == DeviceLifecycleState::kRunningSilence &&
        render_thread_.joinable()) {
      return Fail(kMmeInvalidState,
                  "MME RunningSilence restart requires explicit release before rerun");
    }
    if (current != DeviceLifecycleState::kPrepared &&
        current != DeviceLifecycleState::kHeldOpen) {
      return Fail(kMmeInvalidState,
                  "MME waveOut stream must be prepared before start");
    }
    if (wave_out_ == nullptr || buffers_.empty()) {
      return Fail(kMmeNotInitialized, "MME waveOut stream is not initialized");
    }

    force_silence_ = false;
    release_requested_ = false;
    render_thread_stop_ = false;
    signal_frames_written_ = 0;
    generator_.ResetPhase();
    last_callback_time_ = std::chrono::steady_clock::now();

    if (!TransitionTo(DeviceLifecycleState::kRunningSignal,
                      "MME 1 kHz signal started")) {
      return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
    }

    for (std::size_t index = 0; index < buffers_.size(); ++index) {
      if (!QueueBuffer(index)) {
        TransitionTo(DeviceLifecycleState::kFaulted,
                     "initial MME buffer queue failed");
        return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
      }
    }

    render_thread_ = std::thread([this] { RenderLoop(); });
    return OperationResult::Success();
#endif
  }

  OperationResult Stop() {
    const auto current = GetState();
    if (current == DeviceLifecycleState::kRunningSignal &&
        policy_.keep_warm_after_signal) {
      force_silence_ = true;
      if (!TransitionTo(DeviceLifecycleState::kRunningSilence,
                        "normal MME stop switched to queued PCM silence")) {
        return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
      }
      return OperationResult::Success();
    }
    if (current == DeviceLifecycleState::kRunningSilence &&
        policy_.keep_warm_after_signal) {
      return OperationResult::Success();
    }

    if (current == DeviceLifecycleState::kRunningSignal ||
        current == DeviceLifecycleState::kRunningSilence) {
      if (!TransitionTo(DeviceLifecycleState::kDraining,
                        "MME queue draining before stop")) {
        return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
      }
      auto drain = DrainQueuedBuffers();
      if (!drain.ok) {
        return drain;
      }
    }

    if (policy_.release_after_drain) {
      return ReleaseAfterDrain();
    }
    if (GetState() != DeviceLifecycleState::kHeldOpen) {
      if (!TransitionTo(DeviceLifecycleState::kHeldOpen,
                        "MME waveOut held open after drain")) {
        return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
      }
    }
    return OperationResult::Success();
  }

  OperationResult Reset() {
#if !defined(_WIN32)
    return Fail(kMmeNotImplemented, "MME playback is available only on Windows");
#else
    if (wave_out_ == nullptr) {
      return Fail(kMmeResetNotNeeded, "MME waveOut device is not open");
    }
    const MMRESULT result = waveOutReset(wave_out_);
    AddErrorEvent(static_cast<int>(result),
                  "waveOutReset",
                  "explicit MME reset requested");
    if (result != MMSYSERR_NOERROR) {
      return Fail(static_cast<int>(result), "explicit MME reset failed");
    }
    {
      std::lock_guard lock(stats_mutex_);
      ++stats_.discontinuity_count;
    }
    TransitionTo(DeviceLifecycleState::kFaulted,
                 "explicit MME reset moved stream to faulted state");
    return OperationResult::Success();
#endif
  }

  RealtimeStats GetRealtimeStats() const {
    std::lock_guard lock(stats_mutex_);
    return stats_;
  }

  BackendError GetLastError() const {
    std::lock_guard lock(error_mutex_);
    return last_error_;
  }

  OperationResult Shutdown() {
    const auto current = GetState();
    if (current == DeviceLifecycleState::kDiscovered ||
        current == DeviceLifecycleState::kReleased) {
      return OperationResult::Success();
    }

    if (current == DeviceLifecycleState::kRunningSignal ||
        current == DeviceLifecycleState::kRunningSilence) {
      if (!TransitionTo(DeviceLifecycleState::kDraining,
                        "MME queue draining before release")) {
        return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
      }
    }

    if (current != DeviceLifecycleState::kFaulted) {
      auto drain = DrainQueuedBuffers();
      if (!drain.ok) {
        return drain;
      }
    }
    return ReleaseAfterDrain();
  }

  DeviceLifecycleState GetState() const {
    std::lock_guard lock(state_mutex_);
    return state_;
  }

  std::vector<DiagnosticEvent> GetEvents() const {
    std::lock_guard lock(events_mutex_);
    return events_;
  }

 private:
  OperationResult Fail(int code, std::string message) {
    SetLastError({code, std::move(message)});
    return OperationResult::Failure(code, GetLastError().message);
  }

  void SetLastError(BackendError error) {
    std::lock_guard lock(error_mutex_);
    last_error_ = std::move(error);
  }

  bool TransitionTo(DeviceLifecycleState next, std::string message) {
    DeviceLifecycleState previous;
    {
      std::lock_guard lock(state_mutex_);
      previous = state_;
      LifecyclePolicy lifecycle_policy;
      lifecycle_policy.known_problem_device =
          config_.device.is_known_problem_device;
      const auto decision = EvaluateTransition(previous, next, lifecycle_policy);
      if (!decision.allowed) {
        SetLastError({kMmeInvalidState, decision.reason});
        return false;
      }
      state_ = next;
    }

    auto event = MakeLifecycleEvent(
        NextSequence(),
        BackendApi::kMme,
        config_.device.stable_id,
        previous,
        next,
        std::move(message));
    event.backend_fields["hold_mode"] = ToString(config_.hold_mode);
    event.backend_fields["reset_used"] = "false";
    AppendEvent(std::move(event));
    SetLastError({});
    return true;
  }

  std::uint64_t NextSequence() { return ++sequence_; }

  void AppendEvent(DiagnosticEvent event) {
    std::lock_guard lock(events_mutex_);
    events_.push_back(std::move(event));
  }

  void AddInitializationEvent() {
    DiagnosticEvent event;
    event.type = DiagnosticEventType::kFormatProbe;
    event.sequence = NextSequence();
    event.backend = BackendApi::kMme;
    event.device_id = config_.device.stable_id;
    event.format = config_.format;
    event.message = "MME PCM stream opened and buffers prepared";
    event.backend_fields["requested_format"] = FormatSummary(config_.format);
    event.backend_fields["accepted_format"] = FormatSummary(config_.format);
    event.backend_fields["buffer_count"] = std::to_string(policy_.buffer_count);
    event.backend_fields["buffer_duration_ms"] =
        std::to_string(policy_.buffer_duration_ms);
    event.backend_fields["buffer_frames"] = std::to_string(buffer_frames_);
    event.backend_fields["callback_mode"] = "event";
    event.backend_fields["reset_used"] = "false";
    event.backend_fields["audio_thread_mmcss_enabled"] =
        config_.audio_thread_mmcss_enabled ? "true" : "false";
    event.backend_fields["audio_thread_mmcss_task_name"] =
        config_.audio_thread_mmcss_task_name;
    event.backend_fields["audio_thread_mmcss_priority"] =
        std::to_string(config_.audio_thread_mmcss_priority);
    AddHighLoadDiagnosticFields(config_, event.backend_fields);
    AppendEvent(std::move(event));
  }

  void AddThreadSchedulingEvent(
      const AudioThreadMmcssRegistrationSnapshot& snapshot,
      std::string message) {
    DiagnosticEvent event;
    event.type = DiagnosticEventType::kRuntimeStats;
    event.sequence = NextSequence();
    event.backend = BackendApi::kMme;
    event.device_id = config_.device.stable_id;
    event.message = std::move(message);
    event.backend_fields["api"] = "AvSetMmThreadCharacteristics";
    event.backend_fields["thread_role"] = "MME render/requeue thread";
    AddAudioThreadMmcssBackendFields(event.backend_fields, snapshot);
    AppendEvent(std::move(event));
  }

  void AddRuntimeEvent(std::uint32_t queue_depth,
                       double write_duration_ms,
                       std::uint32_t submitted_frames) {
    const auto stats = GetRealtimeStats();
    if (stats.callback_count > 8 && (stats.callback_count % 50) != 0) {
      return;
    }

    DiagnosticEvent event;
    event.type = DiagnosticEventType::kRuntimeStats;
    event.sequence = NextSequence();
    event.backend = BackendApi::kMme;
    event.device_id = config_.device.stable_id;
    event.message = "MME queue update";
    event.realtime_stats = stats;
    event.backend_fields["queue_depth"] = std::to_string(queue_depth);
    event.backend_fields["write_duration_ms"] = std::to_string(write_duration_ms);
    event.backend_fields["submitted_frames"] = std::to_string(submitted_frames);
    AddHighLoadDiagnosticFields(config_, event.backend_fields);
    if (HighLoadLateCallbackJustOccurred(config_, stats)) {
      event.backend_fields["late_callback"] = "true";
      event.backend_fields["late_callback_source"] =
          "high_load_render_delay";
    }
    AppendEvent(std::move(event));
  }

  void AddErrorEvent(int code, std::string api, std::string message) {
    DiagnosticEvent event;
    event.type = DiagnosticEventType::kError;
    event.sequence = NextSequence();
    event.backend = BackendApi::kMme;
    event.device_id = config_.device.stable_id;
    event.message = std::move(message);
    event.backend_fields["api"] = std::move(api);
    event.backend_fields["code"] = std::to_string(code);
    event.backend_fields["symbol"] = MmeResultSymbol(static_cast<std::uint32_t>(code));
    AppendEvent(std::move(event));
  }

  void AddDrainTimeoutEvent(std::uint32_t outstanding_buffers) {
    DiagnosticEvent event;
    event.type = DiagnosticEventType::kRuntimeStats;
    event.sequence = NextSequence();
    event.backend = BackendApi::kMme;
    event.device_id = config_.device.stable_id;
    event.message = "MME drain timeout before release";
    event.realtime_stats = GetRealtimeStats();
    event.backend_fields["event_category"] = "release";
    event.backend_fields["release_result"] = "drain_timeout";
    event.backend_fields["outstanding_buffers"] =
        std::to_string(outstanding_buffers);
    event.backend_fields["render_thread_still_alive"] = "true";
    event.backend_fields["retry_release_supported"] = "true";
    AddHighLoadDiagnosticFields(config_, event.backend_fields);
    AppendEvent(std::move(event));
  }

#if defined(_WIN32)
  struct Buffer {
    std::vector<BYTE> data;
    WAVEHDR header{};
    bool prepared = false;
    bool queued = false;
  };

  OperationResult PrepareBuffers() {
    buffer_frames_ = std::max<std::uint32_t>(
        64,
        (config_.format.sample_rate_hz * policy_.buffer_duration_ms) / 1000);
    const std::size_t buffer_bytes =
        static_cast<std::size_t>(buffer_frames_) *
        wave_format_.Format.nBlockAlign;
    {
      std::lock_guard lock(stats_mutex_);
      stats_.expected_callback_interval_ms =
          1000.0 * static_cast<double>(buffer_frames_) /
          static_cast<double>(config_.format.sample_rate_hz);
    }
    buffers_.clear();
    buffers_.resize(policy_.buffer_count);

    for (auto& buffer : buffers_) {
      buffer.data.assign(buffer_bytes, 0);
      buffer.header = {};
      buffer.header.lpData = reinterpret_cast<LPSTR>(buffer.data.data());
      buffer.header.dwBufferLength = static_cast<DWORD>(buffer.data.size());
      const MMRESULT result = waveOutPrepareHeader(
          wave_out_,
          &buffer.header,
          sizeof(buffer.header));
      if (result != MMSYSERR_NOERROR) {
        AddErrorEvent(static_cast<int>(result),
                      "waveOutPrepareHeader",
                      "failed to prepare MME buffer");
        return Fail(static_cast<int>(result), "failed to prepare MME buffer");
      }
      buffer.prepared = true;
    }
    return OperationResult::Success();
  }

  bool QueueBuffer(std::size_t index) {
    if (index >= buffers_.size()) {
      return false;
    }
    auto& buffer = buffers_[index];
    const std::uint32_t signal_frames = FillBuffer(buffer.data);
    buffer.header.dwFlags &= ~WHDR_DONE;
    const auto before = std::chrono::steady_clock::now();
    const MMRESULT result = waveOutWrite(
        wave_out_,
        &buffer.header,
        sizeof(buffer.header));
    const auto after = std::chrono::steady_clock::now();
    const double write_ms =
        std::chrono::duration<double, std::milli>(after - before).count();
    if (result != MMSYSERR_NOERROR) {
      AddErrorEvent(static_cast<int>(result),
                    "waveOutWrite",
                    "failed to queue MME buffer");
      SetLastError({static_cast<int>(result), "failed to queue MME buffer"});
      return false;
    }

    {
      std::lock_guard lock(buffers_mutex_);
      buffer.queued = true;
    }
    {
      std::lock_guard lock(stats_mutex_);
      stats_.frames_generated += signal_frames;
      stats_.frames_submitted += buffer_frames_;
      stats_.frames_accepted += buffer_frames_;
      ++stats_.callback_count;
      const auto now = std::chrono::steady_clock::now();
      const double interval_ms =
          std::chrono::duration<double, std::milli>(
              now - last_callback_time_).count();
      stats_.last_callback_interval_ms = interval_ms;
      stats_.max_callback_delay_ms =
          std::max(stats_.max_callback_delay_ms, interval_ms);
      CountHighLoadLateCallbackIfNeeded(config_, stats_);
      last_callback_time_ = now;
    }
    AddRuntimeEvent(QueueDepth(), write_ms, buffer_frames_);

    if (GetState() == DeviceLifecycleState::kRunningSignal &&
        (force_silence_ ||
         signal_frames_written_.load() >= signal_frame_target_)) {
      if (policy_.keep_warm_after_signal) {
        TransitionTo(DeviceLifecycleState::kRunningSilence,
                     "signal ended; MME PCM silence keep-warm is queued");
      } else {
        TransitionTo(DeviceLifecycleState::kHeldOpen,
                     "signal ended; MME device remains open");
        release_requested_ = true;
      }
    }
    return true;
  }

  std::uint32_t FillBuffer(std::vector<BYTE>& data) {
    std::memset(data.data(), 0, data.size());
    const std::uint64_t written = signal_frames_written_.load();
    const bool silence_only = force_silence_ || written >= signal_frame_target_;
    const std::uint32_t signal_frames = silence_only
        ? 0
        : static_cast<std::uint32_t>(std::min<std::uint64_t>(
              buffer_frames_,
              signal_frame_target_ - written));
    if (signal_frames == 0) {
      return 0;
    }

    PcmSineConfig sine_config;
    sine_config.sample_rate_hz = config_.format.sample_rate_hz;
    sine_config.channel_count = config_.format.channels.channel_count;
    sine_config.frequency_hz = config_.frequency_hz;
    sine_config.amplitude_dbfs = config_.amplitude_dbfs;
    if (config_.left_channel_enabled && !config_.right_channel_enabled) {
      sine_config.channel_assignment = ChannelAssignment::kLeftOnly;
    } else if (!config_.left_channel_enabled && config_.right_channel_enabled) {
      sine_config.channel_assignment = ChannelAssignment::kRightOnly;
    }
    sine_config.invert_right = config_.invert_right_phase;
    sine_config.right_channel_phase_offset_degrees =
        config_.right_channel_phase_offset_degrees;
    const auto samples =
        generator_.GenerateInterleavedFloat32(sine_config, signal_frames);

    const auto bytes = ConvertFloat32InterleavedToPcmBytes(
        samples,
        config_.format.channels.channel_count,
        config_.format);
    if (bytes.empty()) {
      AddErrorEvent(kMmeInvalidArgument,
                    "ConvertFloat32InterleavedToPcmBytes",
                    "failed to convert MME PCM buffer");
      SetLastError({kMmeInvalidArgument, "failed to convert MME PCM buffer"});
      force_silence_ = true;
      return 0;
    }
    std::memcpy(data.data(), bytes.data(), bytes.size());
    signal_frames_written_ += signal_frames;
    return signal_frames;
  }

  std::uint32_t QueueDepth() const {
    std::lock_guard lock(buffers_mutex_);
    std::uint32_t count = 0;
    for (const auto& buffer : buffers_) {
      if (buffer.queued && (buffer.header.dwFlags & WHDR_DONE) == 0) {
        ++count;
      }
    }
    return count;
  }

  bool AllBuffersDone() const {
    std::lock_guard lock(buffers_mutex_);
    for (const auto& buffer : buffers_) {
      if (buffer.queued && (buffer.header.dwFlags & WHDR_DONE) == 0) {
        return false;
      }
    }
    return true;
  }

  std::uint32_t OutstandingBufferCount() const {
    std::lock_guard lock(buffers_mutex_);
    std::uint32_t count = 0;
    for (const auto& buffer : buffers_) {
      if (buffer.queued && (buffer.header.dwFlags & WHDR_DONE) == 0) {
        ++count;
      }
    }
    return count;
  }

  bool ClaimCompletedBuffer(std::size_t index) {
    std::lock_guard lock(buffers_mutex_);
    if (index >= buffers_.size()) {
      return false;
    }
    auto& buffer = buffers_[index];
    if (!buffer.queued ||
        (buffer.header.dwFlags & WHDR_DONE) == 0) {
      return false;
    }
    buffer.queued = false;
    return true;
  }

  void RenderLoop() {
    ScopedAudioThreadMmcssRegistration mmcss({
        config_.audio_thread_mmcss_enabled,
        config_.audio_thread_mmcss_task_name,
        config_.audio_thread_mmcss_priority,
    });
    AddThreadSchedulingEvent(mmcss.snapshot(),
                             "MME render thread MMCSS registration evaluated");
    while (!render_thread_stop_) {
      WaitForSingleObject(completion_event_, 10);
      for (std::size_t index = 0; index < buffers_.size(); ++index) {
        if (!ClaimCompletedBuffer(index)) {
          continue;
        }
        if (!release_requested_) {
          ApplyHighLoadRenderDelay(config_, GetRealtimeStats().callback_count);
          if (!QueueBuffer(index)) {
            TransitionTo(DeviceLifecycleState::kFaulted,
                         "MME buffer requeue failed");
            render_thread_stop_ = true;
            break;
          }
        }
      }
      if (release_requested_ && AllBuffersDone()) {
        render_thread_stop_ = true;
      }
    }
    AddThreadSchedulingEvent(mmcss.Revert(),
                             "MME render thread MMCSS registration reverted");
  }

  OperationResult DrainQueuedBuffers() {
    release_requested_ = true;
    const auto deadline = std::chrono::steady_clock::now() +
        std::chrono::milliseconds(policy_.drain_timeout_ms);
    while (!AllBuffersDone() && std::chrono::steady_clock::now() < deadline) {
      SetEvent(completion_event_);
      std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    if (!AllBuffersDone()) {
      AddDrainTimeoutEvent(OutstandingBufferCount());
      return Fail(kMmeInvalidState, "MME drain timeout before release");
    }
    render_thread_stop_ = true;
    if (render_thread_.joinable()) {
      SetEvent(completion_event_);
      render_thread_.join();
    }
    return OperationResult::Success();
  }

  OperationResult ReleaseAfterDrain() {
    const auto current = GetState();
    if (current == DeviceLifecycleState::kFaulted) {
      const auto release = ReleaseHandles();
      if (!release.ok) {
        return release;
      }
      if (!TransitionTo(DeviceLifecycleState::kReleased,
                        "faulted MME waveOut resources released once")) {
        return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
      }
      return OperationResult::Success();
    }

    if (current != DeviceLifecycleState::kReleasing &&
        current != DeviceLifecycleState::kReleased) {
      if (!TransitionTo(DeviceLifecycleState::kReleasing,
                        "MME waveOut resources releasing after drain")) {
        return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
      }
    }

    if (policy_.release_cooldown_ms > 0) {
      std::this_thread::sleep_for(
          std::chrono::milliseconds(policy_.release_cooldown_ms));
    }
    const auto release = ReleaseHandles();
    if (!release.ok) {
      return release;
    }
    if (!TransitionTo(DeviceLifecycleState::kReleased,
                      "MME waveOut resources released once")) {
      return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
    }
    return OperationResult::Success();
  }

  OperationResult ReleaseHandles() {
    for (auto& buffer : buffers_) {
      if (buffer.prepared && wave_out_ != nullptr) {
        const MMRESULT result = waveOutUnprepareHeader(
            wave_out_,
            &buffer.header,
            sizeof(buffer.header));
        if (result != MMSYSERR_NOERROR) {
          AddErrorEvent(static_cast<int>(result),
                        "waveOutUnprepareHeader",
                        "failed to unprepare MME buffer");
          return Fail(static_cast<int>(result),
                      "failed to unprepare MME buffer");
        }
        buffer.prepared = false;
      }
    }
    buffers_.clear();

    if (wave_out_ != nullptr) {
      const MMRESULT result = waveOutClose(wave_out_);
      if (result != MMSYSERR_NOERROR) {
        AddErrorEvent(static_cast<int>(result),
                      "waveOutClose",
                      "failed to close MME waveOut device after drain");
        return Fail(static_cast<int>(result),
                    "failed to close MME waveOut device after drain");
      }
      wave_out_ = nullptr;
    }
    if (completion_event_ != nullptr) {
      CloseHandle(completion_event_);
      completion_event_ = nullptr;
    }
    return OperationResult::Success();
  }
#else
  OperationResult DrainQueuedBuffers() { return OperationResult::Success(); }
  OperationResult ReleaseAfterDrain() {
    if (!TransitionTo(DeviceLifecycleState::kReleased,
                      "MME resources released")) {
      return OperationResult::Failure(kMmeInvalidState, GetLastError().message);
    }
    return OperationResult::Success();
  }
#endif

  mutable std::mutex state_mutex_;
  mutable std::mutex stats_mutex_;
  mutable std::mutex error_mutex_;
  mutable std::mutex events_mutex_;
#if defined(_WIN32)
  mutable std::mutex buffers_mutex_;
#endif
  PlaybackConfig config_;
  MmePcmPolicy policy_;
  RealtimeStats stats_;
  BackendError last_error_;
  std::vector<DiagnosticEvent> events_;
  std::atomic<std::uint64_t> sequence_{0};
  DeviceLifecycleState state_ = DeviceLifecycleState::kDiscovered;
  PcmSineGenerator generator_;
  std::uint64_t signal_frame_target_ = 0;
  std::atomic<std::uint64_t> signal_frames_written_{0};
  std::atomic<bool> force_silence_{false};
  std::atomic<bool> release_requested_{false};
  std::atomic<bool> render_thread_stop_{false};
  std::thread render_thread_;
  std::chrono::steady_clock::time_point last_callback_time_ =
      std::chrono::steady_clock::now();
  std::uint32_t buffer_frames_ = 0;

#if defined(_WIN32)
  HWAVEOUT wave_out_ = nullptr;
  HANDLE completion_event_ = nullptr;
  WAVEFORMATEXTENSIBLE wave_format_{};
  std::vector<Buffer> buffers_;
#endif
};

MmePcmBackend::MmePcmBackend() : impl_(std::make_unique<Impl>()) {}

MmePcmBackend::~MmePcmBackend() = default;

BackendApi MmePcmBackend::api() const {
  return impl_->Api();
}

DeviceList MmePcmBackend::enumerateDevices() {
  return impl_->EnumerateDevices();
}

FormatProbeResult MmePcmBackend::probeFormats(const DeviceInfo& device) {
  return impl_->ProbeFormats(device);
}

OperationResult MmePcmBackend::initialize(const PlaybackConfig& config) {
  return impl_->Initialize(config);
}

OperationResult MmePcmBackend::start() {
  return impl_->Start();
}

OperationResult MmePcmBackend::stop() {
  return impl_->Stop();
}

OperationResult MmePcmBackend::reset() {
  return impl_->Reset();
}

RealtimeStats MmePcmBackend::getRealtimeStats() const {
  return impl_->GetRealtimeStats();
}

BackendError MmePcmBackend::getLastError() const {
  return impl_->GetLastError();
}

OperationResult MmePcmBackend::shutdown() {
  return impl_->Shutdown();
}

DeviceLifecycleState MmePcmBackend::lifecycle_state() const {
  return impl_->GetState();
}

std::vector<DiagnosticEvent> MmePcmBackend::diagnostic_events() const {
  return impl_->GetEvents();
}

}  // namespace aptt
