#pragma once

#include <string>
#include <memory>
#include <functional>
#include <mutex>
#include <atomic>
#include <vector>
#include <chrono>

struct lua_State;

namespace mosis {

class PermissionGate;

enum class AudioFormat {
    PCM_16BIT,
    PCM_FLOAT
};

struct RecordingConfig {
    int sample_rate = 44100;    // 8000, 16000, 22050, 44100, 48000
    int channels = 1;           // 1 (mono) or 2 (stereo)
    AudioFormat format = AudioFormat::PCM_16BIT;
};

struct AudioBuffer {
    std::vector<uint8_t> data;
    int sample_rate = 0;
    int channels = 0;
    AudioFormat format = AudioFormat::PCM_16BIT;
    uint64_t timestamp_ms = 0;
    int sample_count = 0;
};

class RecordingSession {
public:
    using BufferCallback = std::function<void(const AudioBuffer& buffer)>;

    RecordingSession(int id, const RecordingConfig& config);
    ~RecordingSession();

    int GetId() const { return m_id; }
    const RecordingConfig& GetConfig() const { return m_config; }
    bool IsActive() const { return m_active; }

    // Get accumulated audio data
    AudioBuffer GetBuffer();

    // Set buffer callback (for streaming)
    void SetOnBuffer(BufferCallback cb) { m_on_buffer = std::move(cb); }

    // Stop recording
    void Stop();

    // For mock mode - simulate audio data arrival
    void SimulateBuffer(const AudioBuffer& buffer);

private:
    int m_id;
    RecordingConfig m_config;
    std::atomic<bool> m_active{true};
    BufferCallback m_on_buffer;
    AudioBuffer m_accumulated;
    mutable std::mutex m_mutex;
};

class MicrophoneInterface {
public:
    MicrophoneInterface(const std::string& app_id, PermissionGate* permissions);
    ~MicrophoneInterface();

    // Start recording session
    // Returns session on success, nullptr on failure (sets error)
    // Requires microphone permission and user gesture
    std::shared_ptr<RecordingSession> StartSession(const RecordingConfig& config, std::string& error);

    // Stop active session
    void StopSession();

    // Check if session is active
    bool HasActiveSession() const;

    // Check if recording indicator should be shown
    bool IsIndicatorVisible() const;

    // Cleanup on app stop
    void Shutdown();

    // For testing
    void SetMockMode(bool enabled) { m_mock_mode = enabled; }
    bool IsMockMode() const { return m_mock_mode; }

    // Simulate user gesture for testing
    void SimulateUserGesture();

private:
    std::string m_app_id;
    PermissionGate* m_permissions;
    std::shared_ptr<RecordingSession> m_active_session;
    mutable std::mutex m_mutex;
    bool m_mock_mode = true;
    std::atomic<bool> m_indicator_visible{false};
    int m_next_session_id = 1;

    // Track user gesture timing
    std::chrono::steady_clock::time_point m_last_gesture_time;
    bool m_has_gesture = false;
    static constexpr int GESTURE_VALIDITY_MS = 5000;  // 5 seconds

    bool HasRecentUserGesture() const;
    void ShowIndicator();
    void HideIndicator();
};

// Register microphone.* APIs as globals
void RegisterMicrophoneAPI(lua_State* L, MicrophoneInterface* microphone);

} // namespace mosis
