#pragma once

#include <vector>
#include <memory>

// Forward declaration
struct DenoiseState;

namespace secondvoice {

/**
 * NoiseReducer - Wrapper around RNNoise for real-time audio denoising
 *
 * RNNoise expects 48kHz audio, but we work at 16kHz.
 * This wrapper handles resampling transparently.
 */
class NoiseReducer {
public:
    NoiseReducer();
    ~NoiseReducer();

    // Process audio samples in-place (batch mode - for final output)
    // Input/output: float samples normalized to [-1, 1]
    void process(std::vector<float>& samples);

    // Process a buffer, returns denoised copy
    std::vector<float> processCopy(const std::vector<float>& samples);

    // Real-time streaming: process samples as they come in
    // Returns denoised samples (may be slightly delayed due to frame buffering)
    std::vector<float> processRealtime(const float* samples, size_t count);

    // Flush any remaining samples in the stream buffer (zero-padded if needed)
    std::vector<float> flushStream();

    // Clear the stream buffer (call when starting a new segment)
    void resetStream() { stream_input_buffer_.clear(); }

    // Enable/disable denoising
    void setEnabled(bool enabled) { enabled_ = enabled; }
    bool isEnabled() const { return enabled_; }

    // Save denoised audio for preview
    void setSavePreview(bool save) { save_preview_ = save; }
    bool isSavePreviewEnabled() const { return save_preview_; }

    // Save audio samples to Opus file (for preview)
    void savePreview(const std::vector<float>& samples);

private:
    DenoiseState* state_ = nullptr;
    bool enabled_ = true;
    bool save_preview_ = true;  // Save denoised audio for listening
    int preview_count_ = 0;

    // RNNoise frame size (480 samples at 48kHz = 10ms)
    static constexpr int RNNOISE_FRAME_SIZE = 480;

    // Our frame size (160 samples at 16kHz = 10ms)
    static constexpr int INPUT_FRAME_SIZE = 160;

    // Resampling buffers
    std::vector<float> upsample_buffer_;
    std::vector<float> downsample_buffer_;

    // Streaming input buffer (for real-time processing)
    std::vector<float> stream_input_buffer_;

    // Transient suppressor state
    float envelope_ = 0.0f;              // Smoothed signal envelope
    float envelope_attack_ = 0.01f;      // Fast attack to track signal
    float envelope_release_ = 0.0005f;   // Slow release to maintain level
    float transient_threshold_ = 4.0f;   // Spike must be 4x envelope to be considered transient
    float transient_ratio_ = 0.1f;       // Attenuate transients to 10% (-90% reduction)

    // Suppress transient sounds (claps, clicks, pops)
    void suppressTransients(float* samples, size_t count);

    // Upsample 16kHz to 48kHz (3x)
    void upsample(const float* in, float* out, int in_samples);

    // Downsample 48kHz to 16kHz (3x)
    void downsample(const float* in, float* out, int out_samples);
};

} // namespace secondvoice
