#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "zvfs_hook_sync.h"
#include "zvfs_hook_init.h"
#include "zvfs_hook_reentrant.h"
#include "fs/zvfs.h"
#include "fs/zvfs_open_file.h"
#include "spdk_engine/io_engine.h"

#include <errno.h>
#include <pthread.h>

/* ------------------------------------------------------------------ */
/* fsync                                                                */
/* ------------------------------------------------------------------ */

int
fsync(int fd)
{
    ZVFS_HOOK_ENTER();

    struct zvfs_open_file *of = NULL;
    if (!ZVFS_IN_HOOK()) {
        pthread_mutex_lock(&g_fs.fd_mu);
        of = openfile_lookup(fd);
        pthread_mutex_unlock(&g_fs.fd_mu);
    }

    if (!of) {
        int r = real_fsync(fd);
        ZVFS_HOOK_LEAVE();
        return r;
    }

    zvfs_ensure_init();

    /*
     * zvfs 无写缓冲区，数据已在 blob_write 时落到 SPDK 存储。
     * 调用 blob_sync_md 确保 blob 元数据（size 等）持久化。
     */
    int r = blob_sync_md(of->handle_id);
    if (r < 0) errno = EIO;

    ZVFS_HOOK_LEAVE();
    return (r < 0) ? -1 : 0;
}

/* ------------------------------------------------------------------ */
/* fdatasync                                                            */
/* ------------------------------------------------------------------ */

int
fdatasync(int fd)
{
    ZVFS_HOOK_ENTER();

    struct zvfs_open_file *of = NULL;
    if (!ZVFS_IN_HOOK()) {
        pthread_mutex_lock(&g_fs.fd_mu);
        of = openfile_lookup(fd);
        pthread_mutex_unlock(&g_fs.fd_mu);
    }

    if (!of) {
        int r = real_fdatasync(fd);
        ZVFS_HOOK_LEAVE();
        return r;
    }

    zvfs_ensure_init();

    /*
     * fdatasync 只保证数据持久化，不要求元数据（atime 等）同步。
     * 对 zvfs：数据已无缓冲，blob_sync_md 同步 size 元数据即可。
     * 与 fsync 实现相同——如果将来区分数据/元数据可在此分叉。
     */
    int r = blob_sync_md(of->handle_id);
    if (r < 0) errno = EIO;

    ZVFS_HOOK_LEAVE();
    return (r < 0) ? -1 : 0;
}

/* ------------------------------------------------------------------ */
/* sync_file_range                                                      */
/* ------------------------------------------------------------------ */

int
sync_file_range(int fd, off_t offset, off_t nbytes, unsigned int flags)
{
    ZVFS_HOOK_ENTER();

    struct zvfs_open_file *of = NULL;
    if (!ZVFS_IN_HOOK()) {
        pthread_mutex_lock(&g_fs.fd_mu);
        of = openfile_lookup(fd);
        pthread_mutex_unlock(&g_fs.fd_mu);
    }

    if (!of) {
        int r = real_sync_file_range
            ? real_sync_file_range(fd, offset, nbytes, flags)
            : (errno = ENOSYS, -1);
        ZVFS_HOOK_LEAVE();
        return r;
    }

    zvfs_ensure_init();

    /*
     * PostgreSQL checkpointer 用此调用按范围刷脏页。
     * zvfs 无页缓存，数据实时落盘，直接返回 0。
     * 参数合法性检查与内核保持一致：
     *   offset < 0 或 nbytes < 0 → EINVAL
     *   flags 包含非法位 → EINVAL
     */
    (void)offset; (void)nbytes; (void)flags;

    ZVFS_HOOK_LEAVE();
    return 0;
}
