#include "unity.h"
#include "zigbee_zcl.h"
#include <stddef.h>  // For NULL

void setUp(void) {
    // Reset ZCL attributes before each test
    zigbee_zcl_set_local_temperature(0);
    zigbee_zcl_set_system_mode(0);
}

void tearDown(void) {
    // Clean up after each test
}

void test_zigbee_zcl_init(void) {
    TEST_ASSERT_TRUE(zigbee_zcl_init());
}

void test_zigbee_zcl_set_and_get_local_temperature(void) {
    // Test setting and getting local temperature
    zigbee_zcl_set_local_temperature(2500); // 25.00°C
    TEST_ASSERT_EQUAL_INT16(2500, zigbee_zcl_get_local_temperature());

    zigbee_zcl_set_local_temperature(-500); // -5.00°C
    TEST_ASSERT_EQUAL_INT16(-500, zigbee_zcl_get_local_temperature());

    zigbee_zcl_set_local_temperature(3000); // 30.00°C
    TEST_ASSERT_EQUAL_INT16(3000, zigbee_zcl_get_local_temperature());
}

void test_zigbee_zcl_set_and_get_system_mode(void) {
    // Test setting and getting valid system modes
    zigbee_zcl_set_system_mode(0); // Off
    TEST_ASSERT_EQUAL_INT8(0, zigbee_zcl_get_system_mode());

    zigbee_zcl_set_system_mode(1); // Auto
    TEST_ASSERT_EQUAL_INT8(1, zigbee_zcl_get_system_mode());

    zigbee_zcl_set_system_mode(3); // Cool
    TEST_ASSERT_EQUAL_INT8(3, zigbee_zcl_get_system_mode());

    zigbee_zcl_set_system_mode(4); // Heat
    TEST_ASSERT_EQUAL_INT8(4, zigbee_zcl_get_system_mode());
}

void test_zigbee_zcl_ignore_invalid_system_mode(void) {
    // Test that invalid system modes are ignored
    zigbee_zcl_set_system_mode(2); // Invalid mode
    TEST_ASSERT_EQUAL_INT8(0, zigbee_zcl_get_system_mode()); // Should remain Off

    zigbee_zcl_set_system_mode(5); // Invalid mode
    TEST_ASSERT_EQUAL_INT8(0, zigbee_zcl_get_system_mode()); // Should remain Off

    zigbee_zcl_set_system_mode(255); // Invalid mode
    TEST_ASSERT_EQUAL_INT8(0, zigbee_zcl_get_system_mode()); // Should remain Off
}

void test_zigbee_zcl_handle_command_non_thermostat_cluster(void) {
    // Test handling command for non-thermostat cluster
    uint8_t payload[] = {0x01, 0x02, 0x03};

    TEST_ASSERT_FALSE(zigbee_zcl_handle_command(
        1, 0x0000, 0x00, payload, sizeof(payload)));
}

void test_zigbee_zcl_handle_command_thermostat_cluster(void) {
    // Test handling command for thermostat cluster
    uint8_t payload[] = {0x01, 0x02};

    // Valid thermostat cluster command
    TEST_ASSERT_TRUE(zigbee_zcl_handle_command(
        1, 0x0201, 0x00, payload, sizeof(payload)));

    // Test with different command ID
    TEST_ASSERT_TRUE(zigbee_zcl_handle_command(
        1, 0x0201, 0x01, payload, sizeof(payload)));
}

void test_zigbee_zcl_handle_command_null_payload(void) {
    // Test handling command with null payload and zero length should fail
    TEST_ASSERT_FALSE(zigbee_zcl_handle_command(
        1, 0x0201, 0x00, NULL, 0));

    // Test handling command with null payload and non-zero length should fail
    TEST_ASSERT_FALSE(zigbee_zcl_handle_command(
        1, 0x0201, 0x00, NULL, 5));
}

void test_zigbee_zcl_handle_schedule_command(void) {
    // Test handling schedule commands
    uint8_t payload[] = {0x01, 0x02, 0x03, 0x04};

    // Test with payload
    TEST_ASSERT_TRUE(zigbee_zcl_handle_schedule_command(
        0x00, payload, sizeof(payload)));

    // Test with null payload but zero length
    TEST_ASSERT_TRUE(zigbee_zcl_handle_schedule_command(
        0x01, NULL, 0));

    // Test with null payload and non-zero length
    TEST_ASSERT_FALSE(zigbee_zcl_handle_schedule_command(
        0x02, NULL, 5));
}

int main(void) {
    UNITY_BEGIN();

    RUN_TEST(test_zigbee_zcl_init);
    RUN_TEST(test_zigbee_zcl_set_and_get_local_temperature);
    RUN_TEST(test_zigbee_zcl_set_and_get_system_mode);
    RUN_TEST(test_zigbee_zcl_ignore_invalid_system_mode);
    RUN_TEST(test_zigbee_zcl_handle_command_non_thermostat_cluster);
    RUN_TEST(test_zigbee_zcl_handle_command_thermostat_cluster);
    RUN_TEST(test_zigbee_zcl_handle_command_null_payload);
    RUN_TEST(test_zigbee_zcl_handle_schedule_command);

    return UNITY_END();
}