#include "SettingsStore.h"
#include "Config.h"
#include "Log.h"
#include <Preferences.h>

namespace { constexpr uint16_t SETTINGS_VERSION = 4; constexpr char NAMESPACE[] = "opt-test"; }

void SettingsStore::defaults(Settings &s) const {
  s = {SETTINGS_VERSION, static_cast<uint8_t>(Role::SOLO), 0, 4, 2, 3, 2, 0};
  s.checksum = settingsChecksum(s);
}

bool SettingsStore::valid(const Settings &s) const {
  return s.version == SETTINGS_VERSION && s.role <= static_cast<uint8_t>(Role::SLAVE) &&
    s.startIndex < countOf(START_FREQ_OPTIONS_HZ) && s.endIndex < countOf(END_FREQ_OPTIONS_HZ) &&
    s.accuracyIndex < countOf(ACCURACY_OPTIONS_PCT) &&
    s.timeIndex < countOf(TEST_TIME_OPTIONS_MS) && s.dutyIndex < countOf(DUTY_OPTIONS_PCT) &&
    s.checksum == settingsChecksum(s) &&
    END_FREQ_OPTIONS_HZ[s.endIndex] > START_FREQ_OPTIONS_HZ[s.startIndex];
}

bool SettingsStore::load(Settings &s) {
  Preferences prefs;
  if (!prefs.begin(NAMESPACE, true)) { defaults(s); Log::event("NVS", "open for read FAILED; defaults selected"); return false; }
  const size_t got = prefs.getBytes("settings", &s, sizeof(s));
  prefs.end();
  if (got != sizeof(s) || !valid(s)) { defaults(s); Log::event("NVS", "missing/corrupt settings; defaults selected"); return false; }
  Log::event("NVS", "settings loaded and validated");
  return true;
}

bool SettingsStore::save(Settings &s) {
  s.version = SETTINGS_VERSION; s.checksum = settingsChecksum(s);
  if (!valid(s)) { Log::event("NVS", "save rejected: invalid settings"); return false; }
  Preferences prefs;
  if (!prefs.begin(NAMESPACE, false)) { Log::event("NVS", "open for write FAILED"); return false; }
  const bool ok = prefs.putBytes("settings", &s, sizeof(s)) == sizeof(s);
  prefs.end(); Log::printf("NVS", "settings save %s", ok ? "OK" : "FAILED"); return ok;
}

TestParams SettingsStore::params(const Settings &s) const {
  return {START_FREQ_OPTIONS_HZ[s.startIndex], END_FREQ_OPTIONS_HZ[s.endIndex],
    ACCURACY_OPTIONS_PCT[s.accuracyIndex], TEST_TIME_OPTIONS_MS[s.timeIndex],
    DUTY_OPTIONS_PCT[s.dutyIndex]};
}
