#pragma once

#include <atomic>
#include <cstdint>
#include <map>
#include <optional>
#include <string>

#include "core/audio_types.h"
#include "core/device_lifecycle.h"

namespace aptt {

inline constexpr int kDiagnosticLogSchemaVersion = 1;

enum class DiagnosticEventType {
  kSessionStart,
  kLifecycleTransition,
  kFormatProbe,
  kRuntimeStats,
  kError,
  kSessionSummary,
};

struct DiagnosticEvent {
  int schema_version = kDiagnosticLogSchemaVersion;
  DiagnosticEventType type = DiagnosticEventType::kSessionStart;
  std::uint64_t sequence = 0;
  std::string wall_time_utc;
  std::uint64_t qpc_ticks = 0;
  BackendApi backend = BackendApi::kNull;
  std::string device_id;
  std::string message;
  std::optional<DeviceLifecycleState> lifecycle_from;
  std::optional<DeviceLifecycleState> lifecycle_to;
  std::optional<FormatDescriptor> format;
  std::optional<RealtimeStats> realtime_stats;
  std::map<std::string, std::string> backend_fields;
};

class DiagnosticSequenceCounter {
 public:
  std::uint64_t Next() {
    return sequence_.fetch_add(1, std::memory_order_relaxed) + 1;
  }

  void Reset(std::uint64_t value = 0) {
    sequence_.store(value, std::memory_order_relaxed);
  }

  std::uint64_t value() const {
    return sequence_.load(std::memory_order_relaxed);
  }

 private:
  std::atomic<std::uint64_t> sequence_{0};
};

const char* ToString(DiagnosticEventType type);
DiagnosticEventType DiagnosticEventTypeFromString(const std::string& value);

std::string SerializeDiagnosticEventJsonl(const DiagnosticEvent& event);
std::optional<DiagnosticEvent> ParseDiagnosticEventJsonl(const std::string& line);

DiagnosticEvent MakeLifecycleEvent(
    std::uint64_t sequence,
    BackendApi backend,
    std::string device_id,
    DeviceLifecycleState from,
    DeviceLifecycleState to,
    std::string message);

}  // namespace aptt
