#ifndef SH_CORE_H
#define SH_CORE_H

#include <Arduino.h>
#include "sh_platform.h"

static const char CORE_VERSION[] PROGMEM = "1.5 dev";

// -------------------- compile-time defaults --------------------
extern const char* DEVICE_TYPE;
extern const char* FW_VERSION;

static constexpr uint8_t SH_PIN_UNUSED = 0xFF;

extern const uint8_t CHANNEL_NUM;

// -------------------- EEPROM layout (ядро) --------------------
constexpr uint16_t SSID_ADDR            = 0;
constexpr uint16_t SSID_MAX_LEN         = 32;

constexpr uint16_t PASS_ADDR            = SSID_ADDR + SSID_MAX_LEN;      // 32
constexpr uint16_t PASS_MAX_LEN         = 64;                            // 32..95

constexpr uint16_t DEVICE_MODE_ADDR     = PASS_ADDR + PASS_MAX_LEN;      // 96

constexpr uint16_t DEVICE_NAME_ADDR     = DEVICE_MODE_ADDR + 1;          // 97
constexpr uint16_t DEVICE_NAME_MAX_LEN  = 64;                            // 97..160

constexpr uint16_t AUTH_TOKEN_ADDR      = DEVICE_NAME_ADDR + DEVICE_NAME_MAX_LEN;
constexpr uint16_t AUTH_TOKEN_MAX_LEN   = 64;

constexpr uint16_t SERVER_ADDR          = AUTH_TOKEN_ADDR + AUTH_TOKEN_MAX_LEN;
constexpr uint16_t SERVER_MAX_LEN       = 32;

// ---- channels schema (EEPROM) ----
// data = 8 каналов * 4 байта = 32
constexpr uint16_t CHANNEL_SCHEMA_DATA_LEN  = 32;
constexpr uint16_t CHANNEL_SCHEMA_META_LEN  = 4;
constexpr uint16_t CHANNEL_SCHEMA_TOTAL_LEN = CHANNEL_SCHEMA_META_LEN + CHANNEL_SCHEMA_DATA_LEN;

constexpr uint16_t CHANNEL_SCHEMA_ADDR      = SERVER_ADDR + SERVER_MAX_LEN;
constexpr uint16_t CHANNEL_SCHEMA_MAX_LEN   = CHANNEL_SCHEMA_DATA_LEN; // ВАЖНО: размер RAM-буфера = 32

constexpr uint8_t  CHANNEL_SCHEMA_MAGIC_0   = 0xA5;
constexpr uint8_t  CHANNEL_SCHEMA_MAGIC_1   = 0x5A;
constexpr uint8_t  CHANNEL_SCHEMA_VERSION   = 1;

constexpr uint16_t CHANNEL_SCHEMA_META_ADDR = CHANNEL_SCHEMA_ADDR;       // +0..+3
constexpr uint16_t CHANNEL_SCHEMA_DATA_ADDR = CHANNEL_SCHEMA_ADDR + 4;   // +4..+35

// Конец блока ядра
constexpr uint16_t CORE_EEPROM_END      = CHANNEL_SCHEMA_ADDR + CHANNEL_SCHEMA_TOTAL_LEN;

// Общий размер EEPROM
constexpr uint16_t EEPROM_SIZE          = 1024;

// Диапазон EEPROM, свободный для устройств:
constexpr uint16_t DEVICE_EEPROM_START  = 512;
constexpr uint16_t DEVICE_EEPROM_SIZE   = EEPROM_SIZE - DEVICE_EEPROM_START;

// ---- channel fields ----
constexpr uint8_t CHANNEL_BYTES = 4;
constexpr uint8_t CHANNEL_MAX   = 8;

enum ShChannelField : uint8_t {
  SH_CH_PIN = 0,
  SH_CH_INDICATOR = 1,
  SH_CH_FEEDBACK = 2,
  SH_CH_RESERVED = 3
};

// -------------------- Device mode --------------------
enum DeviceMode : uint8_t {
  DEVICE_MODE_SETUP    = 0,
  DEVICE_MODE_NORMAL   = 1,
  DEVICE_MODE_ERROR    = 2,
  DEVICE_MODE_UPDATING = 3
};

// -------------------- Globals (ядро) --------------------
extern sh_web_server_t server;

extern String savedSSID;
extern String savedPASS;

extern DeviceMode deviceMode;
extern String     deviceName;
extern String     serverBaseUrl;
extern String     authToken;

// RAM-буфер схемы: ТОЛЬКО 32 байта data
extern char channels_schema[CHANNEL_SCHEMA_DATA_LEN];

// -------------------- pages --------------------
extern const char* wifi_setup_page;
extern const char* update_page;

// -------------------- core API --------------------
uint16_t getDeviceEepromStart();
uint16_t getDeviceEepromSize();

String readStringFromEEPROM(uint16_t addr, uint16_t maxLen);
void writeStringToEEPROM(uint16_t addr, const String &str, uint16_t maxLen);

// channels schema
bool is_channels_schema_valid();
void init_default_channels_schema();
void write_channels_schema();
void load_channels_schema();

uint8_t sh_channel_get_u8(uint8_t ch, ShChannelField field);
void    sh_channel_set_u8(uint8_t ch, ShChannelField field, uint8_t v);

uint8_t sh_channel_pin(uint8_t ch);
uint8_t sh_channel_indicator(uint8_t ch);
uint8_t sh_channel_feedback_pin(uint8_t ch);

constexpr uint8_t SH_CH_FLAG_INVERT = 0x01;

bool sh_channel_is_inverted(uint8_t ch);
void sh_channel_set_inverted(uint8_t ch, bool inverted);


// wifi/device config
void saveWiFiConfig(const String &ssid, const String &pass);
void loadWiFiConfig();

void loadDeviceConfig();
void saveDeviceConfig();

bool tryConnectWiFi();
void startAPMode();

String getUniqueID();
String getMAC();

void coreSetup();
void coreLoop();

// Универсальный POST JSON на serverBaseUrl
bool core_post_json_to_server(const String &path, const String &json_body, uint32_t timeout_ms, int &http_code_out);

// Путь для core event'ов (можно переопределить в прошивке устройства).
__attribute__((weak)) const char* core_get_event_path();

// -------------------- routes registration --------------------
void registerWebUiRoutes();
void registerRestApiRoutes();

#endif // SH_CORE_H
