// SPDX-License-Identifier: GPL-2.0-only
/*
 *  ppm/src/cmd/list.c
 *
 *  Print the packages installed in the active profile by reading the
 *  manifest.toml that lives next to the `current` symlink.
 *
 *  Copyright (C) 2026 Project Tick
 */

#include <ppm/store.h>
#include <ppm/transaction.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#include "../cli.h"
#include "../util/log.h"
#include "../util/path.h"
#include "../util/toml.h"
#include "common.h"

static char *slurp(const char *path) {
    FILE *f = fopen(path, "rb");
    if (!f) return NULL;
    fseek(f, 0, SEEK_END);
    long sz = ftell(f);
    fseek(f, 0, SEEK_SET);
    char *buf = malloc((size_t)sz + 1);
    if (!buf) { fclose(f); return NULL; }
    size_t n = fread(buf, 1, (size_t)sz, f);
    fclose(f);
    buf[n] = '\0';
    return buf;
}

int ppm_cmd_list(int argc, char **argv) {
    (void)argc; (void)argv;

    ppm_store_t *store = NULL;
    if (ppm_cmd_open_store(&store) != PPM_OK) {
        ppm_error("could not open store");
        return 1;
    }

    char *gen_dir = NULL;
    if (ppm_txn_current(store, "default", &gen_dir) != PPM_OK || !gen_dir) {
        ppm_info("no packages installed in profile 'default'");
        ppm_store_close(store);
        return 0;
    }

    char *mpath;
    if (ppm_path_join(gen_dir, "manifest.toml", &mpath) != PPM_OK) {
        free(gen_dir);
        ppm_store_close(store);
        return 1;
    }
    free(gen_dir);

    char *buf = slurp(mpath);
    free(mpath);
    if (!buf) { ppm_store_close(store); return 1; }

    ppm_toml_node_t *root = NULL;
    char *err = NULL;
    if (ppm_toml_parse(buf, &root, &err) != PPM_OK) {
        ppm_error("list: %s", err ? err : "parse error");
        free(err); free(buf);
        ppm_store_close(store);
        return 1;
    }
    free(buf);

    const ppm_toml_node_t *pkg = ppm_toml_get_table(root, "package");
    if (!pkg || pkg->u.tbl.len == 0) {
        printf("(no packages in active profile)\n");
        ppm_toml_free(root);
        ppm_store_close(store);
        return 0;
    }
    for (size_t i = 0; i < pkg->u.tbl.len; i++) {
        const ppm_toml_node_t *v = pkg->u.tbl.pairs[i].value;
        if (v->kind != PPM_TOML_TABLE) continue;
        const char *name = ppm_toml_get_str(v, "name");
        const char *ver  = ppm_toml_get_str(v, "version");
        printf("%-30s  %s\n", name ? name : "?", ver ? ver : "?");
    }

    ppm_toml_free(root);
    ppm_store_close(store);
    return 0;
}
