/**
 * @file     zms_test.c
 * @brief    ZMS bug reproducer — reliably triggers data_wra recovery error
 *
 * This is a standalone test snippet that directly calls the ZMS (Zephyr Memory
 * Storage) library API. It reproduces the data_wra recovery bug caused by
 * "*addr -= 2 * fs->ate_size" in zms_recover_last_ate(), and validates the fix
 * by changing it to "*addr -= fs->ate_size".
 *
 * Entry point: drv_storage_zms_test()
 *
 * Bug symptom (with *addr -= 2 * fs->ate_size):
 *   1. Write "Hello, ZMS!"        to ID 0x1A80
 *   2. Advance 3 sectors           → triggers GC
 *   3. Remount ZMS                 → zms_recover_last_ate() called
 *   4. Read 0x1A80                 → OK, returns "Hello, ZMS!"
 *   5. Write "111111111111111..."  to ID 0x1A81
 *   6. Read 0x1A80 again           → BUG: returns 0x1A81's data instead
 *      (0x1A80 data overwritten by 0x1A81)
 *
 * Root cause:
 *   "*addr -= 2 * fs->ate_size" skips the valid ATE at
 *   sector_size - 3 * ate_size, causing data_wra to be recovered too low.
 *   Subsequent writes then reuse the already-occupied data region.
 *
 * Fix:
 *   Change to "*addr -= fs->ate_size". data_wra is recovered correctly and
 *   0x1A80 data is no longer overwritten.
 */

static struct zms_fs fs;
#define ZMS_PARTITION        storage_partition
#define ZMS_PARTITION_DEVICE FIXED_PARTITION_DEVICE(ZMS_PARTITION)
#define ZMS_PARTITION_OFFSET FIXED_PARTITION_OFFSET(ZMS_PARTITION)
#define ZMS_PARTITION_SIZE   FIXED_PARTITION_SIZE(ZMS_PARTITION)




bool drv_storage_init(void)
{

    struct flash_pages_info info;

    fs.flash_device = ZMS_PARTITION_DEVICE;
    if (!device_is_ready(fs.flash_device)) {
        LOG_ERR("Storage device %s is not ready\n", fs.flash_device->name);
    return false;
    }
    fs.offset = ZMS_PARTITION_OFFSET;
    int rc = flash_get_page_info_by_offs(fs.flash_device, fs.offset, &info);
    if (rc) {
        LOG_ERR("Unable to get page info, rc=%d\n", rc);
    return false;
    }
    fs.sector_size = info.size;
    fs.sector_count = ZMS_PARTITION_SIZE / info.size; // 4096*4=16KB defined in prj.conf

    rc = zms_mount(&fs);
    if (rc) {
        LOG_ERR("Storage Init failed, rc=%d\n", rc);
    return false;
    } 
    LOG_INF("zms info - sector_size: %u, counter: %u, offset: 0x%X partitionsize:0x%x",
        fs.sector_size, fs.sector_count, (uint32_t)fs.offset, ZMS_PARTITION_SIZE);



    return true;
}


bool drv_storage_zms_clean_all_and_reinit(void)
{

	struct flash_pages_info info;
	fs.flash_device = ZMS_PARTITION_DEVICE;
	if (!device_is_ready(fs.flash_device)) {
		LOG_ERR("Storage device %s is not ready\n", fs.flash_device->name);
    return false;
	}
	fs.offset = ZMS_PARTITION_OFFSET;
	int rc = flash_get_page_info_by_offs(fs.flash_device, fs.offset, &info);
	if (rc) {
		LOG_ERR("Unable to get page info, rc=%d\n", rc);
    return false;
	}
	fs.sector_size = info.size;
	fs.sector_count = ZMS_PARTITION_SIZE / info.size; // 4096*4=16KB defined in prj.conf

    /* 1. 先清空整个 ZMS 文件系统（相当于重新初始化数据） */
    rc = zms_clear(&fs);
    if (rc) {
        LOG_ERR("zms_clear failed: %d", rc);
        return rc;
    }

     /* 2. 再挂载 ZMS 文件系统 */
	rc = zms_mount(&fs);
	if (rc) {
		LOG_ERR("Storage Init failed, rc=%d\n", rc);
    return false;
	} 
	LOG_INF("zms info - sector_size: %u, counter: %u, offset: 0x%X partitionsize:0x%x",
		fs.sector_size, fs.sector_count, (uint32_t)fs.offset, ZMS_PARTITION_SIZE);



    return true;
}


void drv_storage_zms_test(void)
{
    const char *test_data = "Hello, ZMS!";
    const char *test1_data = "1111111111111111111111111";
    char read_buffer[20] = {0};

    while(1){

      drv_storage_zms_clean_all_and_reinit();
      
      int rc = zms_write(&fs, 0x1A80, test_data, strlen(test_data));
      if (rc >= 0) {
          //LOG_ERR("ZMS write successful");
      } else {
          LOG_ERR("ZMS write failed, err=%d", rc);
          return;
      }
      zms_sector_use_next(&fs);
      zms_sector_use_next(&fs);
      zms_sector_use_next(&fs);

      drv_storage_init();

      rc = zms_read(&fs, 0x1A80, read_buffer, sizeof(read_buffer));
      if (rc >= 0) {
          LOG_ERR("ZMS read 0X1A80 one successful, data: %s", read_buffer);
      } else {
          LOG_ERR("ZMS read failed, err=%d", rc);
          return;
      }

      if (memcmp(read_buffer, test_data, strlen(test_data)) == 0) {
          //LOG_ERR("ZMS data match: %s", read_buffer);
      } else {
          LOG_ERR("ZMS data mismatch");
      }

      rc = zms_write(&fs, 0x1A81, test1_data, strlen(test1_data));
      if (rc >= 0) {
          //LOG_ERR("ZMS write successful");
      } else {
          LOG_ERR("ZMS write failed, err=%d", rc);
          return;
      }

      rc = zms_read(&fs, 0x1A80, read_buffer, sizeof(read_buffer));
      if (rc >= 0) {
          LOG_ERR("ZMS read 0X1A80 two successful, data: %s", read_buffer);
      } else {
          LOG_ERR("ZMS read failed, err=%d", rc);
          return;
      }

      k_msleep(3000);
    }

}