#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 CameraFacing {
    Front,
    Back
};

enum class CameraResolution {
    VGA,      // 640x480
    HD,       // 1280x720
    FullHD    // 1920x1080
};

struct CameraConfig {
    CameraFacing facing = CameraFacing::Back;
    CameraResolution resolution = CameraResolution::HD;
    int max_fps = 30;
};

struct CameraFrame {
    std::vector<uint8_t> data;  // RGBA or JPEG data
    int width = 0;
    int height = 0;
    uint64_t timestamp_ms = 0;
    bool is_jpeg = false;
};

class CameraSession {
public:
    using FrameCallback = std::function<void(const CameraFrame& frame)>;

    CameraSession(int id, const CameraConfig& config);
    ~CameraSession();

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

    // Capture single photo (returns copy of current frame)
    CameraFrame Capture();

    // Set frame callback (for preview)
    void SetOnFrame(FrameCallback cb) { m_on_frame = std::move(cb); }

    // Stop session
    void Stop();

    // For mock mode - simulate frame arrival
    void SimulateFrame(const CameraFrame& frame);

private:
    int m_id;
    CameraConfig m_config;
    std::atomic<bool> m_active{true};
    FrameCallback m_on_frame;
    CameraFrame m_last_frame;
    mutable std::mutex m_mutex;
};

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

    // Start camera session
    // Returns session on success, nullptr on failure (sets error)
    // Requires camera permission and user gesture
    std::shared_ptr<CameraSession> StartSession(const CameraConfig& 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<CameraSession> 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 camera.* APIs as globals
void RegisterCameraAPI(lua_State* L, CameraInterface* camera);

} // namespace mosis
