#include "zvfs_inode.h"
#include "zvfs.h"

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>

/* ------------------------------------------------------------------ */
/* alloc / free                                                         */
/* ------------------------------------------------------------------ */

struct zvfs_inode *inode_alloc(uint64_t blob_id, mode_t mode, zvfs_itype_t itype) {
    struct zvfs_inode *in = calloc(1, sizeof(*in));
    if (!in)
        return NULL;

    in->blob_id      = blob_id;
    in->logical_size = 0;
    in->itype        = itype;
    in->mode         = mode;
    in->uid          = getuid();
    in->gid          = getgid();

    time_t now  = time(NULL);
    in->atime   = now;
    in->mtime   = now;
    in->deleted = false;

    atomic_init(&in->ref_count, 1);
    pthread_mutex_init(&in->mu, NULL);

    return in;
}

void inode_free(struct zvfs_inode *inode){
    if (!inode)
        return;
    pthread_mutex_destroy(&inode->mu);
    free(inode);
}


/* ------------------------------------------------------------------ */
/* hash table operations  （调用方持有 g_fs.inode_mu）                  */
/* ------------------------------------------------------------------ */

void inode_insert(struct zvfs_inode *inode){
    HASH_ADD(hh, g_fs.inode_table, blob_id, sizeof(uint64_t), inode);
}

struct zvfs_inode *inode_lookup(uint64_t blob_id) {
    struct zvfs_inode *in = NULL;
    HASH_FIND(hh, g_fs.inode_table, &blob_id, sizeof(uint64_t), in);
    return in;
}

void inode_remove(uint64_t blob_id) {
    struct zvfs_inode *in = inode_lookup(blob_id);
    if (in)
        HASH_DELETE(hh, g_fs.inode_table, in);
}

/* ------------------------------------------------------------------ */
/* size / timestamp helpers  （调用方持有 inode->mu）                   */
/* ------------------------------------------------------------------ */

int inode_update_size(struct zvfs_inode *inode, int real_fd, uint64_t new_size) {
    inode->logical_size = new_size;
    if (real_fd >= 0)
        return ftruncate(real_fd, (off_t)new_size);   /* 同步 st_size，忽略错误 */
    return 0;
}

void inode_touch_atime(struct zvfs_inode *inode) {
    inode->atime = time(NULL);
}

void inode_touch_mtime(struct zvfs_inode *inode)
{
    inode->mtime = time(NULL);
}