#pragma once

#include <Arduino.h>
#include <WebServer.h>
#include <WiFi.h>
#include <TBeamStorage.h>

namespace tbeam {

struct WebConfig {
  const char* ssidPrefix = "TBEAM";
  const char* boardId = "NODE";
  const char* password = nullptr;
  uint8_t ipOctet = 25;
  uint16_t port = 80;
  bool enableDelete = true;
  bool enableSerialLog = true;
};

class TBeamWeb {
 public:
  explicit TBeamWeb(Print& diagnostic = Serial);

  bool begin(TBeamStorage& storage, const WebConfig& config = WebConfig{});
  void update();
  void stop();

  bool ready() const { return ready_; }
  const char* ssid() const { return ssid_; }
  IPAddress ip() const { return ip_; }
  const char* lastError() const { return lastError_; }
  uint8_t stationCount() const;

 private:
  static TBeamWeb* active_;
  static void handleRootThunk();
  static void handleStatusThunk();
  static void handleFilesThunk();
  static void handleDownloadThunk();
  static void handleDeleteThunk();
  static void handleNotFoundThunk();

  void handleRoot();
  void handleStatus();
  void handleFiles();
  void handleDownload();
  void handleDelete();
  void handleNotFound();

  void listDirectoryHtml(String& body, const char* path, uint8_t depth);
  size_t countDirectoryEntries(const char* path, size_t maxEntries, bool* truncated);
  bool normalizePath(const String& input, char* out, size_t outSize) const;
  String htmlEscape(const String& in) const;
  String urlEncode(const String& in) const;
  String contentTypeFor(const String& path) const;
  void setError(const char* message);
  void clearError();
  void logf(const char* fmt, ...);

  Print& diagnostic_;
  WebServer server_;
  TBeamStorage* storage_ = nullptr;
  WebConfig config_{};
  bool ready_ = false;
  IPAddress ip_{0, 0, 0, 0};
  char ssid_[40] = {};
  char lastError_[128] = {};
};

}  // namespace tbeam
