// bluetooth_interface.h - Bluetooth interface for Lua sandbox
// Milestone 16: Bluetooth discovery and pairing with user consent
#pragma once

#include <string>
#include <memory>
#include <functional>
#include <mutex>
#include <atomic>
#include <vector>
#include <unordered_map>
#include <cstdint>

struct lua_State;

namespace mosis {

struct BluetoothDevice {
    std::string name;           // Device display name
    std::string address;        // MAC address
};

struct DiscoveryOptions {
    int timeout_seconds = 30;   // Discovery timeout
};

struct ConnectionOptions {
    int timeout_ms = 10000;     // Connection timeout
};

enum class BluetoothError {
    None,
    PermissionDenied,
    UserConsentRequired,
    DiscoveryFailed,
    ConnectionFailed,
    NotConnected,
    ConnectionLimitReached,
    Timeout,
    AlreadyDiscovering
};

class BluetoothConnection {
public:
    using DataCallback = std::function<void(const std::vector<uint8_t>&)>;
    using ErrorCallback = std::function<void(BluetoothError, const std::string&)>;

    BluetoothConnection(int id, const std::string& address);
    ~BluetoothConnection();

    int GetId() const { return m_id; }
    std::string GetAddress() const { return m_address; }
    bool IsConnected() const { return m_connected; }

    bool Send(const std::vector<uint8_t>& data, std::string& error);
    void Close();

    void SetOnData(DataCallback cb) { m_on_data = std::move(cb); }
    void SetOnError(ErrorCallback cb) { m_on_error = std::move(cb); }
    void SetOnDisconnect(std::function<void()> cb) { m_on_disconnect = std::move(cb); }

    // For mock mode - simulate data receive
    void SimulateData(const std::vector<uint8_t>& data);
    void SimulateDisconnect();

private:
    int m_id;
    std::string m_address;
    std::atomic<bool> m_connected{false};
    DataCallback m_on_data;
    ErrorCallback m_on_error;
    std::function<void()> m_on_disconnect;
    mutable std::mutex m_mutex;
};

class BluetoothInterface {
public:
    BluetoothInterface(const std::string& app_id);
    ~BluetoothInterface();

    // Permission checks
    bool HasBluetoothPermission() const { return m_has_bluetooth_permission; }
    void SetBluetoothPermission(bool granted) { m_has_bluetooth_permission = granted; }

    // User gesture tracking
    bool HasUserConsent() const { return m_has_user_consent; }
    void SetUserConsent(bool consent) { m_has_user_consent = consent; }

    // Start device discovery
    // Requires permission AND user consent
    bool StartDiscovery(
        const DiscoveryOptions& options,
        std::function<void(const std::vector<BluetoothDevice>&)> success,
        std::function<void(BluetoothError, const std::string&)> error,
        std::string& out_error
    );

    // Stop current discovery
    void StopDiscovery();

    // Check if discovery is in progress
    bool IsDiscovering() const { return m_is_discovering; }

    // Connect to a device
    std::shared_ptr<BluetoothConnection> Connect(
        const std::string& address,
        const ConnectionOptions& options,
        std::string& error
    );

    // Disconnect a specific connection
    void Disconnect(int connection_id);

    // Disconnect all connections
    void DisconnectAll();

    // Get active connection count
    size_t GetActiveConnectionCount() const;

    // Cleanup on app stop
    void Shutdown();

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

    // Mock mode: set discovered devices
    void SetMockDevices(const std::vector<BluetoothDevice>& devices) { m_mock_devices = devices; }

    // Get connection by ID
    std::shared_ptr<BluetoothConnection> GetConnection(int id);

private:
    std::string m_app_id;
    std::unordered_map<int, std::shared_ptr<BluetoothConnection>> m_connections;
    mutable std::mutex m_mutex;
    bool m_mock_mode = true;
    bool m_has_bluetooth_permission = false;
    bool m_has_user_consent = false;
    std::atomic<bool> m_is_discovering{false};
    std::vector<BluetoothDevice> m_mock_devices;
    int m_next_connection_id = 1;

    static constexpr int MAX_CONNECTIONS = 5;

    void CleanupClosedConnections();
};

// Register bluetooth.* APIs as globals
void RegisterBluetoothAPI(lua_State* L, BluetoothInterface* bluetooth);

} // namespace mosis
