#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include "common/config.h"
#include "common/utils.h"
#include "fs/zvfs.h"
#include "fs/zvfs_inode.h"
#include "fs/zvfs_path_entry.h"
#include "fs/zvfs_open_file.h"

#include <sys/xattr.h>
#include <sys/types.h>
#include <errno.h>
struct zvfs_fs g_fs = {0};

/* ------------------------------------------------------------------ */
/* init / destroy                                                       */
/* ------------------------------------------------------------------ */

int zvfs_fs_init(void) {
    memset(&g_fs, 0, sizeof(g_fs));

    if (pthread_mutex_init(&g_fs.inode_mu, NULL) != 0) goto fail_inode;
    if (pthread_mutex_init(&g_fs.path_mu,  NULL) != 0) goto fail_path;
    if (pthread_mutex_init(&g_fs.fd_mu,    NULL) != 0) goto fail_fd;

    return 0;

fail_fd:
    pthread_mutex_destroy(&g_fs.path_mu);
fail_path:
    pthread_mutex_destroy(&g_fs.inode_mu);
fail_inode:
    return -1;
}

/**
 * 销毁 fd_table：每个 openfile 只释放结构体内存，
 * blob_close / inode 引用计数的清理应由上层在进程退出前完成。
 * 这里做"强制兜底"清理，避免内存泄漏。
 */
int zvfs_fs_destroy(void) {

    pthread_mutex_lock(&g_fs.fd_mu);
    {
        struct zvfs_open_file *of, *tmp_of;
        HASH_ITER(hh, g_fs.fd_table, of, tmp_of) {
            HASH_DEL(g_fs.fd_table, of);
            openfile_free(of);
        }
    }
    pthread_mutex_unlock(&g_fs.fd_mu);

    /* 销毁 path_cache */
    pthread_mutex_lock(&g_fs.path_mu);
    {
        struct zvfs_path_entry *pe, *tmp_pe;
        HASH_ITER(hh, g_fs.path_cache, pe, tmp_pe) {
            HASH_DEL(g_fs.path_cache, pe);
            free(pe->path);
            free(pe);
        }
    }
    pthread_mutex_unlock(&g_fs.path_mu);

    /* 销毁 inode_table */
    pthread_mutex_lock(&g_fs.inode_mu);
    {
        struct zvfs_inode *in, *tmp_in;
        HASH_ITER(hh, g_fs.inode_table, in, tmp_in) {
            HASH_DEL(g_fs.inode_table, in);
            inode_free(in);
        }
    }
    pthread_mutex_unlock(&g_fs.inode_mu);

    pthread_mutex_destroy(&g_fs.fd_mu);
    pthread_mutex_destroy(&g_fs.path_mu);
    pthread_mutex_destroy(&g_fs.inode_mu);

    return 0;
}

/* ------------------------------------------------------------------ */
/* xattr helpers                                                        */
/* ------------------------------------------------------------------ */

int zvfs_xattr_write_blob_id(int fd, uint64_t blob_id)
{
    if (fsetxattr(fd, ZVFS_XATTR_BLOB_ID, &blob_id, sizeof(blob_id), 0) < 0)
        return -1;
    return 0;
}

int zvfs_xattr_read_blob_id(int fd, uint64_t *blob_id_out)
{
    ssize_t ret = fgetxattr(fd, ZVFS_XATTR_BLOB_ID, blob_id_out, sizeof(uint64_t));
    if (ret != sizeof(uint64_t)) {
        if (ret >= 0)
            errno = EIO;   /* 长度不对，视为损坏 */
        return -1;
    }
    return 0;
}