#pragma once

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

#include "shared_types.hpp"

namespace radar::config {

enum class DriverMode {
    Mock,
    Native,
};

enum class SwitchDriverKind {
    H7992,
    HMC349A,
};

struct RadarSweepSettings {
    // Frequency sweep bounds and acquisition settings.
    float start_hz = 1'000'000.0F;
    float stop_hz = 6'000'000'000.0F;
    std::uint32_t points = 501;
    float if_bandwidth_hz = 1'000.0F;
    float power_dbm = -10.0F;
};

struct RadarConfig {
    // Radar device identity and runtime mode.
    std::string model = "librevna";
    std::string serial{};
    DriverMode driver_mode = DriverMode::Mock;
    float mock_signal_hz = 5'000'000.0F;
    RadarSweepSettings sweep{};
};

struct SwitchConfig {
    // One RF switch attached to a specific radar port.
    std::string name{};
    DriverMode driver_mode = DriverMode::Mock;
    SwitchDriverKind driver_kind = SwitchDriverKind::H7992;
    std::uint32_t radar_port = 0;
    std::uint32_t positions = 4;
    std::uint32_t default_position = 0;
    std::string gpio_chip = "/dev/gpiochip0";
    std::int32_t pin_a = 17;
    std::int32_t pin_b = 27;
    bool invert_logic = false;
};

struct RingEndpointConfig {
    // Shared-memory endpoint geometry.
    std::string name{};
    std::uint32_t capacity = 32;
    std::uint32_t slot_size_bytes = 2U * 1024U * 1024U;
};

struct RingsConfig {
    RingEndpointConfig raw{.name = "/radar_raw"};
    RingEndpointConfig raw_tap{.name = "/radar_raw_tap"};
    RingEndpointConfig preprocessed{.name = "/radar_preprocessed"};
    RingEndpointConfig preprocessed_tap{.name = "/radar_preprocessed_tap"};
    RingEndpointConfig results{.name = "/radar_results"};
};

struct RuntimeConfig {
    // Runtime pacing and behavior flags for C++ workers.
    std::uint32_t settling_ms = 0;
    std::uint32_t idle_sleep_ms = 2;
    bool continuous = true;
    std::string processing_live_config_path = "python_app/runtime/processing_live.json";
};

struct PreprocessConfig {
    // Names and bundle paths selected by Python GUI layer.
    std::string calibration_set{};
    std::string reference_set{};
    std::string calibration_bundle_path{};
    std::string reference_bundle_path{};
};

struct GprTxGeometry {
    // Transmitter geometry keyed by output switch position.
    std::uint32_t output_pos = 0;
    float x_m = 0.0F;
};

struct GprRxGeometry {
    // Receiver geometry keyed by input switch position.
    std::uint32_t input_pos = 0;
    float x_m = 0.0F;
};

struct GprConfig {
    // Stable collection-level GPR processing settings.
    std::string mode = "point";
    float relative_permittivity = 1.0F;
    std::vector<GprTxGeometry> tx_geometry{};
    std::vector<GprRxGeometry> rx_geometry{};
};

struct RunConfig {
    // Single configuration object shared by all C++ processes.
    RadarConfig radar{};
    SwitchConfig input_switch{};
    SwitchConfig output_switch{};
    RingsConfig rings{};
    RuntimeConfig runtime{};
    PreprocessConfig preprocess{};
    GprConfig gpr{};
    std::vector<radar::ipc::ComboKey> run_combos{};
};

[[nodiscard]] auto load_run_config(const std::string& path) -> RunConfig;

}  // namespace radar::config
