#pragma once

#include <span>
#include <string>
#include <unordered_map>
#include <vector>

#include "channel_bundle_support.hpp"
#include "shared_types.hpp"

namespace radar::preprocessing {

class CalibrationMaster;

class ReferenceMaster {
  public:
    // Loads a serialized raw sweep bundle with one S21 reference trace per combo.
    void load_s21_reference_bundle(const std::string& path);
    // Loads optional raw S11 reference data.
    void load_s11_reference_bundle(const std::string& path);
    // Builds calibrated references in memory using currently loaded raw references.
    // Must be called after load_s21_reference_bundle() and after calibration standards are loaded.
    void prepare_calibrated(const CalibrationMaster& calibration_master, const std::vector<ipc::ComboKey>& combos);
    // Ensures all runtime combos are present in loaded references.
    void validate_combos(const std::vector<ipc::ComboKey>& combos) const;
    // Subtracts both channel references from one calibrated trace.
    [[nodiscard]] auto apply_to_trace(const ipc::SweepTraceBlock& calibrated_trace) const -> ipc::SweepTraceBlock;
    [[nodiscard]] auto apply_s21(
        const ipc::ComboKey& combo,
        std::span<const float> frequency_hz,
        const std::vector<ipc::Complex32>& calibrated_s21
    ) const -> std::vector<ipc::Complex32>;
    [[nodiscard]] auto apply_s11(
        const ipc::ComboKey& combo,
        std::span<const float> frequency_hz,
        const std::vector<ipc::Complex32>& calibrated_s11
    ) const -> std::vector<ipc::Complex32>;

  private:
    S21ReferenceBundle raw_s21_reference_bundle_{};
    std::unordered_map<ipc::ComboKey, ChannelTrace, ipc::ComboKeyHash> calibrated_s21_references_by_combo_{};
    S11ReferenceBundle raw_s11_reference_bundle_{};
    std::unordered_map<ipc::ComboKey, ChannelTrace, ipc::ComboKeyHash> calibrated_s11_references_by_combo_{};
};

}  // namespace radar::preprocessing
