#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#ifndef NOMINMAX
#define NOMINMAX
#endif

#include <algorithm>
#include <cstdint>
#include <d3d11.h>
#include <filesystem>
#include <iterator>
#include <optional>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
#include <windows.h>
#include <shellapi.h>

#include "app/command_line_args.h"
#include "app/diagnostic_ui_state.h"
#include "core/dop_generator.h"
#include "core/native_dsd_generator.h"
#include "core/version.h"
#include "imgui.h"
#include "imgui_impl_dx11.h"
#include "imgui_impl_win32.h"

extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(
    HWND window,
    UINT message,
    WPARAM wparam,
    LPARAM lparam);

namespace {

constexpr wchar_t kWindowClassName[] = L"AudioPathToneTesterMainWindow";

ID3D11Device* g_d3d_device = nullptr;
ID3D11DeviceContext* g_d3d_context = nullptr;
IDXGISwapChain* g_swap_chain = nullptr;
ID3D11RenderTargetView* g_render_target_view = nullptr;
std::string g_font_status;
bool g_japanese_font_loaded = false;
aptt::DiagnosticUiState* g_ui_state_for_close_guard = nullptr;
std::optional<aptt::AppCloseGuardDecision> g_pending_close_guard_warning;

bool CommandLineContainsExactFlag(std::wstring_view flag) {
  int argc = 0;
  wchar_t** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
  if (argv == nullptr) {
    return false;
  }
  std::vector<std::wstring> arguments;
  arguments.reserve(static_cast<std::size_t>(argc));
  for (int index = 0; index < argc; ++index) {
    arguments.emplace_back(argv[index]);
  }
  LocalFree(argv);
  return aptt::ContainsExactArgument(arguments, flag);
}

void CleanupRenderTarget() {
  if (g_render_target_view != nullptr) {
    g_render_target_view->Release();
    g_render_target_view = nullptr;
  }
}

void CreateRenderTarget() {
  ID3D11Texture2D* back_buffer = nullptr;
  g_swap_chain->GetBuffer(0, IID_PPV_ARGS(&back_buffer));
  g_d3d_device->CreateRenderTargetView(back_buffer, nullptr, &g_render_target_view);
  back_buffer->Release();
}

bool CreateDeviceD3D(HWND window) {
  DXGI_SWAP_CHAIN_DESC swap_chain_desc{};
  swap_chain_desc.BufferCount = 2;
  swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  swap_chain_desc.OutputWindow = window;
  swap_chain_desc.SampleDesc.Count = 1;
  swap_chain_desc.Windowed = TRUE;
  swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

  constexpr D3D_FEATURE_LEVEL feature_levels[] = {
      D3D_FEATURE_LEVEL_11_0,
      D3D_FEATURE_LEVEL_10_0,
  };
  D3D_FEATURE_LEVEL selected_feature_level{};

  const HRESULT result = D3D11CreateDeviceAndSwapChain(
      nullptr,
      D3D_DRIVER_TYPE_HARDWARE,
      nullptr,
      0,
      feature_levels,
      static_cast<UINT>(sizeof(feature_levels) / sizeof(feature_levels[0])),
      D3D11_SDK_VERSION,
      &swap_chain_desc,
      &g_swap_chain,
      &g_d3d_device,
      &selected_feature_level,
      &g_d3d_context);

  if (FAILED(result)) {
    return false;
  }

  CreateRenderTarget();
  return true;
}

void CleanupDeviceD3D() {
  CleanupRenderTarget();
  if (g_swap_chain != nullptr) {
    g_swap_chain->Release();
    g_swap_chain = nullptr;
  }
  if (g_d3d_context != nullptr) {
    g_d3d_context->Release();
    g_d3d_context = nullptr;
  }
  if (g_d3d_device != nullptr) {
    g_d3d_device->Release();
    g_d3d_device = nullptr;
  }
}

void ApplyJapaneseLightTheme() {
  ImGuiStyle& style = ImGui::GetStyle();
  ImGui::StyleColorsLight();
  style.WindowRounding = 4.0F;
  style.ChildRounding = 4.0F;
  style.FrameRounding = 3.0F;
  style.PopupRounding = 4.0F;
  style.ScrollbarRounding = 4.0F;
  style.GrabRounding = 3.0F;
  style.TabRounding = 4.0F;
  style.WindowPadding = ImVec2(12.0F, 10.0F);
  style.FramePadding = ImVec2(8.0F, 5.0F);
  style.ItemSpacing = ImVec2(8.0F, 7.0F);
  style.ItemInnerSpacing = ImVec2(6.0F, 5.0F);
  style.IndentSpacing = 16.0F;
  style.FrameBorderSize = 1.0F;
  style.ChildBorderSize = 1.0F;
  style.TabBorderSize = 1.0F;
  style.CellPadding = ImVec2(7.0F, 5.0F);

  ImVec4* colors = style.Colors;
  colors[ImGuiCol_Text] = ImVec4(0.08F, 0.10F, 0.13F, 1.00F);
  colors[ImGuiCol_TextDisabled] = ImVec4(0.34F, 0.38F, 0.44F, 1.00F);
  colors[ImGuiCol_WindowBg] = ImVec4(0.93F, 0.95F, 0.97F, 1.00F);
  colors[ImGuiCol_ChildBg] = ImVec4(0.98F, 0.99F, 1.00F, 1.00F);
  colors[ImGuiCol_PopupBg] = ImVec4(1.00F, 1.00F, 1.00F, 0.98F);
  colors[ImGuiCol_Border] = ImVec4(0.56F, 0.61F, 0.68F, 1.00F);
  colors[ImGuiCol_FrameBg] = ImVec4(1.00F, 1.00F, 1.00F, 1.00F);
  colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90F, 0.95F, 1.00F, 1.00F);
  colors[ImGuiCol_FrameBgActive] = ImVec4(0.82F, 0.91F, 1.00F, 1.00F);
  colors[ImGuiCol_TitleBg] = ImVec4(0.79F, 0.86F, 0.93F, 1.00F);
  colors[ImGuiCol_TitleBgActive] = ImVec4(0.70F, 0.80F, 0.90F, 1.00F);
  colors[ImGuiCol_MenuBarBg] = ImVec4(0.86F, 0.90F, 0.94F, 1.00F);
  colors[ImGuiCol_Button] = ImVec4(0.77F, 0.85F, 0.95F, 1.00F);
  colors[ImGuiCol_ButtonHovered] = ImVec4(0.64F, 0.77F, 0.92F, 1.00F);
  colors[ImGuiCol_ButtonActive] = ImVec4(0.21F, 0.42F, 0.72F, 1.00F);
  colors[ImGuiCol_Header] = ImVec4(0.78F, 0.87F, 0.97F, 1.00F);
  colors[ImGuiCol_HeaderHovered] = ImVec4(0.66F, 0.79F, 0.94F, 1.00F);
  colors[ImGuiCol_HeaderActive] = ImVec4(0.50F, 0.68F, 0.88F, 1.00F);
  colors[ImGuiCol_Tab] = ImVec4(0.80F, 0.85F, 0.91F, 1.00F);
  colors[ImGuiCol_TabHovered] = ImVec4(0.66F, 0.78F, 0.92F, 1.00F);
  colors[ImGuiCol_TabSelected] = ImVec4(1.00F, 1.00F, 1.00F, 1.00F);
  colors[ImGuiCol_TableHeaderBg] = ImVec4(0.80F, 0.86F, 0.93F, 1.00F);
  colors[ImGuiCol_TableBorderStrong] = ImVec4(0.51F, 0.58F, 0.66F, 1.00F);
  colors[ImGuiCol_TableBorderLight] = ImVec4(0.70F, 0.76F, 0.83F, 1.00F);
}

void LoadJapaneseSystemFont(ImGuiIO& io) {
  const std::vector<std::filesystem::path> candidates = {
      "C:/Windows/Fonts/YuGothR.ttc",
      "C:/Windows/Fonts/YuGothM.ttc",
      "C:/Windows/Fonts/meiryo.ttc",
  };
  for (const auto& path : candidates) {
    if (!std::filesystem::exists(path)) {
      continue;
    }
    ImFont* font = io.Fonts->AddFontFromFileTTF(
        path.string().c_str(),
        17.0F,
        nullptr,
        io.Fonts->GetGlyphRangesJapanese());
    if (font != nullptr) {
      g_japanese_font_loaded = true;
      g_font_status = "Japanese font: " + path.filename().string();
      return;
    }
  }
  io.Fonts->AddFontDefault();
  g_font_status =
      "Japanese UI font load failed; using fallback ImGui font. Check Windows Japanese fonts.";
}

enum class UiLanguage {
  kJapanese,
  kEnglish,
};

struct UiText {
  const char* app_title;
  const char* language;
  const char* active_change_blocked;
  const char* select_device_first;
  const char* probe_first;
  const char* stale_probe;
  const char* no_active_backend;
  const char* export_bundle;
};

constexpr UiText kJapaneseText = {
    "Audio Path Tone Tester - 音声経路診断",
    "表示言語",
    "再生中またはデバイス保持中は、デバイス、再生方式、フォーマットを変更できません。",
    "対象デバイスを選択してください。",
    "検査マトリックスからテスト条件を選択してください。",
    "対応状況が古くなっています。対象デバイスを選び直すか、デバイスを再読み込みしてください。",
    "再生中のバックエンドはありません。",
    "診断データを書き出し",
};

constexpr UiText kEnglishText = {
    "Audio Path Tone Tester - Audio Path Diagnostics",
    "UI language",
    "Stop or release the active backend before changing device, backend, or format.",
    "Select a target device first.",
    "Select a test condition from the test matrix first.",
    "Capability results are stale. Reselect the target device or reload devices before starting.",
    "No active playback backend.",
    "Export diagnostic bundle",
};

UiLanguage g_language = UiLanguage::kJapanese;

const UiText& Text() {
  return g_language == UiLanguage::kJapanese ? kJapaneseText : kEnglishText;
}

bool IsJapaneseUi() {
  return g_language == UiLanguage::kJapanese;
}

const char* UiLabel(const char* japanese, const char* english) {
  return IsJapaneseUi() ? japanese : english;
}

std::string AcceptedFormatStateLabel(
    const aptt::DiagnosticUiState& ui_state) {
  return IsJapaneseUi() ? ui_state.accepted_format_state_text_japanese()
                        : ui_state.accepted_format_state_text();
}

constexpr const char* kBackends[] = {
    "Null（検証用）",
    "MME",
    "DirectSound",
    "WASAPI共有",
    "WASAPI排他",
    "ASIO",
    "Kernel Streaming",
};
constexpr const char* kBackendsEnglish[] = {
    "Null (software test)",
    "MME",
    "DirectSound",
    "WASAPI Shared",
    "WASAPI Exclusive",
    "ASIO",
    "Kernel Streaming",
};
constexpr const char* kStandardBackendLabelsJapanese[] = {
    "MME",
    "DirectSound",
    "WASAPI共有",
    "WASAPI排他",
    "Kernel Streaming",
    "ASIO",
};
constexpr const char* kStandardBackendLabelsEnglish[] = {
    "MME",
    "DirectSound",
    "WASAPI Shared",
    "WASAPI Exclusive",
    "Kernel Streaming",
    "ASIO",
};
constexpr aptt::BackendApi kStandardBackends[] = {
    aptt::BackendApi::kMme,
    aptt::BackendApi::kDirectSound,
    aptt::BackendApi::kWasapiShared,
    aptt::BackendApi::kWasapiExclusive,
    aptt::BackendApi::kKernelStreaming,
    aptt::BackendApi::kAsio,
};
constexpr const char* kSignals[] = {
    "PCM",
    "DoP",
    "ASIOネイティブDSD",
};
constexpr const char* kSignalsEnglish[] = {
    "PCM",
    "DoP",
    "ASIO Native DSD",
};
constexpr const char* kHoldModes[] = {
    "無音保持",
    "初期化状態保持",
    "排出後に解放",
    "即時解放（要承認）",
};
constexpr const char* kHoldModesEnglish[] = {
    "Keep silence",
    "Hold initialized",
    "Release after drain",
    "Immediate release (Requires acknowledgement)",
};
constexpr const char* kSignalHoldModes[] = {
    "信号停止後も無音保持",
    "信号停止後に初期化保持",
};
constexpr const char* kSignalHoldModesEnglish[] = {
    "Keep silence after signal",
    "Hold initialized after signal",
};
constexpr const char* kMmcssPrioritiesJapanese[] = {
    "低",
    "標準",
    "高",
    "最高",
};
constexpr const char* kMmcssPrioritiesEnglish[] = {
    "Low",
    "Normal",
    "High",
    "Critical",
};
constexpr const char* kLogFormats[] = {
    "JSONL",
    "Text",
    "CSV",
};
constexpr const char* kLogLevels[] = {
    "通常",
    "詳細",
    "コールバック",
};
constexpr const char* kLogLevelsEnglish[] = {
    "Normal",
    "Verbose",
    "Callback",
};
constexpr const char* kLogDirectories[] = {
    "diagnostic_bundles",
    "diagnostic_bundles/manual",
    "diagnostic_bundles/callback_trace",
};

const char* BackendLabel(aptt::BackendApi backend) {
  const auto index = static_cast<int>(backend);
  return IsJapaneseUi() ? kBackends[index] : kBackendsEnglish[index];
}

const char* SignalLabel(aptt::SignalMode signal) {
  const auto index = static_cast<int>(signal);
  return IsJapaneseUi() ? kSignals[index] : kSignalsEnglish[index];
}

const char* HoldModeLabel(aptt::HoldMode hold_mode) {
  const auto index = static_cast<int>(hold_mode);
  return IsJapaneseUi() ? kHoldModes[index] : kHoldModesEnglish[index];
}

const char* StopHoldTooltip() {
  return UiLabel(
      "1 kHz信号だけを停止し、デバイスは現在の保持設定で維持します。完全に解放する場合は、停止後に「保持中デバイスを解放」を押してください。",
      "Stops only the 1 kHz signal and keeps the device according to the current hold setting. To fully release it, press Release held device after the signal stops.");
}

const char* DeviceAvailabilityLabel(aptt::DeviceAvailability availability) {
  if (!IsJapaneseUi()) {
    return aptt::ToString(availability);
  }
  switch (availability) {
    case aptt::DeviceAvailability::kUnknown:
      return "不明";
    case aptt::DeviceAvailability::kActive:
      return "使用可能";
    case aptt::DeviceAvailability::kDisabled:
      return "無効";
    case aptt::DeviceAvailability::kNotPresent:
      return "未接続";
    case aptt::DeviceAvailability::kUnplugged:
      return "取り外し";
    case aptt::DeviceAvailability::kUnavailable:
      return "使用不可";
  }
  return "不明";
}

std::string Shorten(std::string_view value, std::size_t max_chars) {
  if (value.size() <= max_chars) {
    return std::string(value);
  }
  if (max_chars <= 3) {
    return std::string(value.substr(0, max_chars));
  }
  std::string shortened(value.substr(0, max_chars - 3));
  shortened += "...";
  return shortened;
}

void TextKeyValueWrapped(const char* label, std::string_view value) {
  ImGui::PushStyleColor(ImGuiCol_Text,
                        ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled));
  ImGui::Text("%s:", label);
  ImGui::PopStyleColor();
  ImGui::SameLine();
  ImGui::PushTextWrapPos(ImGui::GetCursorPosX() +
                         ImGui::GetContentRegionAvail().x);
  ImGui::TextUnformatted(value.data(), value.data() + value.size());
  ImGui::PopTextWrapPos();
}

void MutedTextWrapped(const char* text) {
  ImGui::PushStyleColor(ImGuiCol_Text,
                        ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled));
  ImGui::TextWrapped("%s", text);
  ImGui::PopStyleColor();
}

void SectionHeader(const char* title, const char* description = nullptr) {
  ImGui::SeparatorText(title);
  if (description != nullptr && description[0] != '\0') {
    MutedTextWrapped(description);
  }
}

std::string FormatSummary(const aptt::FormatDescriptor& format) {
  std::ostringstream out;
  if ((format.signal_mode == aptt::SignalMode::kDop ||
       format.signal_mode == aptt::SignalMode::kAsioNativeDsd) &&
      format.dsd_rate_multiplier) {
    out << aptt::ToString(format.signal_mode) << " DSD"
        << *format.dsd_rate_multiplier << " / "
        << format.channels.channel_count << " ch / "
        << aptt::ToString(format.sample_type) << " "
        << format.valid_bits_per_sample << "/"
        << format.container_bits_per_sample << " bit";
    if (format.signal_mode == aptt::SignalMode::kDop) {
      out << " carrier";
    } else {
      out << " native";
    }
    return out.str();
  }
  out << aptt::ToString(format.signal_mode) << " "
      << format.sample_rate_hz << " Hz / "
      << format.channels.channel_count << " ch / "
      << aptt::ToString(format.sample_type) << " "
      << format.valid_bits_per_sample << "/"
      << format.container_bits_per_sample << " bit";
  if (format.dsd_rate_multiplier) {
    out << " / DSD" << *format.dsd_rate_multiplier;
  }
  return out.str();
}

std::string SampleRateLabel(std::uint32_t sample_rate_hz) {
  std::ostringstream out;
  if (sample_rate_hz >= 1000 && sample_rate_hz % 100 == 0) {
    out << (static_cast<double>(sample_rate_hz) / 1000.0) << " kHz";
  } else {
    out << sample_rate_hz << " Hz";
  }
  return out.str();
}

enum class MatrixDisplayColumnKind {
  kPcmSampleRate,
  kDsdRateMultiplier,
};

struct MatrixDisplayColumn {
  MatrixDisplayColumnKind kind = MatrixDisplayColumnKind::kPcmSampleRate;
  std::uint32_t value = 0;
  std::string label;
};

std::vector<MatrixDisplayColumn> PcmMatrixDisplayColumns() {
  constexpr std::uint32_t kPcmSampleRates[] = {
      44100, 48000, 88200, 96000, 176400, 192000, 352800,
      384000, 705600, 768000, 786000, 1411200, 1536000};
  std::vector<MatrixDisplayColumn> columns;
  for (const auto sample_rate_hz : kPcmSampleRates) {
    columns.push_back({MatrixDisplayColumnKind::kPcmSampleRate,
                       sample_rate_hz,
                       SampleRateLabel(sample_rate_hz)});
  }
  return columns;
}

std::vector<MatrixDisplayColumn> DsdMatrixDisplayColumns() {
  constexpr std::uint32_t kDsdMultipliers[] = {64, 128, 256, 512, 1024, 2048};
  std::vector<MatrixDisplayColumn> columns;
  for (const auto multiplier : kDsdMultipliers) {
    columns.push_back({MatrixDisplayColumnKind::kDsdRateMultiplier,
                       multiplier,
                       "DSD" + std::to_string(multiplier)});
  }
  return columns;
}

std::optional<std::size_t> FindMatrixSampleRateColumn(
    const aptt::DeviceCapabilityMatrix& matrix,
    std::uint32_t sample_rate_hz) {
  const auto iterator = std::find(matrix.sample_rate_columns.begin(),
                                  matrix.sample_rate_columns.end(),
                                  sample_rate_hz);
  if (iterator == matrix.sample_rate_columns.end()) {
    return std::nullopt;
  }
  return static_cast<std::size_t>(
      std::distance(matrix.sample_rate_columns.begin(), iterator));
}

std::optional<std::size_t> MatrixColumnForDisplayColumn(
    const aptt::DeviceCapabilityMatrix& matrix,
    const aptt::FormatDescriptor& row_format,
    const MatrixDisplayColumn& display_column) {
  if (display_column.kind == MatrixDisplayColumnKind::kPcmSampleRate) {
    if (row_format.signal_mode != aptt::SignalMode::kPcm) {
      return std::nullopt;
    }
    return FindMatrixSampleRateColumn(matrix, display_column.value);
  }
  if (row_format.signal_mode == aptt::SignalMode::kDop) {
    return FindMatrixSampleRateColumn(
        matrix, aptt::DopCarrierSampleRateHz(display_column.value));
  }
  if (row_format.signal_mode == aptt::SignalMode::kAsioNativeDsd) {
    return FindMatrixSampleRateColumn(
        matrix, aptt::NativeDsdRateHz(display_column.value));
  }
  return std::nullopt;
}

std::string MatrixRowLabel(const aptt::FormatDescriptor& format) {
  std::ostringstream out;
  const char* signal = "PCM";
  if (format.signal_mode == aptt::SignalMode::kDop) {
    signal = "DoP";
  } else if (format.signal_mode == aptt::SignalMode::kAsioNativeDsd) {
    signal = "Native DSD";
  }
  out << signal << " " << aptt::ToString(format.sample_type);
  if (format.signal_mode != aptt::SignalMode::kAsioNativeDsd) {
    out << " " << format.valid_bits_per_sample << "/"
        << format.container_bits_per_sample;
  }
  if (format.signal_mode == aptt::SignalMode::kDop) {
    out << " carrier";
  } else if (format.signal_mode == aptt::SignalMode::kAsioNativeDsd) {
    out << " native";
  }
  return out.str();
}

const char* CapabilityCellStatusLabel(aptt::CapabilityCellStatus status) {
  switch (status) {
    case aptt::CapabilityCellStatus::kAvailable:
      return UiLabel("使用可能", "Available");
    case aptt::CapabilityCellStatus::kDataRangeMatch:
      return UiLabel("範囲一致", "Data range");
    case aptt::CapabilityCellStatus::kPinCreateVerified:
      return UiLabel("pin作成OK", "Pin OK");
    case aptt::CapabilityCellStatus::kStartVerified:
      return UiLabel("開始確認OK", "Start OK");
    case aptt::CapabilityCellStatus::kUnsupported:
      return UiLabel("非対応", "Unsupported");
    case aptt::CapabilityCellStatus::kUnchecked:
      return UiLabel("未確認", "Unchecked");
    case aptt::CapabilityCellStatus::kInUse:
      return UiLabel("使用中", "In use");
    case aptt::CapabilityCellStatus::kReferenceInfo:
      return UiLabel("参考情報", "Reference");
    case aptt::CapabilityCellStatus::kWarning:
      return UiLabel("要注意", "Warning");
    case aptt::CapabilityCellStatus::kError:
      return UiLabel("エラー", "Error");
    case aptt::CapabilityCellStatus::kNotApplicable:
      return UiLabel("対象外", "N/A");
  }
  return UiLabel("不明", "Unknown");
}

const char* CapabilityCellShortLabel(aptt::CapabilityCellStatus status) {
  switch (status) {
    case aptt::CapabilityCellStatus::kAvailable:
      return UiLabel("可", "OK");
    case aptt::CapabilityCellStatus::kDataRangeMatch:
      return UiLabel("候", "Cand");
    case aptt::CapabilityCellStatus::kPinCreateVerified:
      return UiLabel("Pin", "Pin");
    case aptt::CapabilityCellStatus::kStartVerified:
      return UiLabel("始", "Run");
    case aptt::CapabilityCellStatus::kUnsupported:
      return UiLabel("非", "No");
    case aptt::CapabilityCellStatus::kUnchecked:
      return UiLabel("未", "?");
    case aptt::CapabilityCellStatus::kInUse:
      return UiLabel("中", "Use");
    case aptt::CapabilityCellStatus::kReferenceInfo:
      return UiLabel("参", "Ref");
    case aptt::CapabilityCellStatus::kWarning:
      return UiLabel("注", "Warn");
    case aptt::CapabilityCellStatus::kError:
      return "Err";
    case aptt::CapabilityCellStatus::kNotApplicable:
      return "-";
  }
  return "-";
}

const char* MatrixLegendText() {
  return UiLabel(
      "凡例: 可=使用可能 / 候=範囲一致 / Pin=pin作成OK / 始=開始確認OK / 非=非対応 / 中=使用中 / 参=参考情報 / 注=要注意 / Err=エラー / -=対象外",
      "Legend: OK=available / Cand=data-range match / Pin=pin-create verified / Run=start verified / No=unsupported / Use=in use / Ref=reference / Warn=warning / Err=error / -=not applicable");
}

const char* KernelStreamingDataRangeCandidateWarning() {
  return UiLabel(
      "KSDATARANGE上の候補です。pin作成と開始はまだ確認していません。",
      "This is a KSDATARANGE candidate. Pin creation and start have not been verified yet.");
}

std::string CapabilityCellBackendField(
    const aptt::CapabilityCell& cell,
    const std::string& key) {
  const auto it = cell.raw_backend_fields.find(key);
  return it == cell.raw_backend_fields.end() ? std::string{} : it->second;
}

std::string KernelStreamingModelUiLabel(
    const aptt::CapabilityCell& cell) {
  const auto localized = CapabilityCellBackendField(
      cell,
      IsJapaneseUi() ? "ks_streaming_model_label_ja"
                     : "ks_streaming_model_label_en");
  if (!localized.empty()) {
    return localized;
  }
  const auto model = CapabilityCellBackendField(cell, "ks_streaming_model");
  if (model == "standard_packet") {
    return UiLabel("KS標準パケット", "KS standard packet");
  }
  if (model == "standard_looped") {
    return UiLabel("KSループ", "KS loop");
  }
  if (model == "wavert_cyclic") {
    return UiLabel("WaveRT循環バッファ", "WaveRT cyclic buffer");
  }
  return UiLabel("未確認", "Unknown");
}

std::string KernelStreamingPlaybackStatusUiLabel(
    const aptt::CapabilityCell& cell) {
  const auto localized = CapabilityCellBackendField(
      cell,
      IsJapaneseUi() ? "ks_playback_status_label_ja"
                     : "ks_playback_status_label_en");
  if (!localized.empty()) {
    return localized;
  }
  const auto implementation =
      CapabilityCellBackendField(cell, "ks_playback_implementation");
  const auto model = CapabilityCellBackendField(cell, "ks_streaming_model");
  if (implementation == "implemented") {
    return UiLabel("再生実装済み", "Playback implemented");
  }
  if (implementation == "unimplemented" &&
      model == "standard_looped") {
    return UiLabel("検出済み / 再生未実装",
                   "Detected / playback not implemented");
  }
  return UiLabel("未確認", "Unknown");
}

std::string CapabilityCellDisabledReason(const aptt::CapabilityCell& cell) {
  if (cell.stale) {
    return UiLabel("古い対応状況です。対象デバイスを選び直すか、デバイスを再読み込みしてください。",
                   "This capability result is stale. Reselect the target device or reload devices.");
  }
  if (cell.reference_only) {
    return UiLabel("参考情報のため、テスト条件には選択できません。",
                   "Reference information cannot be selected as a test condition.");
  }
  switch (cell.result_status) {
    case aptt::CapabilityCellStatus::kDataRangeMatch:
      return KernelStreamingDataRangeCandidateWarning();
    case aptt::CapabilityCellStatus::kPinCreateVerified:
      return UiLabel("pin作成までは確認済みです。開始時のRUN遷移はログで確認してください。",
                     "Pin creation is verified. Check the log for the RUN transition at start.");
    case aptt::CapabilityCellStatus::kStartVerified:
      return UiLabel("開始確認まで完了した条件です。",
                     "This condition has been start-verified.");
    case aptt::CapabilityCellStatus::kNotApplicable:
      return UiLabel("このフォーマットはこの再生方式の対象外です。",
                     "This format is not applicable to this backend path.");
    case aptt::CapabilityCellStatus::kUnchecked:
      return UiLabel("このセルはまだ確認されていません。",
                     "This cell has not been checked yet.");
    case aptt::CapabilityCellStatus::kUnsupported:
      return UiLabel("この組み合わせは非対応です。",
                     "This combination is unsupported.");
    case aptt::CapabilityCellStatus::kInUse:
      return UiLabel("デバイスが他のアプリまたはドライバーで使用中です。",
                     "The device is in use by another app or driver.");
    case aptt::CapabilityCellStatus::kError:
      return UiLabel("確認中にエラーが記録されました。",
                     "An error was recorded while checking this cell.");
    case aptt::CapabilityCellStatus::kAvailable:
      return UiLabel("選択できます。",
                     "This cell can be selected.");
    case aptt::CapabilityCellStatus::kReferenceInfo:
      return UiLabel("参考情報のため、テスト条件には選択できません。",
                     "Reference information cannot be selected as a test condition.");
    case aptt::CapabilityCellStatus::kWarning:
      if (CapabilityCellBackendField(cell, "ks_playback_implementation") ==
          "unimplemented") {
        return KernelStreamingPlaybackStatusUiLabel(cell);
      }
      return UiLabel("注意が必要な組み合わせです。",
                     "This combination needs attention.");
  }
  return UiLabel("現在このセルは選択できません。",
                 "This cell is currently unavailable.");
}

ImVec4 CapabilityCellButtonColor(aptt::CapabilityCellStatus status) {
  switch (status) {
    case aptt::CapabilityCellStatus::kAvailable:
    case aptt::CapabilityCellStatus::kStartVerified:
      return ImVec4(0.66F, 0.86F, 0.70F, 1.00F);
    case aptt::CapabilityCellStatus::kPinCreateVerified:
      return ImVec4(0.69F, 0.82F, 0.94F, 1.00F);
    case aptt::CapabilityCellStatus::kUnsupported:
    case aptt::CapabilityCellStatus::kNotApplicable:
      return ImVec4(0.84F, 0.87F, 0.90F, 1.00F);
    case aptt::CapabilityCellStatus::kInUse:
    case aptt::CapabilityCellStatus::kWarning:
    case aptt::CapabilityCellStatus::kDataRangeMatch:
      return ImVec4(0.96F, 0.83F, 0.55F, 1.00F);
    case aptt::CapabilityCellStatus::kError:
      return ImVec4(0.96F, 0.67F, 0.66F, 1.00F);
    case aptt::CapabilityCellStatus::kReferenceInfo:
      return ImVec4(0.77F, 0.84F, 0.94F, 1.00F);
    case aptt::CapabilityCellStatus::kUnchecked:
      return ImVec4(0.88F, 0.90F, 0.93F, 1.00F);
  }
  return ImVec4(0.88F, 0.90F, 0.93F, 1.00F);
}

ImVec4 CapabilityCellButtonHoverColor(aptt::CapabilityCellStatus status) {
  switch (status) {
    case aptt::CapabilityCellStatus::kAvailable:
    case aptt::CapabilityCellStatus::kStartVerified:
      return ImVec4(0.56F, 0.80F, 0.62F, 1.00F);
    case aptt::CapabilityCellStatus::kPinCreateVerified:
      return ImVec4(0.58F, 0.75F, 0.90F, 1.00F);
    case aptt::CapabilityCellStatus::kError:
      return ImVec4(0.92F, 0.56F, 0.55F, 1.00F);
    case aptt::CapabilityCellStatus::kInUse:
    case aptt::CapabilityCellStatus::kWarning:
    case aptt::CapabilityCellStatus::kDataRangeMatch:
      return ImVec4(0.93F, 0.76F, 0.43F, 1.00F);
    case aptt::CapabilityCellStatus::kReferenceInfo:
      return ImVec4(0.67F, 0.78F, 0.91F, 1.00F);
    default:
      return ImVec4(0.78F, 0.82F, 0.87F, 1.00F);
  }
}

bool SameFormat(const aptt::FormatDescriptor& left,
                const aptt::FormatDescriptor& right) {
  return left.signal_mode == right.signal_mode &&
         left.sample_rate_hz == right.sample_rate_hz &&
         left.sample_type == right.sample_type &&
         left.valid_bits_per_sample == right.valid_bits_per_sample &&
         left.container_bits_per_sample == right.container_bits_per_sample &&
         left.channels.channel_count == right.channels.channel_count &&
         left.channels.channel_mask == right.channels.channel_mask &&
         left.dsd_rate_multiplier == right.dsd_rate_multiplier;
}

const aptt::DeviceCapabilitySnapshot* SelectedDeviceSnapshot(
    const aptt::DiagnosticUiState& ui_state) {
  if (!ui_state.selected_device()) {
    return nullptr;
  }
  for (const auto& device : ui_state.discovery_snapshot().devices) {
    if (device.device.stable_id == ui_state.selected_device()->stable_id) {
      return &device;
    }
  }
  return nullptr;
}

std::string KernelStreamingFriendlyDeviceName(
    const aptt::DeviceCapabilitySnapshot& snapshot) {
  std::string name = snapshot.device.display_name;
  const auto pin_suffix = name.find(" / pin ");
  if (pin_suffix != std::string::npos) {
    name = name.substr(0, pin_suffix);
  }
  if (name.empty()) {
    name = UiLabel("Kernel Streamingデバイス", "Kernel Streaming device");
  }
  return name + UiLabel("（KS出力）", " (KS output)");
}

std::string DeviceDisplayNameForTable(
    const aptt::DeviceCapabilitySnapshot& snapshot) {
  if (snapshot.device.backend == aptt::BackendApi::kKernelStreaming) {
    return KernelStreamingFriendlyDeviceName(snapshot);
  }
  return snapshot.device.display_name;
}

bool IsKnownProblemSelection(const aptt::DiagnosticUiState& ui_state) {
  const auto& settings = ui_state.settings();
  return settings.manual_known_problem_device ||
         (ui_state.selected_device() &&
          ui_state.selected_device()->is_known_problem_device);
}

bool IsFullReleaseMode(aptt::HoldMode mode) {
  return mode == aptt::HoldMode::kReleaseAfterDrain ||
         mode == aptt::HoldMode::kImmediateRelease;
}

bool HasAnyActiveBackend(const aptt::DiagnosticUiState& ui_state) {
  return ui_state.HasAnyActiveBackend();
}

bool SelectDeviceForInspection(aptt::DiagnosticUiState& ui_state,
                               const std::string& stable_id) {
  if (HasAnyActiveBackend(ui_state)) {
    return false;
  }
  if (!ui_state.SelectDiscoveredDeviceById(stable_id)) {
    return false;
  }
  ui_state.BuildDeviceCapabilityMatrix();
  return true;
}

std::string ActiveBackendName(const aptt::DiagnosticUiState& ui_state) {
  if (ui_state.has_active_wasapi_shared_backend()) {
    return BackendLabel(aptt::BackendApi::kWasapiShared);
  }
  if (ui_state.has_active_wasapi_exclusive_backend()) {
    return BackendLabel(aptt::BackendApi::kWasapiExclusive);
  }
  if (ui_state.has_active_mme_backend()) {
    return BackendLabel(aptt::BackendApi::kMme);
  }
  if (ui_state.has_active_directsound_backend()) {
    return BackendLabel(aptt::BackendApi::kDirectSound);
  }
  if (ui_state.has_active_asio_backend()) {
    return "ASIO PCM/DoP";
  }
  if (ui_state.has_active_asio_native_dsd_backend()) {
    return SignalLabel(aptt::SignalMode::kAsioNativeDsd);
  }
  return UiLabel("なし", "None");
}

bool DisabledButton(const char* label,
                    bool disabled,
                    std::string_view reason,
                    const ImVec2& size = ImVec2(0.0F, 0.0F)) {
  ImGui::BeginDisabled(disabled);
  const bool clicked = ImGui::Button(label, size);
  ImGui::EndDisabled();
  if (disabled && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
    const std::string tooltip =
        reason.empty()
            ? UiLabel("現在この操作は使用できません.",
                      "This action is currently unavailable.")
            : std::string(reason);
    ImGui::SetTooltip("%s", tooltip.c_str());
  }
  return clicked && !disabled;
}

void InputUint(const char* label,
               std::uint32_t& value,
               int minimum,
               int maximum,
               bool& changed) {
  int edited = static_cast<int>(value);
  ImGui::SetNextItemWidth(170.0F);
  if (ImGui::InputInt(label, &edited)) {
    edited = std::clamp(edited, minimum, maximum);
    value = static_cast<std::uint32_t>(edited);
    changed = true;
  }
}

bool IsSelectedWasapiEndpoint(const aptt::DiagnosticUiState& ui_state) {
  if (!ui_state.selected_device()) {
    return false;
  }
  const auto backend = ui_state.selected_device()->backend;
  return backend == aptt::BackendApi::kWasapiShared ||
         backend == aptt::BackendApi::kWasapiExclusive;
}

bool IsWasapiEndpointBackend(aptt::BackendApi backend) {
  return backend == aptt::BackendApi::kWasapiShared ||
         backend == aptt::BackendApi::kWasapiExclusive;
}

std::string ProbeRowsStaleReason(const aptt::DiagnosticUiState& ui_state) {
  if (ui_state.last_probe_rows_are_stale() && ui_state.selected_device()) {
    const auto* snapshot = SelectedDeviceSnapshot(ui_state);
    if (snapshot != nullptr &&
        IsWasapiEndpointBackend(snapshot->device.backend) &&
        IsWasapiEndpointBackend(ui_state.selected_device()->backend) &&
        snapshot->device.backend != ui_state.selected_device()->backend) {
      return UiLabel(
          "再生方式が変更されています。対象デバイスを選び直してください。",
          "Playback mode changed. Reselect the target device.");
    }
  }
  return Text().stale_probe;
}

bool SelectedDeviceMatchesRequestedBackend(
    const aptt::DiagnosticUiState& ui_state) {
  if (!ui_state.selected_device()) {
    return false;
  }
  const auto requested = ui_state.settings().requested_backend;
  const auto selected = ui_state.selected_device()->backend;
  return requested == selected;
}

bool SelectedFormatIs(aptt::DiagnosticUiState& ui_state,
                      aptt::BackendApi backend,
                      std::optional<aptt::SignalMode> signal = std::nullopt) {
  if (!ui_state.selected_playback_format() ||
      !ui_state.selected_playback_backend() ||
      *ui_state.selected_playback_backend() != backend) {
    return false;
  }
  return !signal || ui_state.selected_playback_format()->signal_mode == *signal;
}

const char* NativeDsdRequiresAsioReason() {
  return UiLabel("ASIOネイティブDSDはASIOドライバーでのみ使用できます。",
                 "ASIO Native DSD can only be used with an ASIO driver.");
}

const char* KernelStreamingSilenceResumeDisabledReason() {
  return UiLabel(
      aptt::KernelStreamingRunningSilenceRestartRequiredMessage(),
      "Immediate signal restart from a KS held silence stream is not supported. Release the held device, then run again.");
}

std::string ActiveStartDisabledReason(
    const aptt::DiagnosticUiState& ui_state) {
  const auto lifecycle = ui_state.active_backend_lifecycle_state();
  if (ui_state.has_active_kernel_streaming_backend() &&
      lifecycle &&
      *lifecycle == aptt::DeviceLifecycleState::kRunningSilence) {
    return KernelStreamingSilenceResumeDisabledReason();
  }
  return Text().active_change_blocked;
}

std::string StartDisabledReason(const aptt::DiagnosticUiState& ui_state,
                                aptt::BackendApi backend,
                                std::optional<aptt::SignalMode> signal) {
  if (HasAnyActiveBackend(ui_state)) {
    return ActiveStartDisabledReason(ui_state);
  }
  if (!ui_state.selected_device()) {
    return Text().select_device_first;
  }
  if (!SelectedDeviceMatchesRequestedBackend(ui_state)) {
    return UiLabel("選択中の出力デバイスは現在の再生方式と一致しません。",
                   "The selected output device does not match the current backend.");
  }
  if (ui_state.settings().requested_signal ==
          aptt::SignalMode::kAsioNativeDsd &&
      ui_state.settings().requested_backend != aptt::BackendApi::kAsio) {
    return NativeDsdRequiresAsioReason();
  }
  if (!ui_state.selected_playback_format()) {
    return UiLabel("検査マトリックスからテスト条件を選択してください。",
                   "Select a test condition from the test matrix.");
  }
  if (ui_state.accepted_format_is_stale()) {
    return ProbeRowsStaleReason(ui_state);
  }
  if (!ui_state.selected_test_condition()) {
    return UiLabel("検査マトリックスからテスト条件を選択してください。",
                   "Select a test condition from the test matrix.");
  }
  if (ui_state.selected_test_condition_is_stale()) {
    return UiLabel("選択中の検査条件が古くなっています。出力経路でフォーマットを選び直してください。",
                   "The selected test condition is stale. Reselect the format in Output Path.");
  }
  if (!ui_state.selected_playback_backend() ||
      *ui_state.selected_playback_backend() != backend ||
      (signal && ui_state.selected_playback_format()->signal_mode != *signal)) {
    if (signal && *signal == aptt::SignalMode::kDop) {
      return "DoP requires WASAPI exclusive or ASIO PCM path.";
    }
    return UiLabel("この再生方式では対応状況セルが選択されていません。",
                   "No compatible matrix cell is selected for this backend.");
  }
  if (*ui_state.selected_playback_backend() !=
      ui_state.settings().requested_backend) {
    return UiLabel("選択済みフォーマットは現在の再生方式と一致しません。出力経路で選び直してください。",
                   "The selected accepted format does not match the current backend. Reselect it in Output Path.");
  }
  if (backend == aptt::BackendApi::kAsio && !aptt::IsAsioSdkEnabled()) {
    return UiLabel("このビルドではASIOサポートが無効です。",
                   "ASIO support is disabled in this build.");
  }
  if (IsKnownProblemSelection(ui_state) &&
      IsFullReleaseMode(ui_state.settings().hold_mode) &&
      !ui_state.settings().expert_unsafe_release_ack) {
    return UiLabel("危険な解放操作には明示承認が必要です。",
                   "Risky release settings require explicit acknowledgement.");
  }
  return {};
}

std::string ReleaseAfterStopDisabledReason(
    const aptt::DiagnosticUiState& ui_state) {
  if (!HasAnyActiveBackend(ui_state)) {
    return Text().no_active_backend;
  }
  const auto lifecycle = ui_state.active_backend_lifecycle_state();
  if (lifecycle && *lifecycle == aptt::DeviceLifecycleState::kRunningSignal) {
    return UiLabel("先に信号停止 / 保持を押すか、指定時間の終了を待ってください。",
                   "Stop the signal first, or wait for the requested duration to finish.");
  }
  if (IsKnownProblemSelection(ui_state) &&
      !ui_state.settings().expert_unsafe_release_ack) {
    return UiLabel("既知の注意デバイスの解放には明示承認が必要です。",
                   "Releasing a known-problem device requires explicit acknowledgement.");
  }
  return {};
}

bool CanStart(const aptt::DiagnosticUiState& ui_state,
              aptt::BackendApi backend,
              std::optional<aptt::SignalMode> signal) {
  return StartDisabledReason(ui_state, backend, signal).empty();
}

void RefreshRequestedBackend(aptt::DiagnosticUiState& ui_state) {
  switch (ui_state.settings().requested_backend) {
    case aptt::BackendApi::kMme:
      ui_state.RefreshMmeDevices();
      break;
    case aptt::BackendApi::kDirectSound:
      ui_state.RefreshDirectSoundDevices();
      break;
    case aptt::BackendApi::kAsio:
      ui_state.RefreshAsioDrivers();
      break;
    case aptt::BackendApi::kKernelStreaming:
      ui_state.RefreshKernelStreamingDevices();
      break;
    case aptt::BackendApi::kWasapiShared:
    case aptt::BackendApi::kWasapiExclusive:
      ui_state.RefreshWasapiEndpoints();
      break;
    case aptt::BackendApi::kNull:
      ui_state.RunNullSession();
      break;
  }
}

void StartSelectedFormat(aptt::DiagnosticUiState& ui_state) {
  if (!ui_state.selected_playback_backend() ||
      !ui_state.selected_playback_format()) {
    return;
  }
  const auto backend = *ui_state.selected_playback_backend();
  const auto signal = ui_state.selected_playback_format()->signal_mode;
  if (backend != ui_state.settings().requested_backend) {
    return;
  }
  if (backend == aptt::BackendApi::kMme) {
    ui_state.StartMmePcm();
  } else if (backend == aptt::BackendApi::kDirectSound) {
    ui_state.StartDirectSoundPcm();
  } else if (backend == aptt::BackendApi::kWasapiShared) {
    ui_state.StartWasapiSharedPcm();
  } else if (backend == aptt::BackendApi::kWasapiExclusive &&
             signal == aptt::SignalMode::kDop) {
    ui_state.StartWasapiExclusiveDop();
  } else if (backend == aptt::BackendApi::kWasapiExclusive) {
    ui_state.StartWasapiExclusivePcm();
  } else if (backend == aptt::BackendApi::kKernelStreaming) {
    ui_state.StartKernelStreamingPcm();
  } else if (backend == aptt::BackendApi::kAsio &&
             signal == aptt::SignalMode::kDop) {
    ui_state.StartAsioDop();
  } else if (backend == aptt::BackendApi::kAsio &&
             signal == aptt::SignalMode::kAsioNativeDsd) {
    ui_state.StartAsioNativeDsd();
  } else if (backend == aptt::BackendApi::kAsio) {
    ui_state.StartAsioPcm();
  }
}

void StopActiveBackend(aptt::DiagnosticUiState& ui_state) {
  if (ui_state.has_active_wasapi_shared_backend()) {
    ui_state.StopWasapiSharedPcm();
  } else if (ui_state.has_active_wasapi_exclusive_backend()) {
    ui_state.StopWasapiExclusivePcm();
  } else if (ui_state.has_active_mme_backend()) {
    ui_state.StopMmePcm();
  } else if (ui_state.has_active_directsound_backend()) {
    ui_state.StopDirectSoundPcm();
  } else if (ui_state.has_active_kernel_streaming_backend()) {
    ui_state.StopKernelStreamingPcm();
  } else if (ui_state.has_active_asio_backend()) {
    ui_state.StopAsioPcm();
  } else if (ui_state.has_active_asio_native_dsd_backend()) {
    ui_state.StopAsioNativeDsd();
  }
}

void ReleaseActiveBackend(aptt::DiagnosticUiState& ui_state) {
  if (ui_state.has_active_wasapi_shared_backend()) {
    ui_state.ReleaseWasapiSharedPcm();
  } else if (ui_state.has_active_wasapi_exclusive_backend()) {
    ui_state.ReleaseWasapiExclusivePcm();
  } else if (ui_state.has_active_mme_backend()) {
    ui_state.ReleaseMmePcm();
  } else if (ui_state.has_active_directsound_backend()) {
    ui_state.ReleaseDirectSoundPcm();
  } else if (ui_state.has_active_kernel_streaming_backend()) {
    ui_state.ReleaseKernelStreamingPcm();
  } else if (ui_state.has_active_asio_backend()) {
    ui_state.ReleaseAsioPcm();
  } else if (ui_state.has_active_asio_native_dsd_backend()) {
    ui_state.ReleaseAsioNativeDsd();
  }
}

void RenderHeldDeviceReleaseAcknowledgement(
    aptt::DiagnosticUiState& ui_state) {
  if (!HasAnyActiveBackend(ui_state) || !IsKnownProblemSelection(ui_state)) {
    return;
  }
  bool acknowledged = ui_state.settings().expert_unsafe_release_ack;
  if (ImGui::Checkbox(
          UiLabel("既知の注意デバイスの解放を承認",
                  "Approve release for known-problem device"),
          &acknowledged)) {
    auto settings = ui_state.settings();
    settings.expert_unsafe_release_ack = acknowledged;
    ui_state.UpdateSettings(settings);
  }
  if (!acknowledged) {
    ImGui::TextWrapped(
        "%s",
        UiLabel("このデバイスは完全解放で復帰に時間がかかる可能性があります。必要な場合だけ承認してから解放してください。",
                "This device may take time to recover after full release. Approve only when release is needed."));
  }
}

void RenderHeldDeviceReleaseAcknowledgementCompact(
    aptt::DiagnosticUiState& ui_state) {
  if (!HasAnyActiveBackend(ui_state) || !IsKnownProblemSelection(ui_state)) {
    return;
  }
  bool acknowledged = ui_state.settings().expert_unsafe_release_ack;
  if (ImGui::Checkbox(UiLabel("解放承認", "Release OK"), &acknowledged)) {
    auto settings = ui_state.settings();
    settings.expert_unsafe_release_ack = acknowledged;
    ui_state.UpdateSettings(settings);
  }
  if (ImGui::IsItemHovered()) {
    ImGui::SetTooltip(
        "%s",
        UiLabel("このデバイスは完全解放で復帰に時間がかかる可能性があります。必要な場合だけ承認してから解放してください。",
                "This device may take time to recover after full release. Approve only when release is needed."));
  }
}

std::string NextRequiredAction(const aptt::DiagnosticUiState& ui_state) {
  if (HasAnyActiveBackend(ui_state)) {
    const auto lifecycle = ui_state.active_backend_lifecycle_state();
    if (lifecycle && *lifecycle == aptt::DeviceLifecycleState::kRunningSignal) {
      return UiLabel("指定時間の終了を待つか、信号停止 / 保持を押してください",
                     "Wait for the requested duration, or stop the signal and hold the device");
    }
    return UiLabel("信号は停止済みです。診断データを書き出すか、必要に応じて保持中デバイスを解放してください",
                   "The signal has stopped. Export diagnostics, or release the held device if needed");
  }
  if (ui_state.discovery_snapshot().devices.empty()) {
    return UiLabel("出力デバイスを再読み込みしてください",
                   "Refresh output devices");
  }
  if (!ui_state.selected_device()) {
    return UiLabel("対象デバイスを選択してください",
                   "Select a target device");
  }
  if (!ui_state.device_capability_matrix()) {
    return UiLabel("デバイスを選択すると対応状況を自動確認します",
                   "Selecting a device automatically checks capabilities");
  }
  if (ui_state.device_capability_matrix()->stale) {
    return UiLabel("対応状況が古くなっています。デバイスを選び直してください",
                   "Capability results are stale. Reselect the device");
  }
  if (ui_state.accepted_format_is_stale()) {
    return ProbeRowsStaleReason(ui_state);
  }
  if (!ui_state.selected_test_condition() &&
      ui_state.last_probe_rows_are_stale()) {
    return ProbeRowsStaleReason(ui_state);
  }
  if (!ui_state.selected_test_condition() ||
      ui_state.selected_test_condition_is_stale()) {
    return UiLabel("検査マトリックスから使用可能または候補のセルを選択してください",
                   "Select an available or candidate cell from the test matrix");
  }
  if (!ui_state.last_run_ok()) {
    return UiLabel("エラー概要とフォーマット対応状況を確認してください",
                   "Review the error summary and format compatibility");
  }
  return UiLabel("開始できます", "Ready to start");
}

void RenderTopStatusRibbon(aptt::DiagnosticUiState& ui_state) {
  const std::string selected_device = ui_state.selected_device()
      ? Shorten(ui_state.selected_device()->display_name, 32)
      : UiLabel("未選択", "Not selected");
  const std::string accepted = ui_state.selected_playback_format()
      ? FormatSummary(*ui_state.selected_playback_format())
      : UiLabel("なし", "None");
  const std::string bundle = ui_state.bundle_path()
      ? Shorten(ui_state.bundle_path()->string(), 42)
      : UiLabel("なし", "None");
  const std::string status = Shorten(ui_state.status_text(), 120);
  const std::string backend_error =
      Shorten(ui_state.last_backend_error_summary(), 140);
  const std::string safety = IsKnownProblemSelection(ui_state)
      ? UiLabel("既知の注意デバイス", "Known-problem device")
      : HoldModeLabel(ui_state.settings().hold_mode);

  if (ImGui::BeginTable("top-status-ribbon", 4,
                        ImGuiTableFlags_BordersInnerV |
                            ImGuiTableFlags_SizingStretchProp |
                            ImGuiTableFlags_NoHostExtendX)) {
    ImGui::TableSetupColumn("app",
                            ImGuiTableColumnFlags_WidthFixed,
                            190.0F);
    ImGui::TableSetupColumn("selection",
                            ImGuiTableColumnFlags_WidthStretch,
                            1.0F);
    ImGui::TableSetupColumn("format",
                            ImGuiTableColumnFlags_WidthStretch,
                            1.2F);
    ImGui::TableSetupColumn("diagnostics",
                            ImGuiTableColumnFlags_WidthStretch,
                            1.0F);
    ImGui::TableNextRow();
    ImGui::TableSetColumnIndex(0);
    ImGui::Text("%s", Text().app_title);
    TextKeyValueWrapped(UiLabel("バージョン", "Version"),
                        aptt::kVersionString);
    TextKeyValueWrapped(UiLabel("稼働中", "Active"),
                        ActiveBackendName(ui_state));
    ImGui::TableSetColumnIndex(1);
    TextKeyValueWrapped(UiLabel("再生方式", "Backend"),
                        BackendLabel(ui_state.settings().requested_backend));
    TextKeyValueWrapped(UiLabel("対象デバイス", "Target device"),
                        selected_device);
    TextKeyValueWrapped(UiLabel("状態", "Status"), status);
    ImGui::TableSetColumnIndex(2);
    TextKeyValueWrapped(UiLabel("選択フォーマット", "Selected format"),
                        accepted);
    TextKeyValueWrapped(UiLabel("選択状態", "Selection state"),
                        AcceptedFormatStateLabel(ui_state));
    ImGui::TableSetColumnIndex(3);
    TextKeyValueWrapped(UiLabel("デバイス保持", "Device hold"), safety);
    TextKeyValueWrapped(UiLabel("最後のエラー", "Last error"),
                        backend_error);
    TextKeyValueWrapped(UiLabel("診断データ", "Diagnostic data"), bundle);
    ImGui::EndTable();
  }
}

void RenderNextActionBanner(const aptt::DiagnosticUiState& ui_state) {
  ImGui::TextWrapped("%s: %s", UiLabel("次に必要な操作", "Next required action"),
                     NextRequiredAction(ui_state).c_str());
}

void RenderDeviceTable(aptt::DiagnosticUiState& ui_state) {
  if (ui_state.discovery_snapshot().devices.empty()) {
    ImGui::TextUnformatted(
        UiLabel("出力デバイスはまだ読み込まれていません。",
                "Output devices have not been loaded yet."));
    return;
  }
  if (ImGui::BeginTable("device-table", 4,
                        ImGuiTableFlags_Borders |
                            ImGuiTableFlags_RowBg |
                            ImGuiTableFlags_Resizable |
                            ImGuiTableFlags_ScrollY,
                        ImVec2(0.0F, 210.0F))) {
    ImGui::TableSetupColumn(UiLabel("状態", "Status"),
                            ImGuiTableColumnFlags_WidthFixed, 90.0F);
    ImGui::TableSetupColumn(UiLabel("既定", "Default"),
                            ImGuiTableColumnFlags_WidthFixed, 55.0F);
    ImGui::TableSetupColumn(UiLabel("出力デバイス", "Output device"));
    ImGui::TableSetupColumn(UiLabel("操作", "Action"),
                            ImGuiTableColumnFlags_WidthFixed, 92.0F);
    ImGui::TableHeadersRow();
    for (const auto& snapshot : ui_state.discovery_snapshot().devices) {
      const auto& device = snapshot.device;
      const std::string table_display_name =
          DeviceDisplayNameForTable(snapshot);
      const bool selected = ui_state.selected_device() &&
                            ui_state.selected_device()->stable_id ==
                                device.stable_id;
      ImGui::TableNextRow();
      ImGui::TableSetColumnIndex(0);
      ImGui::TextUnformatted(DeviceAvailabilityLabel(snapshot.availability));
      ImGui::TableSetColumnIndex(1);
      ImGui::TextUnformatted(device.is_default ? UiLabel("はい", "Yes") : "-");
      ImGui::TableSetColumnIndex(2);
      ImGui::PushID(device.stable_id.c_str());
      ImGui::BeginDisabled(HasAnyActiveBackend(ui_state));
      if (ImGui::Selectable(table_display_name.c_str(),
                            selected,
                            ImGuiSelectableFlags_SpanAllColumns)) {
        SelectDeviceForInspection(ui_state, device.stable_id);
      }
      ImGui::EndDisabled();
      if (HasAnyActiveBackend(ui_state) &&
          ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
        ImGui::SetTooltip("%s", Text().active_change_blocked);
      } else if (ImGui::IsItemHovered()) {
        if (device.backend == aptt::BackendApi::kKernelStreaming) {
          const auto filter = snapshot.backend_fields.find(
              "ks_filter_symbolic_link");
          const auto pin = snapshot.backend_fields.find("ks_pin_id");
          ImGui::SetTooltip(
              "%s\n%s: %s\npin: %s\nID: %s",
              table_display_name.c_str(),
              UiLabel("API", "API"),
              BackendLabel(device.backend),
              pin == snapshot.backend_fields.end() ? "unknown"
                                                   : pin->second.c_str(),
              filter == snapshot.backend_fields.end()
                  ? Shorten(device.stable_id, 64).c_str()
                  : Shorten(filter->second, 64).c_str());
        } else {
          ImGui::SetTooltip("%s\n%s: %s\nID: %s",
                            table_display_name.c_str(),
                            UiLabel("API", "API"),
                            BackendLabel(device.backend),
                            Shorten(device.stable_id, 64).c_str());
        }
      }
      ImGui::PopID();
      ImGui::TableSetColumnIndex(3);
      if (selected) {
        ImGui::TextColored(ImVec4(0.03F, 0.38F, 0.14F, 1.00F),
                           "%s",
                           UiLabel("選択中", "Selected"));
      } else {
        const std::string label =
            std::string(UiLabel("選択##", "Select##")) + device.stable_id;
        if (DisabledButton(label.c_str(),
                           HasAnyActiveBackend(ui_state),
                           Text().active_change_blocked,
                           ImVec2(-1.0F, 0.0F))) {
          SelectDeviceForInspection(ui_state, device.stable_id);
        }
      }
    }
    ImGui::EndTable();
  }
}

void RenderCapabilityMatrixTable(
    aptt::DiagnosticUiState& ui_state,
    const aptt::DeviceCapabilityMatrix& matrix,
    const std::vector<std::size_t>& row_indices,
    const std::vector<MatrixDisplayColumn>& display_columns,
    const char* table_id,
    float height,
    float format_column_width,
    float rate_column_width) {
  if (row_indices.empty()) {
    MutedTextWrapped(UiLabel("この区分の候補はありません。",
                             "No candidates in this section."));
    return;
  }

  const auto column_count =
      static_cast<int>(display_columns.size() + 1);
  if (ImGui::BeginTable(table_id,
                        column_count,
                        ImGuiTableFlags_Borders |
                            ImGuiTableFlags_RowBg |
                            ImGuiTableFlags_Resizable |
                            ImGuiTableFlags_ScrollX |
                            ImGuiTableFlags_ScrollY |
                            ImGuiTableFlags_SizingFixedFit,
                        ImVec2(0.0F, height))) {
    ImGui::TableSetupColumn(UiLabel("形式", "Format"),
                            ImGuiTableColumnFlags_WidthFixed,
                            format_column_width);
    for (const auto& display_column : display_columns) {
      ImGui::TableSetupColumn(display_column.label.c_str(),
                              ImGuiTableColumnFlags_WidthFixed,
                              rate_column_width);
    }
    ImGui::TableSetupScrollFreeze(1, 1);
    ImGui::TableHeadersRow();

    for (const auto row : row_indices) {
      ImGui::TableNextRow();
      ImGui::TableSetColumnIndex(0);
      ImGui::TextUnformatted(MatrixRowLabel(matrix.rows[row]).c_str());

      for (std::size_t display_column_index = 0;
           display_column_index < display_columns.size();
           ++display_column_index) {
        ImGui::TableSetColumnIndex(
            static_cast<int>(display_column_index + 1));
        const auto matrix_column = MatrixColumnForDisplayColumn(
            matrix, matrix.rows[row], display_columns[display_column_index]);
        if (!matrix_column) {
          ImGui::TextUnformatted("-");
          continue;
        }
        const auto cell_index =
            row * matrix.sample_rate_columns.size() + *matrix_column;
        if (cell_index >= matrix.cells.size()) {
          ImGui::TextUnformatted("-");
          continue;
        }
        const auto& cell = matrix.cells[cell_index];
        const bool selected =
            ui_state.selected_test_condition() &&
            !ui_state.selected_test_condition_is_stale() &&
            ui_state.selected_test_condition()->matrix_scan_revision ==
                matrix.scan_revision &&
            ui_state.selected_test_condition()->matrix_row == row &&
            ui_state.selected_test_condition()->matrix_column ==
                *matrix_column;
        const std::string reason = CapabilityCellDisabledReason(cell);
        if (selected) {
          ImGui::TextColored(ImVec4(0.03F, 0.38F, 0.14F, 1.00F),
                             "%s",
                             UiLabel("選", "Sel"));
        } else {
          const std::string label =
              std::string(CapabilityCellShortLabel(cell.result_status)) +
              "##" + table_id + "-" + std::to_string(row) + "-" +
              std::to_string(*matrix_column);
          ImGui::PushStyleColor(
              ImGuiCol_Button,
              CapabilityCellButtonColor(cell.result_status));
          ImGui::PushStyleColor(
              ImGuiCol_ButtonHovered,
              CapabilityCellButtonHoverColor(cell.result_status));
          ImGui::PushStyleColor(
              ImGuiCol_ButtonActive,
              CapabilityCellButtonHoverColor(cell.result_status));
          if (DisabledButton(label.c_str(),
                             !cell.selectable ||
                                 HasAnyActiveBackend(ui_state),
                             HasAnyActiveBackend(ui_state)
                                 ? Text().active_change_blocked
                                 : reason,
                             ImVec2(-1.0F, 0.0F))) {
            ui_state.SelectCapabilityMatrixCell(row, *matrix_column);
          }
          ImGui::PopStyleColor(3);
        }
        if (ImGui::IsItemHovered()) {
          std::ostringstream tooltip;
          tooltip << CapabilityCellStatusLabel(cell.result_status)
                  << "\n"
                  << BackendLabel(matrix.target_backend)
                  << "\n"
                  << UiLabel("要求フォーマット", "Requested format") << ": "
                  << FormatSummary(cell.requested_format);
          if (cell.accepted_format) {
            tooltip << "\n"
                    << UiLabel("使用可能", "Accepted") << ": "
                    << FormatSummary(*cell.accepted_format);
          }
          if (matrix.target_backend == aptt::BackendApi::kKernelStreaming) {
            tooltip << "\n"
                    << UiLabel("KSストリーミング方式", "KS streaming model")
                    << ": " << KernelStreamingModelUiLabel(cell);
            const auto implementation =
                CapabilityCellBackendField(cell, "ks_playback_implementation");
            if (!implementation.empty()) {
              tooltip << "\n"
                      << UiLabel("実装状態", "Implementation")
                      << ": " << KernelStreamingPlaybackStatusUiLabel(cell);
            }
          }
          if (!cell.error_symbol.empty() || !cell.error_code_hex.empty()) {
            tooltip << "\n" << cell.error_symbol << " "
                    << cell.error_code_hex;
          }
          if (!reason.empty()) {
            tooltip << "\n" << reason;
          }
          ImGui::SetTooltip("%s", tooltip.str().c_str());
        }
      }
    }
    ImGui::EndTable();
  }
}

void RenderSelectedCapabilityCellSummary(
    const aptt::DiagnosticUiState& ui_state,
    const aptt::DeviceCapabilityMatrix& matrix) {
  if (!ui_state.selected_test_condition()) {
    return;
  }
  const auto& condition = *ui_state.selected_test_condition();
  if (condition.matrix_scan_revision != matrix.scan_revision ||
      condition.matrix_row >= matrix.rows.size() ||
      condition.matrix_column >= matrix.sample_rate_columns.size()) {
    return;
  }
  const auto cell_index =
      condition.matrix_row * matrix.sample_rate_columns.size() +
      condition.matrix_column;
  if (cell_index >= matrix.cells.size()) {
    return;
  }

  SectionHeader(UiLabel("選択中のフォーマット", "Selected Format"));
  TextKeyValueWrapped(UiLabel("テスト条件", "Test condition"),
                      FormatSummary(condition.accepted_playback_format));
  TextKeyValueWrapped(UiLabel("状態", "Status"),
                      ui_state.selected_test_condition_is_stale()
                          ? UiLabel("再選択が必要", "Reselect required")
                          : CapabilityCellStatusLabel(
                                matrix.cells[cell_index].result_status));
  if (matrix.target_backend == aptt::BackendApi::kKernelStreaming) {
    TextKeyValueWrapped(UiLabel("KSストリーミング方式",
                                "KS streaming model"),
                        KernelStreamingModelUiLabel(matrix.cells[cell_index]));
  }
  if (matrix.cells[cell_index].result_status ==
      aptt::CapabilityCellStatus::kDataRangeMatch) {
    MutedTextWrapped(KernelStreamingDataRangeCandidateWarning());
  }
}

void RenderCapabilityMatrix(aptt::DiagnosticUiState& ui_state) {
  const auto& maybe_matrix = ui_state.device_capability_matrix();
  if (!maybe_matrix) {
    MutedTextWrapped(
        UiLabel("デバイスを選択すると対応状況を自動確認し、ここにフォーマット対応状況を表示します。",
                "Select a device to automatically check and show format compatibility here."));
    return;
  }

  const auto& matrix = *maybe_matrix;
  if (matrix.stale) {
    MutedTextWrapped(
        UiLabel("対応状況が古くなっています。対象デバイスを選び直すか、デバイス一覧を再読み込みしてください。",
                "Capability results are stale. Reselect the target device or refresh the device list."));
  }
  ImGui::Text("%s: %llu / %s: %zu",
              UiLabel("改訂", "Revision"),
              static_cast<unsigned long long>(matrix.scan_revision),
              UiLabel("形式行", "Format rows"),
              matrix.rows.size());
  MutedTextWrapped(MatrixLegendText());

  std::vector<std::size_t> pcm_rows;
  std::vector<std::size_t> dsd_rows;
  for (std::size_t row = 0; row < matrix.rows.size(); ++row) {
    if (matrix.rows[row].signal_mode == aptt::SignalMode::kPcm) {
      pcm_rows.push_back(row);
    } else {
      dsd_rows.push_back(row);
    }
  }

  SectionHeader(
      "PCM",
      UiLabel("PCM候補をサンプリングレート別に確認します。",
              "PCM candidates by sample rate."));
  RenderCapabilityMatrixTable(ui_state,
                              matrix,
                              pcm_rows,
                              PcmMatrixDisplayColumns(),
                              "capability-matrix-pcm-table",
                              220.0F,
                              230.0F,
                              94.0F);

  SectionHeader(
      "DSD",
      UiLabel("DoPキャリアとASIOネイティブDSDを分けて確認します。",
              "DoP carrier and ASIO Native DSD candidates."));
  RenderCapabilityMatrixTable(ui_state,
                              matrix,
                              dsd_rows,
                              DsdMatrixDisplayColumns(),
                              "capability-matrix-dsd-table",
                              190.0F,
                              220.0F,
                              92.0F);
  RenderSelectedCapabilityCellSummary(ui_state, matrix);
}

void RenderSignalStep(aptt::DiagnosticUiState& ui_state,
                      aptt::DiagnosticUiSettings& settings,
                      bool& settings_changed) {
  SectionHeader(
      UiLabel("テスト信号", "Test Signal"),
      UiLabel("通常は1 kHz、控えめなレベルで開始してください。DoPはビットパーフェクトな経路でのみ使用してください。",
              "Start with 1 kHz at a conservative level. Use DoP only on a bit-perfect path."));
  const bool active_locked = HasAnyActiveBackend(ui_state);
  ImGui::BeginDisabled(active_locked);
  float frequency_hz = static_cast<float>(settings.frequency_hz);
  ImGui::SetNextItemWidth(170.0F);
  if (ImGui::InputFloat(UiLabel("周波数 Hz", "Frequency Hz"), &frequency_hz)) {
    settings.frequency_hz = frequency_hz;
    settings_changed = true;
  }
  float amplitude_dbfs = static_cast<float>(settings.amplitude_dbfs);
  ImGui::SetNextItemWidth(210.0F);
  if (ImGui::SliderFloat(UiLabel("信号レベル dBFS", "Signal level dBFS"),
                         &amplitude_dbfs,
                         -120.0F,
                         0.0F)) {
    settings.amplitude_dbfs = amplitude_dbfs;
    settings_changed = true;
  }
  InputUint(UiLabel("再生時間 ms", "Duration ms"),
            settings.duration_ms,
            1,
            86400000,
            settings_changed);
  if (ImGui::Checkbox(UiLabel("連続再生", "Continuous playback"),
                      &settings.continuous)) {
    settings_changed = true;
  }
  ImGui::EndDisabled();

  const bool pcm_signal = ui_state.selected_test_condition() &&
                          ui_state.selected_playback_format() &&
                          ui_state.selected_playback_format()->signal_mode ==
                              aptt::SignalMode::kPcm;
  if (!pcm_signal) {
    return;
  }

  SectionHeader(UiLabel("PCMチャンネル設定", "PCM Channel Settings"));
  ImGui::BeginDisabled(active_locked);
  if (ImGui::Checkbox(UiLabel("左チャンネル", "Left channel"),
                      &settings.left_channel_enabled)) {
    settings_changed = true;
  }
  ImGui::SameLine();
  if (ImGui::Checkbox(UiLabel("右チャンネル", "Right channel"),
                      &settings.right_channel_enabled)) {
    settings_changed = true;
  }
  if (ImGui::Checkbox(UiLabel("右チャンネルの位相を反転",
                              "Invert right-channel phase"),
                      &settings.invert_right_phase)) {
    settings_changed = true;
  }
  float phase_offset = static_cast<float>(settings.phase_offset_degrees);
  ImGui::SetNextItemWidth(210.0F);
  if (ImGui::SliderFloat(UiLabel("右チャンネル位相オフセット",
                                 "Right-channel phase offset"),
                         &phase_offset,
                         -180.0F,
                         180.0F)) {
    settings.phase_offset_degrees = phase_offset;
    settings_changed = true;
  }
  ImGui::EndDisabled();
}

void RenderBufferLifecycleStep(const aptt::DiagnosticUiState& ui_state,
                               aptt::DiagnosticUiSettings& settings,
                               bool& settings_changed) {
  SectionHeader(
      UiLabel("バッファー / デバイス保持", "Buffer / Device Hold"),
      UiLabel("通常は信号停止後も無音保持を選びます。USB DACによっては、完全に解放すると再認識に時間がかかる場合があります。",
              "Normally keep valid silence after the signal stops. Some USB DACs can take time to recover after full release."));
  const bool active_locked = HasAnyActiveBackend(ui_state);
  ImGui::BeginDisabled(active_locked);
  SectionHeader(UiLabel("API別バッファー / スケジューリング",
                        "API Buffer / Scheduling"));
  switch (settings.requested_backend) {
    case aptt::BackendApi::kMme:
      InputUint(UiLabel("waveOut バッファー数", "waveOut buffer count"),
                settings.mme_buffer_count,
                2,
                64,
                settings_changed);
      InputUint(UiLabel("waveOut バッファー長 ms", "waveOut buffer ms"),
                settings.mme_buffer_duration_ms,
                1,
                60000,
                settings_changed);
      ImGui::TextDisabled("%s",
                          UiLabel("通知: CALLBACK_EVENT",
                                  "Notification: CALLBACK_EVENT"));
      break;
    case aptt::BackendApi::kDirectSound:
      InputUint(UiLabel("二次バッファー長 ms", "Secondary buffer ms"),
                settings.directsound_secondary_buffer_duration_ms,
                50,
                60000,
                settings_changed);
      InputUint(UiLabel("書き込みチャンク ms", "Write chunk ms"),
                settings.directsound_write_chunk_ms,
                1,
                60000,
                settings_changed);
      InputUint(UiLabel("カーソル監視間隔 ms", "Cursor poll ms"),
                settings.directsound_cursor_poll_interval_ms,
                1,
                1000,
                settings_changed);
      break;
    case aptt::BackendApi::kWasapiShared:
      InputUint(UiLabel("共有バッファー要求 ms", "Shared buffer request ms"),
                settings.wasapi_shared_buffer_duration_ms,
                1,
                60000,
                settings_changed);
      InputUint(UiLabel("レンダー監視間隔 ms", "Render poll ms"),
                settings.wasapi_shared_render_poll_interval_ms,
                1,
                1000,
                settings_changed);
      ImGui::TextDisabled("%s",
                          UiLabel("周期: 0 / イベント駆動: 無効",
                                  "Periodicity: 0 / event driven: off"));
      break;
    case aptt::BackendApi::kWasapiExclusive:
      if (ImGui::Checkbox(UiLabel("イベント駆動",
                                  "Event-driven render"),
                          &settings.wasapi_exclusive_event_callback_enabled)) {
        if (settings.wasapi_exclusive_event_callback_enabled) {
          settings.wasapi_exclusive_periodicity_ms =
              settings.wasapi_exclusive_buffer_duration_ms;
        }
        settings_changed = true;
      }
      InputUint(UiLabel("排他バッファー要求 ms", "Exclusive buffer request ms"),
                settings.wasapi_exclusive_buffer_duration_ms,
                1,
                5000,
                settings_changed);
      if (settings.wasapi_exclusive_event_callback_enabled) {
        settings.wasapi_exclusive_periodicity_ms =
            settings.wasapi_exclusive_buffer_duration_ms;
        ImGui::TextDisabled(
            "%s: %u ms",
            UiLabel("排他周期要求はバッファー長と同一",
                    "Exclusive periodicity follows buffer request"),
            settings.wasapi_exclusive_periodicity_ms);
        InputUint(UiLabel("イベント待機タイムアウト ms",
                          "Event wait timeout ms"),
                  settings.wasapi_exclusive_event_timeout_ms,
                  1,
                  60000,
                  settings_changed);
        if (ImGui::Checkbox(UiLabel("バッファーアライン補正を許可",
                                    "Allow buffer alignment retry"),
                            &settings.wasapi_exclusive_alignment_retry_enabled)) {
          settings_changed = true;
        }
      } else {
        InputUint(UiLabel("排他周期要求 ms（0=既定）",
                          "Exclusive periodicity ms (0=default)"),
                  settings.wasapi_exclusive_periodicity_ms,
                  0,
                  5000,
                  settings_changed);
        InputUint(UiLabel("レンダー監視間隔 ms", "Render poll ms"),
                  settings.wasapi_exclusive_render_poll_interval_ms,
                  1,
                  1000,
                  settings_changed);
        ImGui::TextDisabled("%s",
                            UiLabel("駆動方式: タイマー/ポーリング",
                                    "Drive mode: timer / polling"));
      }
      break;
    case aptt::BackendApi::kAsio:
      if (ImGui::Checkbox(
              UiLabel("対応時に ASIOOutputReady を呼ぶ",
                      "Call ASIOOutputReady when supported"),
              &settings.asio_use_output_ready_if_supported)) {
        settings_changed = true;
      }
      ImGui::TextDisabled("%s",
                          UiLabel("バッファー長: ドライバー推奨値",
                                  "Buffer size: driver preferred"));
      break;
    case aptt::BackendApi::kKernelStreaming:
      ImGui::TextDisabled(
          "%s",
          UiLabel("KSは選択済みフィルター/ピン/受理済みPCMまたはDoPキャリアで実行します。",
                  "KS runs only on the selected filter, pin, and accepted PCM or DoP carrier format."));
      ImGui::TextDisabled(
          "%s",
          UiLabel("通常停止は有効なPCM無音またはDoP無音で保持し、完全解放は下段の解放操作で行います。",
                  "Normal stop keeps valid PCM or DoP silence; full release is done with the release action below."));
      break;
    case aptt::BackendApi::kNull:
      ImGui::TextDisabled("%s",
                          UiLabel("ソフトウェア検証のみ",
                                  "Software-only simulation"));
      break;
  }

  if (settings.requested_backend != aptt::BackendApi::kNull) {
    SectionHeader(
        UiLabel("スレッド優先度 / MMCSS", "Thread Priority / MMCSS"),
        UiLabel("アプリが所有するレンダー/監視スレッドをMMCSSへ登録し、登録成否とスレッドIDをログへ残します。",
                "Registers app-owned render/poll threads with MMCSS and logs the result plus thread ID."));
    if (ImGui::Checkbox(UiLabel("MMCSSを使用", "Use MMCSS"),
                        &settings.audio_thread_mmcss_enabled)) {
      settings_changed = true;
    }
    int task_index =
        settings.audio_thread_mmcss_task_name == "Audio" ? 1 : 0;
    const char* const task_names[] = {"Pro Audio", "Audio"};
    if (ImGui::Combo(UiLabel("MMCSSタスク", "MMCSS task"),
                     &task_index,
                     task_names,
                     IM_ARRAYSIZE(task_names))) {
      settings.audio_thread_mmcss_task_name = task_names[task_index];
      settings_changed = true;
    }
    int priority_index = settings.audio_thread_mmcss_priority + 1;
    const char* const* priority_labels = IsJapaneseUi()
        ? kMmcssPrioritiesJapanese
        : kMmcssPrioritiesEnglish;
    if (ImGui::Combo(UiLabel("相対優先度", "Relative priority"),
                     &priority_index,
                     priority_labels,
                     IM_ARRAYSIZE(kMmcssPrioritiesEnglish))) {
      settings.audio_thread_mmcss_priority = priority_index - 1;
      settings_changed = true;
    }
    if (settings.requested_backend == aptt::BackendApi::kAsio) {
      MutedTextWrapped(
          UiLabel("ASIOはドライバー所有のコールバックスレッドで呼ばれる場合があるため、この設定は現時点ではアプリ所有スレッドにだけ適用されます。",
                  "ASIO callbacks may run on a driver-owned thread, so this setting is currently applied only to app-owned threads."));
    }

    ImGui::Spacing();
    SectionHeader(
        UiLabel("高負荷診断", "High-Load Diagnostics"),
        UiLabel("通常の音出し確認では使いません。意図的にレンダー/コールバックを遅らせ、ドロップアウト診断ログを得るための危険な実験モードです。",
                "Not for normal tone checks. This risky diagnostic mode intentionally delays rendering/callbacks to capture dropout evidence."));
    ImGui::TextColored(
        ImVec4(0.74F, 0.18F, 0.12F, 1.0F),
        "%s",
        UiLabel("明示的な高負荷テスト専用です。停止、排出、クールダウン、解放ログを必ず確認してください。",
                "Explicit high-load testing only. Check stop, drain, cooldown, and release logs."));
    if (ImGui::Checkbox(UiLabel("高負荷診断を有効化",
                                "Enable high-load diagnostics"),
                        &settings.high_load_diagnostics_enabled)) {
      if (!settings.high_load_diagnostics_enabled) {
        settings.high_load_risk_acknowledged = false;
      }
      settings_changed = true;
    }
    ImGui::BeginDisabled(!settings.high_load_diagnostics_enabled);
    if (ImGui::Checkbox(UiLabel("危険性を理解して実行する",
                                "Acknowledge diagnostic risk"),
                        &settings.high_load_risk_acknowledged)) {
      settings_changed = true;
    }
    InputUint(UiLabel("注入遅延 ms", "Injected delay ms"),
              settings.high_load_render_delay_ms,
              1,
              500,
              settings_changed);
    InputUint(UiLabel("遅延間隔 callbacks", "Delay every callbacks"),
              settings.high_load_delay_every_callbacks,
              1,
              1000,
              settings_changed);
    ImGui::EndDisabled();
  }

  SectionHeader(UiLabel("デバイス保持", "Device Hold"));
  int hold_index =
      settings.hold_mode == aptt::HoldMode::kHoldInitialized ? 1 : 0;
  const char* const* hold_labels =
      IsJapaneseUi() ? kSignalHoldModes : kSignalHoldModesEnglish;
  if (ImGui::Combo(UiLabel("信号停止後の保持", "Hold after signal stop"),
                   &hold_index,
                   hold_labels,
                   IM_ARRAYSIZE(kSignalHoldModes))) {
    settings.hold_mode = hold_index == 0
        ? aptt::HoldMode::kKeepWarmAfterStop
        : aptt::HoldMode::kHoldInitialized;
    settings_changed = true;
  }
  MutedTextWrapped(
      UiLabel("完全な解放は、信号停止後に下部の「保持中デバイスを解放」から実行します。",
              "Full release is performed after the signal stops with the Release held device action."));
  if (ImGui::Checkbox(UiLabel("無音ストリームを維持",
                              "Keep silence stream alive"),
                      &settings.keep_alive_stream_enabled)) {
    settings_changed = true;
  }
  if (ImGui::Checkbox(UiLabel("停止前に排出する", "Drain before stop"),
                      &settings.drain_before_stop)) {
    settings_changed = true;
  }
  InputUint(UiLabel("排出タイムアウト ms", "Drain timeout ms"),
            settings.drain_timeout_ms, 1, 120000,
            settings_changed);
  InputUint(UiLabel("解放クールダウン ms", "Release cooldown ms"),
            settings.release_cooldown_ms, 1, 120000,
            settings_changed);
  InputUint(UiLabel("再取得クールダウン ms", "Reacquire cooldown ms"),
            settings.reacquire_cooldown_ms, 1, 120000,
            settings_changed);
  InputUint(UiLabel("再取得回数上限", "Max reacquire attempts"),
            settings.max_reacquire_attempts, 0, 10,
            settings_changed);
  if (ImGui::Checkbox(UiLabel("急速なフォーマット切替を防止",
                              "Prevent rapid format cycling"),
                      &settings.rapid_format_cycle_guard)) {
    settings_changed = true;
  }
  if (ImGui::Checkbox(UiLabel("危険な解放操作を明示承認",
                              "Explicitly acknowledge risky release operations"),
                      &settings.expert_unsafe_release_ack)) {
    settings_changed = true;
  }
  ImGui::EndDisabled();
}

void RenderRunExportStep(aptt::DiagnosticUiState& ui_state) {
  SectionHeader(
      UiLabel("実行 / 書き出し", "Run / Export"),
      UiLabel("選択済みの検査条件を開始し、停止後に必要な診断データを書き出します。",
              "Start the selected test condition and export diagnostics after stopping if needed."));
  std::string start_reason = Text().probe_first;
  if (HasAnyActiveBackend(ui_state)) {
    start_reason = ActiveStartDisabledReason(ui_state);
  } else if (ui_state.selected_playback_backend() &&
             ui_state.selected_playback_format()) {
    start_reason = StartDisabledReason(
        ui_state,
        *ui_state.selected_playback_backend(),
        ui_state.selected_playback_format()->signal_mode);
  } else if (!ui_state.selected_device()) {
    start_reason = Text().select_device_first;
  } else if (!ui_state.selected_test_condition()) {
    start_reason = UiLabel("検査マトリックスからテスト条件を選択してください。",
                           "Select a test condition from the test matrix.");
  }
  if (DisabledButton(UiLabel("選択条件で開始", "Start selected condition"),
                     !start_reason.empty(),
                     start_reason)) {
    StartSelectedFormat(ui_state);
  }

  ImGui::SeparatorText(UiLabel("信号停止 / デバイス解放",
                               "Signal Stop / Device Release"));
  const bool no_active = !HasAnyActiveBackend(ui_state);
  if (DisabledButton(UiLabel("信号停止 / 保持", "Stop signal / hold"),
                     no_active,
                     Text().no_active_backend)) {
    StopActiveBackend(ui_state);
  }
  if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
    ImGui::SetTooltip("%s", StopHoldTooltip());
  }
  RenderHeldDeviceReleaseAcknowledgement(ui_state);
  const auto release_reason = ReleaseAfterStopDisabledReason(ui_state);
  if (DisabledButton(UiLabel("保持中デバイスを解放",
                             "Release held device"),
                     !release_reason.empty(),
                     release_reason)) {
    ReleaseActiveBackend(ui_state);
  }

  ImGui::SeparatorText(UiLabel("書き出し", "Export"));
  if (DisabledButton(Text().export_bundle,
                     !ui_state.has_exportable_diagnostic(),
                     UiLabel("診断を実行してから書き出してください。",
                             "Run a diagnostic before exporting."))) {
    ui_state.ExportDiagnosticBundle();
  }

  ImGui::SeparatorText(UiLabel("ソフトウェアのみの確認",
                               "Software-only Check"));
  if (DisabledButton(UiLabel("Null診断を実行", "Run Null diagnostic"),
                     HasAnyActiveBackend(ui_state),
                     Text().active_change_blocked)) {
    ui_state.RunNullSession();
  }
  ImGui::SameLine();
  if (DisabledButton(UiLabel("Null診断 + 書き出し",
                             "Run Null diagnostic + export"),
                     HasAnyActiveBackend(ui_state),
                     Text().active_change_blocked)) {
    ui_state.RunNullSession();
    ui_state.ExportDiagnosticBundle();
  }
}

void RenderAdvancedStep(aptt::DiagnosticUiState& ui_state,
                        aptt::DiagnosticUiSettings& settings,
                        bool& settings_changed) {
  ImGui::TextWrapped(
      "%s",
      UiLabel("診断記録、注意事項、選択IDを確認します。再生条件そのものは前の手順で確定します。",
              "Review diagnostic logging, safety notes, and selection IDs. Playback conditions are finalized in the previous steps."));
  if (ImGui::CollapsingHeader(UiLabel("ログ設定", "Log Settings"))) {
    int log_dir_index = settings.log_directory == "diagnostic_bundles/callback_trace"
        ? 2
        : settings.log_directory == "diagnostic_bundles/manual" ? 1 : 0;
    if (ImGui::Combo(UiLabel("ログ保存先", "Log destination"),
                     &log_dir_index,
                     kLogDirectories,
                     IM_ARRAYSIZE(kLogDirectories))) {
      settings.log_directory = kLogDirectories[log_dir_index];
      settings_changed = true;
    }
    int log_format_index = static_cast<int>(settings.log_format);
    if (ImGui::Combo(UiLabel("ログ形式", "Log format"),
                     &log_format_index,
                     kLogFormats,
                     IM_ARRAYSIZE(kLogFormats))) {
      settings.log_format =
          static_cast<aptt::DiagnosticLogFormat>(log_format_index);
      settings_changed = true;
    }
    int log_level_index = static_cast<int>(settings.log_level);
    const char* const* log_level_labels = IsJapaneseUi()
        ? kLogLevels
        : kLogLevelsEnglish;
    if (ImGui::Combo(UiLabel("ログレベル", "Log level"),
                     &log_level_index,
                     log_level_labels,
                     IM_ARRAYSIZE(kLogLevels))) {
      settings.log_level =
          static_cast<aptt::DiagnosticLogLevel>(log_level_index);
      settings_changed = true;
    }
    if (ImGui::Checkbox(UiLabel("初期化情報を記録",
                                "Record initialization details"),
                        &settings.initialization_dump_enabled)) {
      settings_changed = true;
    }
    if (ImGui::Checkbox(UiLabel("コールバックログ", "Callback log"),
                        &settings.callback_event_logging)) {
      settings_changed = true;
    }
    InputUint(UiLabel("コールバックログ上限", "Callback log limit"),
              settings.callback_trace_limit, 1, 1000000,
              settings_changed);
    InputUint(UiLabel("サマリー間隔 ms", "Summary interval ms"),
              settings.periodic_summary_interval_ms, 100, 3600000,
              settings_changed);
    if (ImGui::Checkbox(UiLabel("既存ログを上書き",
                                "Overwrite existing logs"),
                        &settings.overwrite_logs)) {
      settings_changed = true;
    }
  }
  if (ImGui::CollapsingHeader(UiLabel("安全上の注意", "Safety Notes"))) {
    const auto warnings = ui_state.settings_warnings();
    if (warnings.empty()) {
      ImGui::TextUnformatted(UiLabel("現在の設定に追加の注意はありません。",
                                     "No additional safety notes for the current settings."));
    } else {
      for (const auto& warning : warnings) {
        ImGui::TextWrapped("%s", warning.c_str());
      }
    }
  }
  if (ImGui::CollapsingHeader(UiLabel("選択ID / 低レベル情報",
                                      "Selection IDs / Low-level Info"))) {
    ImGui::TextWrapped("Selected device ID: %s",
                       ui_state.selected_device()
                           ? ui_state.selected_device()->stable_id.c_str()
                           : "none");
  }
}

void RenderAutomationStep(aptt::DiagnosticUiState& ui_state,
                          aptt::DiagnosticUiSettings& settings,
                          bool& settings_changed) {
  ImGui::TextWrapped(
      "%s",
      UiLabel("自動診断は、選択中の1デバイスと選択済み対応状況セルに対してのみ計画します。実行は安全な単発診断に限定されています。",
              "Automatic diagnostics are planned only for the selected device and selected compatibility cell. Execution is limited to a safe single diagnostic."));
  const bool active_locked = HasAnyActiveBackend(ui_state);
  ImGui::BeginDisabled(active_locked);
  if (ImGui::Checkbox(UiLabel("フォーマットマトリクス（計画のみ）",
                              "Format matrix (plan only)"),
                      &settings.automatic_format_matrix_enabled)) {
    settings_changed = true;
  }
  if (ImGui::Checkbox(UiLabel("バッファー段階変更（計画のみ）",
                              "Buffer ramp (plan only)"),
                      &settings.automatic_buffer_ramp_enabled)) {
    settings_changed = true;
  }
  if (ImGui::Checkbox(UiLabel("開始/停止ストレス（要注意）",
                              "Start/stop stress (Caution)"),
                      &settings.automatic_start_stop_stress_enabled)) {
    settings_changed = true;
  }
  if (ImGui::Checkbox(UiLabel("再初期化ループ（要注意）",
                              "Reinitialize loop (Caution)"),
                      &settings.automatic_reinitialize_enabled)) {
    settings_changed = true;
  }
  ImGui::EndDisabled();
  const bool can_auto_plan =
      ui_state.selected_device().has_value() &&
      ui_state.selected_playback_format().has_value() &&
      ui_state.selected_test_condition().has_value() &&
      !ui_state.selected_test_condition_is_stale() &&
      !ui_state.accepted_format_is_stale() &&
      !active_locked;
  const char* auto_reason = active_locked
      ? Text().active_change_blocked
      : ui_state.accepted_format_is_stale()
            ? Text().stale_probe
            : UiLabel("対象デバイスと検査マトリックスのテスト条件を選択してください。",
                      "Select a target device and test condition from the matrix.");
  if (DisabledButton(UiLabel("自動診断を計画", "Plan automatic diagnostic"),
                     !can_auto_plan,
                     auto_reason)) {
    ui_state.PlanAutomaticSingleDeviceDiagnostic();
  }
  ImGui::SameLine();
  if (DisabledButton(UiLabel("単発自動診断を実行",
                             "Run single automatic diagnostic"),
                     !can_auto_plan,
                     auto_reason)) {
    ui_state.RunAutomaticSingleDeviceDiagnostic();
  }
}

void RenderStatusPane(aptt::DiagnosticUiState& ui_state);

void RenderSelectedDeviceSummary(aptt::DiagnosticUiState& ui_state,
                                 aptt::DiagnosticUiSettings& settings,
                                 bool& settings_changed) {
  if (!ui_state.selected_device()) {
    MutedTextWrapped(UiLabel("まだ対象デバイスは選択されていません。",
                             "No target device is selected yet."));
    return;
  }

  const auto& device = *ui_state.selected_device();
  const auto* selected_snapshot = SelectedDeviceSnapshot(ui_state);
  const std::string display_name =
      selected_snapshot != nullptr
          ? DeviceDisplayNameForTable(*selected_snapshot)
          : device.display_name;
  if (ImGui::BeginTable("selected-device-summary", 2,
                        ImGuiTableFlags_BordersInnerV |
                            ImGuiTableFlags_SizingStretchProp)) {
    ImGui::TableSetupColumn("labels", ImGuiTableColumnFlags_WidthFixed, 130.0F);
    ImGui::TableSetupColumn("values");
    ImGui::TableNextRow();
    ImGui::TableSetColumnIndex(0);
    TextKeyValueWrapped(UiLabel("API", "API"), BackendLabel(device.backend));
    ImGui::TableSetColumnIndex(1);
    TextKeyValueWrapped(UiLabel("対象デバイス", "Target device"),
                        display_name);
    ImGui::TableNextRow();
    ImGui::TableSetColumnIndex(0);
    TextKeyValueWrapped(UiLabel("状態", "State"),
                        ui_state.device_capability_matrix()
                            ? UiLabel("対応状況確認済み", "Capabilities checked")
                            : UiLabel("対応状況確認待ち", "Waiting for capability check"));
    ImGui::TableSetColumnIndex(1);
    TextKeyValueWrapped("ID", device.stable_id);
    ImGui::EndTable();
  }

  if (DisabledButton(UiLabel("IDをコピー", "Copy ID"),
                     false,
                     "")) {
    ImGui::SetClipboardText(device.stable_id.c_str());
  }
  ImGui::SameLine();
  if (ImGui::Checkbox(UiLabel("注意が必要なUSB DACとして扱う",
                              "Treat as known-problem USB DAC"),
                      &settings.manual_known_problem_device)) {
    settings_changed = true;
  }
}

void RenderOutputPathTab(aptt::DiagnosticUiState& ui_state,
                         aptt::DiagnosticUiSettings& settings,
                         bool& settings_changed) {
  const bool active_locked = HasAnyActiveBackend(ui_state);
  SectionHeader(
      UiLabel("読み込み対象API", "Device List API"),
      UiLabel("ここで選んだAPIだけを読み込み、デバイス選択後に対応状況を自動確認します。",
              "Only the selected API is loaded. Capabilities are checked automatically after device selection."));

  int standard_backend_index = 0;
  for (int index = 0; index < IM_ARRAYSIZE(kStandardBackends); ++index) {
    if (settings.requested_backend == kStandardBackends[index]) {
      standard_backend_index = index;
    }
  }
  const char* const* labels = IsJapaneseUi()
      ? kStandardBackendLabelsJapanese
      : kStandardBackendLabelsEnglish;
  ImGui::BeginDisabled(active_locked);
  ImGui::SetNextItemWidth(220.0F);
  if (ImGui::Combo(UiLabel("読み込み対象API", "Target API"),
                   &standard_backend_index,
                   labels,
                   IM_ARRAYSIZE(kStandardBackends))) {
    settings.requested_backend = kStandardBackends[standard_backend_index];
    ui_state.UpdateSettings(settings);
    settings_changed = false;
  }
  ImGui::SameLine();
  if (DisabledButton(UiLabel("デバイスを読み込み", "Load devices"),
                     active_locked,
                     Text().active_change_blocked)) {
    RefreshRequestedBackend(ui_state);
  }
  ImGui::EndDisabled();
  if (settings.requested_backend == aptt::BackendApi::kKernelStreaming) {
    MutedTextWrapped(UiLabel(
        "Kernel Streamingスキャンは、対象デバイスのKSフィルターを開いてピン/データレンジを確認し、WaveRT判定ではRUNなしで短時間の通知バッファ取得probeを行います。再生は行いませんが、ドライバーによっては一時的にデバイスを使用中にする場合があります。",
        "Kernel Streaming scans open KS filters, inspect pins/data ranges, and may perform a short no-RUN notification-buffer probe for WaveRT classification. They do not play audio, but some drivers may temporarily mark the device as in use."));
  }

  SectionHeader(
      UiLabel("出力デバイス", "Output Device"),
      UiLabel("検査するデバイスを選択してください。選択すると、フォーマット対応状況の確認まで自動で進みます。",
              "Select the device to inspect. Selecting it automatically checks format compatibility."));
  RenderSelectedDeviceSummary(ui_state, settings, settings_changed);
  ImGui::Spacing();
  RenderDeviceTable(ui_state);

  SectionHeader(
      UiLabel("対応状況マトリックス", "Compatibility Matrix"),
      UiLabel("セルは選択したAPIで確認した対応状況です。使用可能または候補のセルを選んで、テスト条件を作成できます。",
              "Cells show compatibility checked for the selected API. Select an available or candidate cell to create a test condition."));
  if (ui_state.device_capability_matrix()) {
    const auto& matrix = *ui_state.device_capability_matrix();
    ImGui::Text("%s: %s / %s: %zu",
                UiLabel("確認状態", "Check state"),
                matrix.stale ? UiLabel("再確認が必要", "Needs refresh")
                             : UiLabel("確認済み", "Checked"),
                UiLabel("形式行", "Format rows"),
                matrix.rows.size());
  }
  RenderCapabilityMatrix(ui_state);
}

void RenderSelectedTestConditionSummary(
    const aptt::DiagnosticUiState& ui_state) {
  SectionHeader(
      UiLabel("選択中の検査条件", "Selected Test Condition"),
      UiLabel("出力経路タブで選んだ対応状況セルが、ここで実行条件になります。",
              "The compatibility cell selected in Output Path becomes the run condition here."));
  if (!ui_state.selected_test_condition()) {
    MutedTextWrapped(
        UiLabel("出力経路タブで使用可能または候補のフォーマットセルを選択してください。",
                "Select an available or candidate format cell in the Output Path tab."));
    return;
  }

  const auto& condition = *ui_state.selected_test_condition();
  TextKeyValueWrapped(UiLabel("対象デバイス", "Target device"),
                      condition.target_device.display_name);
  TextKeyValueWrapped(UiLabel("再生方式", "Backend"),
                      BackendLabel(condition.backend));
  TextKeyValueWrapped(UiLabel("検査フォーマット", "Test format"),
                      FormatSummary(condition.accepted_playback_format));
  std::ostringstream signal;
  signal << condition.signal_frequency_hz << " Hz / "
         << condition.signal_amplitude_dbfs << " dBFS / "
         << condition.duration_ms << " ms";
  TextKeyValueWrapped(UiLabel("現在の信号設定", "Current signal setting"),
                      signal.str());
  TextKeyValueWrapped(
      UiLabel("開始状態", "Start state"),
      ui_state.selected_test_condition_is_stale()
          ? UiLabel("再選択が必要", "Reselect required")
          : UiLabel("開始可能", "Ready"));
  if (condition.backend == aptt::BackendApi::kKernelStreaming &&
      condition.capability_status ==
          aptt::CapabilityCellStatus::kDataRangeMatch) {
    MutedTextWrapped(KernelStreamingDataRangeCandidateWarning());
  }
}

void RenderTestConditionsTab(aptt::DiagnosticUiState& ui_state,
                             aptt::DiagnosticUiSettings& settings,
                             bool& settings_changed) {
  RenderSelectedTestConditionSummary(ui_state);
  ImGui::Spacing();

  const float available_width = ImGui::GetContentRegionAvail().x;
  if (available_width > 980.0F &&
      ImGui::BeginTable("test-condition-columns", 2,
                        ImGuiTableFlags_BordersInnerV |
                            ImGuiTableFlags_SizingStretchSame)) {
    ImGui::TableSetupColumn("signal");
    ImGui::TableSetupColumn("drive");
    ImGui::TableNextRow();
    ImGui::TableSetColumnIndex(0);
    RenderSignalStep(ui_state, settings, settings_changed);
    ImGui::TableSetColumnIndex(1);
    RenderBufferLifecycleStep(ui_state, settings, settings_changed);
    ImGui::EndTable();
  } else {
    RenderSignalStep(ui_state, settings, settings_changed);
    ImGui::Spacing();
    RenderBufferLifecycleStep(ui_state, settings, settings_changed);
  }

  ImGui::Spacing();
  RenderRunExportStep(ui_state);
  ImGui::Spacing();
  if (ImGui::CollapsingHeader(UiLabel("自動診断", "Automation"),
                              ImGuiTreeNodeFlags_SpanAvailWidth)) {
    RenderAutomationStep(ui_state, settings, settings_changed);
  }
}

void RenderLogsTab(aptt::DiagnosticUiState& ui_state,
                   aptt::DiagnosticUiSettings& settings,
                   bool& settings_changed) {
  SectionHeader(
      UiLabel("ログ / 状態", "Logs / Status"),
      UiLabel("左側で記録設定、右側で実行状態とログを確認します。",
              "Review logging settings on the left and runtime state plus logs on the right."));

  const float available_width = ImGui::GetContentRegionAvail().x;
  if (available_width > 1050.0F &&
      ImGui::BeginTable("logs-columns", 2,
                        ImGuiTableFlags_BordersInnerV |
                            ImGuiTableFlags_SizingStretchProp)) {
    ImGui::TableSetupColumn("settings", ImGuiTableColumnFlags_WidthStretch, 0.8F);
    ImGui::TableSetupColumn("runtime", ImGuiTableColumnFlags_WidthStretch, 1.2F);
    ImGui::TableNextRow();
    ImGui::TableSetColumnIndex(0);
    RenderAdvancedStep(ui_state, settings, settings_changed);
    ImGui::TableSetColumnIndex(1);
    RenderStatusPane(ui_state);
    ImGui::EndTable();
  } else {
    RenderAdvancedStep(ui_state, settings, settings_changed);
    ImGui::Spacing();
    RenderStatusPane(ui_state);
  }
}

void RenderStatusPane(aptt::DiagnosticUiState& ui_state);

void RenderDiagnosticFlow(aptt::DiagnosticUiState& ui_state) {
  auto settings = ui_state.settings();
  bool settings_changed = false;

  if (ImGui::BeginTabBar("diagnostic-main-tabs")) {
    if (ImGui::BeginTabItem(UiLabel("出力経路", "Output Path"))) {
      RenderOutputPathTab(ui_state, settings, settings_changed);
      ImGui::EndTabItem();
    }

    if (ImGui::BeginTabItem(UiLabel("テスト条件", "Test Conditions"))) {
      RenderTestConditionsTab(ui_state, settings, settings_changed);
      ImGui::EndTabItem();
    }

    if (ImGui::BeginTabItem(UiLabel("ログ", "Logs"))) {
      RenderLogsTab(ui_state, settings, settings_changed);
      ImGui::EndTabItem();
    }

    ImGui::EndTabBar();
  }

  if (settings_changed) {
    ui_state.UpdateSettings(settings);
  }
}

void RenderStatusPane(aptt::DiagnosticUiState& ui_state) {
  const auto& stats = ui_state.stats();
  ImGui::SeparatorText(UiLabel("再生状態", "Playback Status"));
  TextKeyValueWrapped(UiLabel("状態", "Status"), ui_state.status_text());
  ImGui::Text("%s: %s", UiLabel("稼働中", "Active"),
              ActiveBackendName(ui_state).c_str());
  ImGui::Text("%s: %llu", UiLabel("検出デバイス数", "Discovered devices"),
              static_cast<unsigned long long>(
                  ui_state.discovery_snapshot().devices.size()));
  ImGui::SeparatorText(UiLabel("バッファー状態", "Buffer Status"));
  ImGui::Text("%s: %llu", UiLabel("生成フレーム", "Frames generated"),
              static_cast<unsigned long long>(stats.frames_generated));
  ImGui::Text("%s: %llu", UiLabel("送信フレーム", "Frames submitted"),
              static_cast<unsigned long long>(stats.frames_submitted));
  ImGui::Text("%s: %llu", UiLabel("受理フレーム", "Frames accepted"),
              static_cast<unsigned long long>(stats.frames_accepted));
  ImGui::Text("%s: %llu", UiLabel("コールバック", "Callbacks"),
              static_cast<unsigned long long>(stats.callback_count));
  ImGui::Text("%s: %llu", UiLabel("バッファー切れ/不足", "Underruns"),
              static_cast<unsigned long long>(stats.underrun_count));
  ImGui::Text("%s: %llu", UiLabel("不連続", "Discontinuities"),
              static_cast<unsigned long long>(stats.discontinuity_count));
  ImGui::Text("%s: %llu", UiLabel("デバイス無効化", "Device invalidations"),
              static_cast<unsigned long long>(stats.device_invalidated_count));

  if (ui_state.last_pcm_summary()) {
    const auto& summary = *ui_state.last_pcm_summary();
    ImGui::SeparatorText(UiLabel("PCMサマリー", "PCM Summary"));
    ImGui::Text("%s: %s", UiLabel("方式", "Backend"),
                BackendLabel(summary.backend));
    ImGui::Text("%s: %llu", UiLabel("受理フレーム", "Frames accepted"),
                static_cast<unsigned long long>(
                    summary.common_counters.frames_accepted));
  }
  if (ui_state.last_automatic_plan()) {
    const auto& plan = *ui_state.last_automatic_plan();
    ImGui::SeparatorText(UiLabel("自動診断", "Automation"));
    ImGui::Text("%s: %s / %llu step(s)", UiLabel("計画", "Plan"),
                plan.accepted ? "accepted" : "rejected",
                static_cast<unsigned long long>(plan.steps.size()));
  }
  if (ui_state.last_diagnostic_score()) {
    const auto& score = *ui_state.last_diagnostic_score();
    ImGui::Text("Score: %d / %s", score.score, score.rating.c_str());
  }
  if (ui_state.bundle_path()) {
    ImGui::SeparatorText(UiLabel("書き出し", "Export"));
    ImGui::TextWrapped("%s", ui_state.bundle_path()->string().c_str());
  }

  ImGui::Separator();
  if (ImGui::BeginTabBar("right-pane-tabs")) {
    if (ImGui::BeginTabItem(UiLabel("直近ログ", "Recent Log"))) {
      if (ui_state.log_lines().empty()) {
        ImGui::TextUnformatted(UiLabel("まだログはありません。",
                                       "No log entries yet."));
      } else {
        constexpr int kRecentLogLimit = 500;
        const auto& lines = ui_state.log_lines();
        const int total = static_cast<int>(lines.size());
        const int first = std::max(0, total - kRecentLogLimit);
        if (total > kRecentLogLimit) {
          ImGui::TextDisabled(
              "%s",
              UiLabel("直近500行を表示中。フルログは診断データに含まれます。",
                      "Showing the most recent 500 lines. Full logs are included in the diagnostic bundle."));
        }
        for (int row = first; row < total; ++row) {
          ImGui::TextWrapped("%s",
                             lines[static_cast<std::size_t>(row)].c_str());
        }
      }
      ImGui::EndTabItem();
    }
    if (ImGui::BeginTabItem(UiLabel("再生ログ", "Playback Log"))) {
      ImGui::Text("%s: %.3f ms",
                  UiLabel("想定コールバック間隔",
                          "Expected callback interval"),
                  stats.expected_callback_interval_ms);
      ImGui::Text("%s: %.3f ms",
                  UiLabel("最後のコールバック間隔",
                          "Last callback interval"),
                  stats.last_callback_interval_ms);
      ImGui::Text("%s: %.3f ms",
                  UiLabel("最大コールバック遅延",
                          "Max callback delay"),
                  stats.max_callback_delay_ms);
      ImGui::EndTabItem();
    }
    if (ImGui::BeginTabItem(UiLabel("エラー概要", "Error Summary"))) {
      ImGui::TextWrapped("%s",
                         ui_state.last_backend_error_summary().c_str());
      ImGui::TextWrapped("%s",
                         ui_state.last_run_ok()
                             ? UiLabel("失敗した操作は記録されていません。",
                                       "No failed operation is recorded.")
                             : UiLabel("最後の操作が失敗したか、エラーを報告しています。",
                                       "The last operation failed or reported an error."));
      ImGui::EndTabItem();
    }
    if (ImGui::BeginTabItem(UiLabel("書き出し", "Export"))) {
      if (DisabledButton(Text().export_bundle,
                         !ui_state.has_exportable_diagnostic(),
                         UiLabel("診断を実行してから書き出してください。",
                                 "Run a diagnostic before exporting."))) {
        ui_state.ExportDiagnosticBundle();
      }
      ImGui::EndTabItem();
    }
    ImGui::EndTabBar();
  }
}

void RenderGlobalViewControls() {
  constexpr const char* kLanguagesJapanese[] = {"日本語", "English"};
  constexpr const char* kLanguagesEnglish[] = {"Japanese", "English"};
  const char* const* languages = IsJapaneseUi()
      ? kLanguagesJapanese
      : kLanguagesEnglish;
  int language_index = static_cast<int>(g_language);
  ImGui::SetNextItemWidth(120.0F);
  if (ImGui::Combo(Text().language,
                   &language_index,
                   languages,
                   2)) {
    g_language = static_cast<UiLanguage>(language_index);
  }
  ImGui::SameLine();
  ImGui::TextDisabled("%s", g_font_status.c_str());
}

void RenderBottomActionBar(aptt::DiagnosticUiState& ui_state) {
  const bool active_locked = HasAnyActiveBackend(ui_state);
  ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0F, 4.0F));
  if (DisabledButton(UiLabel("再読み込み", "Refresh"),
                     active_locked,
                     Text().active_change_blocked)) {
    RefreshRequestedBackend(ui_state);
  }
  ImGui::SameLine();
  std::string start_reason = Text().probe_first;
  if (active_locked) {
    start_reason = ActiveStartDisabledReason(ui_state);
  } else if (ui_state.selected_playback_backend() &&
      ui_state.selected_playback_format()) {
    start_reason = StartDisabledReason(
        ui_state,
        *ui_state.selected_playback_backend(),
        ui_state.selected_playback_format()->signal_mode);
  } else if (!ui_state.selected_device()) {
    start_reason = Text().select_device_first;
  } else if (!ui_state.selected_test_condition()) {
    start_reason = UiLabel("検査マトリックスからテスト条件を選択してください。",
                           "Select a test condition from the test matrix.");
  } else if (ui_state.selected_device()->backend == aptt::BackendApi::kAsio &&
             !aptt::IsAsioSdkEnabled()) {
    start_reason = UiLabel("このビルドではASIOサポートが無効です。",
                           "ASIO support is disabled in this build.");
  }
  if (DisabledButton(UiLabel("開始", "Start"),
                     !start_reason.empty(),
                     start_reason)) {
    StartSelectedFormat(ui_state);
  }
  ImGui::SameLine();
  const bool no_active = !HasAnyActiveBackend(ui_state);
  if (DisabledButton(UiLabel("信号停止 / 保持", "Stop signal / hold"),
                     no_active,
                     Text().no_active_backend)) {
    StopActiveBackend(ui_state);
  }
  if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
    ImGui::SetTooltip("%s", StopHoldTooltip());
  }
  if (HasAnyActiveBackend(ui_state) && IsKnownProblemSelection(ui_state)) {
    ImGui::SameLine();
    RenderHeldDeviceReleaseAcknowledgementCompact(ui_state);
  }
  const auto release_reason = ReleaseAfterStopDisabledReason(ui_state);
  ImGui::SameLine();
  if (DisabledButton(UiLabel("保持中デバイスを解放",
                             "Release held device"),
                     !release_reason.empty(),
                     release_reason)) {
    ReleaseActiveBackend(ui_state);
  }
  ImGui::SameLine();
  if (DisabledButton(Text().export_bundle,
                     !ui_state.has_exportable_diagnostic(),
                     UiLabel("診断を実行してから書き出してください。",
                             "Run a diagnostic before exporting."))) {
    ui_state.ExportDiagnosticBundle();
  }
  ImGui::PopStyleVar();
}

void RenderDiagnosticShell(aptt::DiagnosticUiState& ui_state) {
  const ImGuiIO& io = ImGui::GetIO();
  ImGui::SetNextWindowPos(ImVec2(0.0F, 0.0F));
  ImGui::SetNextWindowSize(io.DisplaySize);
  ImGuiWindowFlags flags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize |
                           ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBringToFrontOnFocus;
  ImGui::Begin(Text().app_title, nullptr, flags);

  RenderGlobalViewControls();
  ImGui::Separator();
  RenderTopStatusRibbon(ui_state);
  RenderNextActionBanner(ui_state);
  if (g_pending_close_guard_warning && !ui_state.HasAnyActiveBackend()) {
    g_pending_close_guard_warning.reset();
  }
  if (g_pending_close_guard_warning) {
    const std::string& message = IsJapaneseUi()
        ? g_pending_close_guard_warning->japanese_message
        : g_pending_close_guard_warning->english_message;
    ImGui::Separator();
    ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.55F, 0.08F, 0.04F, 1.0F));
    ImGui::PushTextWrapPos(0.0F);
    ImGui::TextUnformatted(message.c_str());
    ImGui::PopTextWrapPos();
    ImGui::PopStyleColor();
    if (ImGui::SmallButton(UiLabel("確認", "Dismiss"))) {
      g_pending_close_guard_warning.reset();
    }
  }
  ImGui::Separator();

  const float bottom_bar_height = ImGui::GetFrameHeightWithSpacing() + 8.0F;
  const bool flow_visible = ImGui::BeginChild(
      "diagnostic-flow-scroll",
      ImVec2(0.0F, -bottom_bar_height),
      false,
      ImGuiWindowFlags_AlwaysVerticalScrollbar);
  if (flow_visible) {
    RenderDiagnosticFlow(ui_state);
  }
  ImGui::EndChild();

  ImGui::Separator();
  RenderBottomActionBar(ui_state);

  ImGui::End();
}

LRESULT CALLBACK WindowProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) {
  if (ImGui_ImplWin32_WndProcHandler(window, message, wparam, lparam)) {
    return true;
  }

  switch (message) {
    case WM_SIZE:
      if (g_d3d_device != nullptr && wparam != SIZE_MINIMIZED) {
        CleanupRenderTarget();
        g_swap_chain->ResizeBuffers(0, LOWORD(lparam), HIWORD(lparam),
                                    DXGI_FORMAT_UNKNOWN, 0);
        CreateRenderTarget();
      }
      return 0;
    case WM_CLOSE:
      if (g_ui_state_for_close_guard != nullptr) {
        const auto decision =
            g_ui_state_for_close_guard->app_close_guard_decision();
        if (decision.should_block_quit) {
          g_pending_close_guard_warning = decision;
          return 0;
        }
      }
      DestroyWindow(window);
      return 0;
    case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
    default:
      return DefWindowProcW(window, message, wparam, lparam);
  }
}

}  // namespace

int APIENTRY WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int show_command) {
  if (CommandLineContainsExactFlag(L"--smoke")) {
    return 0;
  }

  WNDCLASSEXW window_class{};
  window_class.cbSize = sizeof(window_class);
  window_class.style = CS_CLASSDC;
  window_class.lpfnWndProc = WindowProc;
  window_class.hInstance = instance;
  window_class.lpszClassName = kWindowClassName;
  RegisterClassExW(&window_class);

  HWND window = CreateWindowW(kWindowClassName, aptt::kAppNameWide, WS_OVERLAPPEDWINDOW,
                              100, 100, 1280, 760, nullptr, nullptr, instance, nullptr);

  if (window == nullptr || !CreateDeviceD3D(window)) {
    CleanupDeviceD3D();
    UnregisterClassW(kWindowClassName, instance);
    return 1;
  }

  ShowWindow(window, show_command);
  UpdateWindow(window);

  IMGUI_CHECKVERSION();
  ImGui::CreateContext();
  ImGuiIO& io = ImGui::GetIO();
  io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
  LoadJapaneseSystemFont(io);
  ApplyJapaneseLightTheme();

  ImGui_ImplWin32_Init(window);
  ImGui_ImplDX11_Init(g_d3d_device, g_d3d_context);

  bool running = true;
  aptt::DiagnosticUiState ui_state;
  g_ui_state_for_close_guard = &ui_state;
  while (running) {
    MSG message{};
    while (PeekMessageW(&message, nullptr, 0, 0, PM_REMOVE)) {
      TranslateMessage(&message);
      DispatchMessageW(&message);
      if (message.message == WM_QUIT) {
        running = false;
      }
    }
    if (!running) {
      break;
    }

    ImGui_ImplDX11_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();
    ui_state.Tick();
    RenderDiagnosticShell(ui_state);
    ImGui::Render();

    constexpr float clear_color[4] = {0.96F, 0.97F, 0.98F, 1.0F};
    g_d3d_context->OMSetRenderTargets(1, &g_render_target_view, nullptr);
    g_d3d_context->ClearRenderTargetView(g_render_target_view, clear_color);
    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
    g_swap_chain->Present(1, 0);
  }

  g_ui_state_for_close_guard = nullptr;
  g_pending_close_guard_warning.reset();
  ImGui_ImplDX11_Shutdown();
  ImGui_ImplWin32_Shutdown();
  ImGui::DestroyContext();
  CleanupDeviceD3D();
  DestroyWindow(window);
  UnregisterClassW(kWindowClassName, instance);
  return 0;
}
