#pragma once

#include "settings/SettingsManager.hpp"
#include <WiFi.h>
#include <DNSServer.h>
#include <functional>

namespace cyd {

// Manages station WiFi connection and a captive-portal AP for first-time setup.
class WiFiManager {
public:
    using ModeChangeCallback = std::function<void(bool apMode)>;

    enum class State {
        Uninitialized,
        Connecting,
        StationConnected,
        StationFailed,
        AccessPoint,
        FallbackToAp
    };

    explicit WiFiManager(SettingsManager& settings);

    // Load credentials and either connect as station or start AP.
    void begin();

    // Non-blocking update. Must be called frequently from loop().
    void update();

    State getState() const { return state_; }
    bool isApMode() const { return state_ == State::AccessPoint || state_ == State::FallbackToAp; }
    bool isConnected() const { return state_ == State::StationConnected; }
    String getIpAddress() const;

    void onModeChange(ModeChangeCallback cb) { modeCallback_ = cb; }

    // Start the AP+captive portal explicitly (e.g. from a "settings" UI button).
    void enterSetupMode();

    // Persist new credentials and try to connect. Useful from the API server.
    void configureAndConnect(const String& ssid, const String& pass);

private:
    SettingsManager& settings_;
    State state_ = State::Uninitialized;
    ModeChangeCallback modeCallback_;

    // Station connect timing
    unsigned long connectStartMillis_ = 0;
    static constexpr unsigned long kConnectTimeoutMs = 20000;

    // Captive portal DNS redirect. The actual HTTP server lives in ApiServer
    // so we don't bind port 80 in two places.
    DNSServer dnsServer_;
    bool apRunning_ = false;

    static constexpr const char* kApSsid = "CYD-ThermoPro-Setup";
    static constexpr const char* kApPass = "";

    void startStation_();
    void startAccessPoint_();
    void stopAccessPoint_();
};

} // namespace cyd
