/**
 * @file    test_task.cpp
 * @brief   任务框架单元测试 — 定时器/事件/消息队列全覆盖
 */
#include "myTask.h"
#include <cstdio>
#include <cstring>
#include <thread>
#include <chrono>
#include <atomic>

static int g_pass = 0, g_fail = 0;
#define TEST(n) do { printf("  TEST: %s ... ", n); } while (0)
#define OK()    do { printf("OK\n"); g_pass++; } while (0)
#define FAIL(m) do { printf("FAIL: %s\n", m); g_fail++; } while (0)
#define CHECK(c, m) do { if (!(c)) { FAIL(m); } } while (0)

static std::atomic<int> g_fired(0);
static void on_timer(void *arg) { (void)arg; g_fired++; }

int main(void)
{
    printf("\n=== libtask 单元测试 ===\n\n");

    TEST("task_sleep_ms");  { task_sleep_ms(10); } OK();

    TEST("timer once: create + start + fire");
    {
        g_fired = 0;
        stru_task_timer_t t = task_timer_create("t1", on_timer, NULL, 20, TASK_TIMER_FLAG_ONCE);
        CHECK(t != NULL, "create");
        task_timer_start(t);
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
        CHECK(g_fired >= 1, "fired");
        task_timer_destroy(t);
    }
    OK();

    TEST("timer periodic");
    {
        g_fired = 0;
        stru_task_timer_t t = task_timer_create("t2", on_timer, NULL, 50, TASK_TIMER_FLAG_PERIODIC);
        CHECK(t != NULL, "create");
        task_timer_start(t);
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
        task_timer_stop(t);
        CHECK(g_fired >= 2, "periodic");
        task_timer_destroy(t);
    }
    OK();

    TEST("timer stop + restart + is_active");
    {
        g_fired = 0;
        stru_task_timer_t t = task_timer_create("t3", on_timer, NULL, 30, TASK_TIMER_FLAG_PERIODIC);
        CHECK(task_timer_is_active(t) == 0, "not active");
        task_timer_start(t);
        CHECK(task_timer_is_active(t) == 1, "active");
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        task_timer_stop(t);
        int n = g_fired.load();
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        CHECK(g_fired == n, "stopped");
        task_timer_restart(t, 30);
        task_timer_start(t);
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        CHECK(g_fired > n, "restarted");
        task_timer_stop(t);
        task_timer_destroy(t);
    }
    OK();

    TEST("event OR: send + recv + clear");
    {
        stru_task_event_t e = task_event_create("e1");
        CHECK(e != NULL, "create");
        task_event_send(e, 0x05);
        uint32_t r = 0;
        CHECK(task_event_recv(e, 0x01, TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR, 1000, &r) == 0, "recv");
        CHECK(r & 0x01, "bit");
        task_event_destroy(e);
    }
    OK();

    TEST("event AND: both bits");
    {
        stru_task_event_t e = task_event_create("e2");
        task_event_send(e, 0x06);
        uint32_t r = 0;
        CHECK(task_event_recv(e, 0x06, TASK_EVENT_FLAG_AND | TASK_EVENT_FLAG_CLEAR, 1000, &r) == 0, "recv");
        CHECK(r == 0x06, "both");
        task_event_destroy(e);
    }
    OK();

    TEST("event timeout");
    {
        stru_task_event_t e = task_event_create("e3");
        uint32_t r = 0;
        CHECK(task_event_recv(e, 0x01, TASK_EVENT_FLAG_OR, 50, &r) == -1, "timeout");
        task_event_destroy(e);
    }
    OK();

    TEST("event query after clear");
    {
        stru_task_event_t e = task_event_create("e4");
        task_event_send(e, 0x0F);
        CHECK(task_event_query(e) & 0x0F, "query");
        task_event_clear(e, 0x0F);
        CHECK((task_event_query(e) & 0x0F) == 0, "cleared");
        task_event_destroy(e);
    }
    OK();

    TEST("msg queue: send + recv + get_count");
    {
        stru_task_msg_queue_t q = task_msg_queue_create("q1", 64, 8);
        CHECK(q != NULL, "create");
        CHECK(task_msg_queue_send(q, "hello", 6) == 0, "send");
        CHECK(task_msg_queue_get_count(q) == 1, "count");
        char buf[64] = {0};
        CHECK(task_msg_queue_recv(q, buf, sizeof(buf), 1000) > 0, "recv");
        CHECK(strcmp(buf, "hello") == 0, "content");
        CHECK(task_msg_queue_get_count(q) == 0, "empty");
        task_msg_queue_destroy(q);
    }
    OK();

    TEST("msg queue burst 20 msgs + try_recv + space");
    {
        stru_task_msg_queue_t q = task_msg_queue_create("q2", 32, 32);
        CHECK(q != NULL, "create");
        for (int i = 0; i < 20; i++) {
            char s[32]; snprintf(s, sizeof(s), "m_%d", i);
            CHECK(task_msg_queue_send(q, s, (int)strlen(s)+1) == 0, "send");
        }
        CHECK(task_msg_queue_get_count(q) == 20, "count 20");
        for (int i = 0; i < 20; i++) {
            char b[32] = {0};
            CHECK(task_msg_queue_recv(q, b, sizeof(b), 100) > 0, "recv");
        }
        CHECK(task_msg_queue_get_count(q) == 0, "empty");
        /* try_recv on empty */
        char b2[32];
        CHECK(task_msg_queue_try_recv(q, b2, sizeof(b2)) == -1, "try empty");
        task_msg_queue_destroy(q);
    }
    OK();

    printf("\n========================================\n");
    printf("  测试结果: %d pass, %d fail\n", g_pass, g_fail);
    printf("========================================\n");
    return (g_fail > 0) ? 1 : 0;
}
