#pragma once

#include <cstdint>
#include <string>
#include <vector>

#include "core/audio_types.h"

namespace aptt {

enum class DiagnosticTestMode {
  kDryRun,
  kNullBackendRun,
  kSingleRun,
  kFormatMatrix,
  kBufferRampDown,
  kStartStopStress,
  kReinitializeLoop,
};

struct DiagnosticPlanRequest {
  BackendApi backend = BackendApi::kNull;
  std::string device_id;
  bool known_problem_device = false;
  HoldMode hold_mode = HoldMode::kKeepWarmAfterStop;
  std::uint32_t cooldown_ms = 0;
  std::uint32_t max_reacquire_attempts = 1;
  bool expert_allow_stress = false;
  bool expert_allow_reinitialize = false;
  std::vector<DiagnosticTestMode> modes;
  std::vector<FormatDescriptor> formats;
};

struct DiagnosticPlanStep {
  DiagnosticTestMode mode = DiagnosticTestMode::kDryRun;
  BackendApi backend = BackendApi::kNull;
  std::string device_id;
  FormatDescriptor format;
  bool opens_audio_device = false;
  std::uint32_t cooldown_before_ms = 0;
  std::uint32_t max_reacquire_attempts = 0;
  bool abort_on_fault = true;
  bool export_bundle_after_step = true;
};

struct DiagnosticPlan {
  bool accepted = false;
  bool opens_audio_device = false;
  bool bundle_export_required = false;
  std::uint32_t cooldown_ms = 0;
  std::uint32_t max_reacquire_attempts = 0;
  std::string abort_policy;
  std::string fault_policy;
  std::string summary_scoring;
  std::vector<std::string> rejection_reasons;
  std::vector<DiagnosticPlanStep> steps;
};

struct DiagnosticRunScore {
  int score = 0;
  std::string rating;
  std::vector<std::string> penalties;
};

const char* ToString(DiagnosticTestMode mode);

DiagnosticPlan BuildDiagnosticDryRunPlan(const DiagnosticPlanRequest& request);
DiagnosticPlan BuildAutomaticSingleDevicePlan(
    const DiagnosticPlanRequest& request);
DiagnosticRunScore ScoreDiagnosticRun(const DiagnosticPlan& plan,
                                      const RealtimeStats& stats,
                                      bool run_ok);
std::string SerializeDiagnosticPlanJson(const DiagnosticPlan& plan);
std::string SerializeDiagnosticRunScoreJson(const DiagnosticRunScore& score);

}  // namespace aptt
