/******************************************************************************
 * 模块名称：SD2506 RTC Test Suite
 * 模块功能：SD2506API-G RTC 驱动功能自测（黑盒，仅用公共 API）。
 *
 * 历史背景：本驱动曾出现"时间写不进"问题，根因是 sd2506.h 中寄存器宏写成
 *           "0x0FH"（H 后缀）。KEIL/ARMCC 不识别 H 整数后缀，将其编译为 0，
 *           导致 SD2506_REG_CTR1 实际等于 0（秒寄存器），sd2506_write_enable()
 *           把 WRTC 写到了错误寄存器，写保护永不解除。修正为 "0x0FU" 后恢复。
 *           详见 docs/SD2506_Trap_Records.md。
 *
 * 当前测试：Phase 1 基本读写（init / 读 / 写 / 回读一致 / 走时），
 *           结束后自动恢复板子原始时间。
 * 入口：sd2506_test_run()（由 StartCh395fTestTask 经 TEST_SUITE_RTC 调度）
 * 创建日期：2026-08-28
 ******************************************************************************/

#include <string.h>
#include <stdint.h>
#include "sd2506_test.h"
#include "test_config.h"
#include "cmsis_os.h"
#include "sd2506.h"

#define DBG_TAG "[RTC_TEST]"
#include "dbg_log.h"

#ifdef TEST_SUITE_RTC

/* 全局测试统计（宏自动管理） */
sd2506_test_stats_t g_sd2506_test_stats;

/* ===================== Phase 1：基本读写 ===================== */
#ifdef ENABLE_RTC_BASIC_TESTS
static void sd2506_phase_basic(void)
{
    DBG_INFO("=== SD2506 Phase 1: basic read/write (public API) ===");

    /* TC-RTC-001: init + 读取当前时间 */
    int ret = sd2506_init();
    SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_init() ret=%d (expect 0)", ret);

    sd2506_time_t r;
    ret = sd2506_get_time(&r);
    SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_get_time() ret=%d (expect 0)", ret);
    if (ret == SD2506_OK) {
        DBG_INFO("  current RTC: %04u-%02u-%02u %02u:%02u:%02u wk=%u",
                 (unsigned int)r.year, (unsigned int)r.month, (unsigned int)r.day,
                 (unsigned int)r.hour, (unsigned int)r.minute,
                 (unsigned int)r.second, (unsigned int)r.week);
    }

    /* TC-RTC-002: 写固定时间，立即回读比对。
     * 若 FAIL -> 先查 sd2506.h 寄存器宏后缀是否为 H（曾因 0x0FH 被 KEIL 编译为 0
     *            导致 SD2506_REG_CTR1 指向秒寄存器、WRTC 写错地址）。详见 docs/SD2506_Trap_Records.md。 */
    sd2506_time_t t;
    t.year = 2026; t.month = 8; t.day = 28; t.hour = 12; t.minute = 0; t.second = 0; t.week = 4;
    ret = sd2506_set_time(&t);
    SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_set_time() ret=%d (expect 0)", ret);

    ret = sd2506_get_time(&r);
    SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_get_time() after set ret=%d (expect 0)", ret);
    if (ret == SD2506_OK) {
        DBG_INFO("  set     : %04u-%02u-%02u %02u:%02u:%02u",
                 (unsigned int)t.year, (unsigned int)t.month, (unsigned int)t.day,
                 (unsigned int)t.hour, (unsigned int)t.minute, (unsigned int)t.second);
        DBG_INFO("  readback: %04u-%02u-%02u %02u:%02u:%02u",
                 (unsigned int)r.year, (unsigned int)r.month, (unsigned int)r.day,
                 (unsigned int)r.hour, (unsigned int)r.minute, (unsigned int)r.second);
    }
    int match = (r.year == t.year && r.month == t.month && r.day == t.day &&
                r.hour == t.hour && r.minute == t.minute &&
                (r.second == t.second || r.second == ((t.second + 1U) % 60U)));
    SD2506_TEST_CHECK(match, "set==readback (in-session write takes effect)");

    /* TC-RTC-003: 走时。写后等 3s，应前进约 3 秒 */
    if (ret == SD2506_OK) {
        osDelay(3000);
        sd2506_time_t r2;
        int ret2 = sd2506_get_time(&r2);
        if (ret2 == SD2506_OK) {
            int adv = (r2.second + 60 * (r2.minute + 60 * (r2.hour + 24 * r2.day)))
                    - (r.second + 60 * (r.minute + 60 * (r.hour + 24 * r.day)));
            if (adv < 0) adv += 60 * 60 * 24 * 32;
            DBG_INFO("  3s later: %04u-%02u-%02u %02u:%02u:%02u (advanced %d s)",
                     (unsigned int)r2.year, (unsigned int)r2.month, (unsigned int)r2.day,
                     (unsigned int)r2.hour, (unsigned int)r2.minute, (unsigned int)r2.second, adv);
            SD2506_TEST_CHECK(adv >= 2 && adv <= 5, "RTC ticking forward (~3s)");
        }
    }

    SD2506_TEST_REPORT("Phase 1 basic");
}
#endif /* ENABLE_RTC_BASIC_TESTS */

/* ===================== Phase 2：全功能 API 覆盖 ===================== */
#ifdef ENABLE_RTC_API_TESTS
static void sd2506_phase_api(void)
{
    DBG_INFO("=== SD2506 Phase 2: full API coverage ===");

    /* TC-RTC-010: BCD<->DEC 互转（纯算法，确定性，无需硬件交互） */
    int conv_ok = 1;
    uint8_t samples[][2] = {
        {0, 0x00U}, {1, 0x01U}, {9, 0x09U}, {10, 0x10U}, {23, 0x23U},
        {59, 0x59U}, {60, 0x60U}, {99, 0x99U}, {42, 0x42U}, {88, 0x88U}
    };
    for (uint32_t i = 0U; i < (sizeof(samples) / sizeof(samples[0])); i++) {
        uint8_t dec = samples[i][0];
        uint8_t bcd = samples[i][1];
        if (sd2506_dec_to_bcd(dec) != bcd) {
            conv_ok = 0;
            DBG_ERROR("  dec_to_bcd(%u) != 0x%02X", (unsigned int)dec, (unsigned int)bcd);
        }
        if (sd2506_bcd_to_dec(bcd) != dec) {
            conv_ok = 0;
            DBG_ERROR("  bcd_to_dec(0x%02X) != %u", (unsigned int)bcd, (unsigned int)dec);
        }
    }
    SD2506_TEST_CHECK(conv_ok, "bcd<->dec round-trip (10 samples)");

    /* TC-RTC-011: 内部温度读取 */
    int8_t temp = 0;
    int ret = sd2506_get_temperature(&temp);
    SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_get_temperature() ret=%d (expect 0)", ret);
    if (ret == SD2506_OK) {
        DBG_INFO("  temperature: %d C", (int)temp);
        SD2506_TEST_CHECK(temp >= -40 && temp <= 85,
                          "temperature in range [-40,85]: %d", (int)temp);
    }

    /* TC-RTC-012: 电池电压（毫伏） */
    uint16_t volt = 0U;
    ret = sd2506_get_battery_voltage(&volt);
    SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_get_battery_voltage() ret=%d (expect 0)", ret);
    if (ret == SD2506_OK) {
        DBG_INFO("  battery: %u mV", (unsigned int)volt);
        SD2506_TEST_CHECK(volt > 2000U && volt < 5000U,
                          "battery voltage plausible: %u mV", (unsigned int)volt);
    }

    /* TC-RTC-013: 芯片 8 字节 ID */
    uint8_t id[8] = {0};
    ret = sd2506_get_id(id);
    SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_get_id() ret=%d (expect 0)", ret);
    if (ret == SD2506_OK) {
        DBG_INFO("  id: %02X%02X%02X%02X%02X%02X%02X%02X",
                 id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]);
    }

    /* TC-RTC-014: 用户 SRAM 读写回环（addr=0, len=8） */
    uint8_t wbuf[8] = {0xA1U, 0xB2U, 0xC3U, 0xD4U, 0xE5U, 0xF6U, 0x07U, 0x18U};
    uint8_t rbuf[8] = {0};
    ret = sd2506_write_sram(0U, wbuf, 8U);
    SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_write_sram() ret=%d (expect 0)", ret);
    if (ret == SD2506_OK) {
        ret = sd2506_read_sram(0U, rbuf, 8U);
        SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_read_sram() ret=%d (expect 0)", ret);
        int sram_ok = (memcmp(wbuf, rbuf, 8U) == 0);
        SD2506_TEST_CHECK(sram_ok, "SRAM write==readback");
    }

    /* TC-RTC-015: 报警设置 + 清除（验证 API 通路，不影响时间寄存器） */
    sd2506_time_t at;
    at.year = 2026; at.month = 8; at.day = 28; at.hour = 12; at.minute = 0; at.second = 30; at.week = 4;
    ret = sd2506_set_alarm(&at, (uint8_t)(SD2506_AL_EN_EAS | SD2506_AL_EN_EAMN));
    SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_set_alarm() ret=%d (expect 0)", ret);
    ret = sd2506_clear_alarm();
    SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_clear_alarm() ret=%d (expect 0)", ret);

    SD2506_TEST_REPORT("Phase 2 API");
}
#endif /* ENABLE_RTC_API_TESTS */

/* ===================== 套件入口 ===================== */
void sd2506_test_run(void)
{
    DBG_INFO("SD2506 test suite started");

    int ret = sd2506_init();
    SD2506_TEST_CHECK(ret == SD2506_OK, "sd2506_init() ret=%d (expect 0)", ret);

    /* 信息：读取 CTR1 默认状态（确认 WRTC 初始/可写能力，纯诊断） */
    uint8_t c1 = 0x00U;
    if (sd2506_read_ctr1(&c1) == SD2506_OK) {
        DBG_INFO("  CTR1=0x%02X (WRTC2=CTR1.2=%u WRTC3=CTR1.7=%u)",
                 (unsigned int)c1,
                 (unsigned int)((c1 >> 2) & 1U),
                 (unsigned int)((c1 >> 7) & 1U));
    }

    /* 记录原始时间，测试结束恢复，避免把板子时间留在测试值 */
    sd2506_time_t orig;
    int have_orig = (sd2506_get_time(&orig) == SD2506_OK);
    if (!have_orig) {
        DBG_INFO("  WARN: cannot read original time; restore step will be skipped");
    }

    memset(&g_sd2506_test_stats, 0, sizeof(g_sd2506_test_stats));

#ifdef ENABLE_RTC_BASIC_TESTS
    sd2506_phase_basic();
#endif

#ifdef ENABLE_RTC_API_TESTS
    sd2506_phase_api();
#endif

    /* 恢复原始时间（用公共 API，写保护逻辑已由 sd2506.c 正确处理） */
    if (have_orig) {
        int r = sd2506_set_time(&orig);
        DBG_INFO("  restored original time (ret=%d)", r);
    }

    DBG_INFO("SD2506 test suite done");
    for (;;) {
        osDelay(1000);
    }
}

#endif /* TEST_SUITE_RTC */
