// ============================================================================
// test/test_batch_e/test_rf_cataloger.cpp
//
// Unity tests for src/rf_cataloger.{h,cpp} — situational sub-GHz ISM
// activity classification. rf_cataloger_classify() is pure (no radio
// access) and unconditionally compiled (not #ifdef ARDUINO-gated), so it
// is directly testable in the native env without any stubs.
//
// Kept in its own test/<dir> (not colocated with test_batch_e) because
// PlatformIO's native unity runner compiles every .cpp under one test
// directory into a single executable -- two files each defining main()
// in the same directory would fail to link.
//
// Run with:
//   pio test -e native -f test_rf_cataloger
// ============================================================================

#include <unity.h>
#include "../../src/rf_cataloger.cpp"

void setUp(void) {}
void tearDown(void) {}

void test_classify_none_below_threshold(void) {
    TEST_ASSERT_EQUAL(RF_ACTIVITY_NONE, rf_cataloger_classify(0.0f, false));
}

void test_classify_continuous_overrides_rate(void) {
    // Even a rate that would otherwise look like a plausible control link
    // must classify as CONTINUOUS if the dwell never dropped back below
    // threshold -- that's a genuine sustained carrier, not a packetized
    // burst pattern.
    TEST_ASSERT_EQUAL(RF_ACTIVITY_CONTINUOUS, rf_cataloger_classify(50.0f, true));
    TEST_ASSERT_EQUAL(RF_ACTIVITY_CONTINUOUS, rf_cataloger_classify(0.0f, true));
}

void test_classify_low_rate_keyfob_like(void) {
    TEST_ASSERT_EQUAL(RF_ACTIVITY_LOW_RATE, rf_cataloger_classify(0.5f, false));
    TEST_ASSERT_EQUAL(RF_ACTIVITY_LOW_RATE, rf_cataloger_classify(4.9f, false));
}

void test_classify_periodic_sensor_like(void) {
    TEST_ASSERT_EQUAL(RF_ACTIVITY_PERIODIC, rf_cataloger_classify(5.0f, false));
    TEST_ASSERT_EQUAL(RF_ACTIVITY_PERIODIC, rf_cataloger_classify(19.9f, false));
}

void test_classify_control_link_rate_matches_subghz_scanner_band(void) {
    // Boundary values mirror subghz_scanner.h's own documented plausible
    // control-link band (20-1200 Hz). Widened 2026-07-30 from 600 Hz after
    // cross-checking against real sourced data: ExpressLRS's own docs list
    // real 900MHz-band rates up to 1000 Hz FSK, which the old 600 Hz
    // ceiling would have misclassified as ERRATIC/noise.
    TEST_ASSERT_EQUAL(RF_ACTIVITY_CONTROL_LINK_RATE, rf_cataloger_classify(20.0f, false));
    TEST_ASSERT_EQUAL(RF_ACTIVITY_CONTROL_LINK_RATE, rf_cataloger_classify(250.0f, false));
    TEST_ASSERT_EQUAL(RF_ACTIVITY_CONTROL_LINK_RATE, rf_cataloger_classify(1000.0f, false));
    TEST_ASSERT_EQUAL(RF_ACTIVITY_CONTROL_LINK_RATE, rf_cataloger_classify(1200.0f, false));
}

void test_classify_erratic_above_control_link_band(void) {
    TEST_ASSERT_EQUAL(RF_ACTIVITY_ERRATIC, rf_cataloger_classify(1200.1f, false));
    TEST_ASSERT_EQUAL(RF_ACTIVITY_ERRATIC, rf_cataloger_classify(5000.0f, false));
}

void test_classify_negative_rate_treated_as_none(void) {
    // Defensive: crossing rate is derived from an unsigned crossing count
    // divided by dwell time in production, so it should never actually go
    // negative, but the classifier must not misbehave (e.g. fall through
    // to LOW_RATE) if it ever does.
    TEST_ASSERT_EQUAL(RF_ACTIVITY_NONE, rf_cataloger_classify(-1.0f, false));
}

int main(int, char**) {
    UNITY_BEGIN();

    RUN_TEST(test_classify_none_below_threshold);
    RUN_TEST(test_classify_continuous_overrides_rate);
    RUN_TEST(test_classify_low_rate_keyfob_like);
    RUN_TEST(test_classify_periodic_sensor_like);
    RUN_TEST(test_classify_control_link_rate_matches_subghz_scanner_band);
    RUN_TEST(test_classify_erratic_above_control_link_band);
    RUN_TEST(test_classify_negative_rate_treated_as_none);

    return UNITY_END();
}
