#pragma once

#include <string>
#include <vector>
#include <functional>
#include "esp_wifi.h"
#include "esp_event.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"

class Wifi {
public:
    static Wifi& instance();

    void init();
    void scan(std::function<void(std::vector<wifi_ap_record_t>&)> callback);
    void connect(const char* ssid, const char* password);
    void disconnect();
    bool isConnected();
    std::string getCurrentSSID();
    std::string getIPAddress();
    int8_t getRSSI();

    void saveNetwork(const char* ssid, const char* password);
    void removeNetwork(const char* ssid);
    std::vector<std::string> getSavedNetworks();
    bool getSavedPassword(const char* ssid, std::string& password);

    void setStatusCallback(std::function<void(bool connected)> callback);

private:
    Wifi() = default;
    Wifi(const Wifi&) = delete;
    Wifi& operator=(const Wifi&) = delete;

    static void eventHandler(void* arg, esp_event_base_t event_base,
                            int32_t event_id, void* event_data);

    void loadSavedNetworksFromNvs();
    void saveSavedNetworksToNvs();

    bool initialized_ = false;
    bool connected_ = false;
    std::string currentSSID_;
    EventGroupHandle_t wifiEventGroup_ = nullptr;
    std::function<void(std::vector<wifi_ap_record_t>&)> scanCallback_;
    std::function<void(bool connected)> statusCallback_;

    static constexpr int WIFI_CONNECTED_BIT = BIT0;
    static constexpr int WIFI_FAIL_BIT = BIT1;
    static constexpr int WIFI_SCAN_DONE_BIT = BIT2;

    static constexpr const char* NVS_NAMESPACE = "wifi_creds";
    static constexpr int MAX_SAVED_NETWORKS = 10;
};
