// SPDX-License-Identifier: GPL-2.0-only
/*
 *  ppm/src/cmd/info.c
 *
 *  Copyright (C) 2026 Project Tick
 */

#include <ppm/manifest.h>
#include <ppm/registry.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

static void print_version(const ppm_version_t *v) {
    printf("%u.%u.%u", v->major, v->minor, v->patch);
    if (v->pre)   printf("-%s", v->pre);
    if (v->build) printf("+%s", v->build);
}

static void print_manifest(const ppm_manifest_t *m) {
    printf("name:     %s\n", m->name);
    printf("version:  ");
    print_version(&m->version);
    putchar('\n');
    if (m->summary)  printf("summary:  %s\n", m->summary);
    if (m->license)  printf("license:  %s\n", m->license);
    if (m->homepage) printf("homepage: %s\n", m->homepage);
    if (m->authors) {
        printf("authors:");
        for (char **p = m->authors; *p; p++) printf("\n  - %s", *p);
        putchar('\n');
    }
    if (m->source.url) {
        printf("source:\n");
        printf("  url:  %s\n", m->source.url);
        char hex[PPM_SHA512_HEX_BUFSZ];
        ppm_sha512_to_hex(&m->source.hash, hex);
        int hash_set = 0;
        for (size_t i = 0; i < PPM_SHA512_BYTES; i++)
            if (m->source.hash.bytes[i]) { hash_set = 1; break; }
        if (hash_set) printf("  hash: sha512:%s\n", hex);
    }
    if (m->deps_len) {
        printf("dependencies:\n");
        for (size_t i = 0; i < m->deps_len; i++)
            printf("  %s = %s\n", m->deps[i].name, m->deps[i].spec);
    }
    if (m->build_deps_len) {
        printf("build-dependencies:\n");
        for (size_t i = 0; i < m->build_deps_len; i++)
            printf("  %s = %s\n", m->build_deps[i].name, m->build_deps[i].spec);
    }
}

int ppm_cmd_info(int argc, char **argv) {
    /*
     * Two modes:
     *   ppm info <path-to-ppm.toml>   read a local file (LOCAL validation)
     *   ppm info <package-name>       look up the newest published version
     *                                 in the registry (PUBLISHED validation,
     *                                 signature-enforced)
     *
     * We disambiguate by checking whether the argument ends in ".toml" or
     * contains a path separator.
     */
    if (argc < 2) {
        ppm_error("usage: ppm info <path-to-ppm.toml | package-name>");
        return 2;
    }
    const char *arg = argv[1];
    const char *dot = strrchr(arg, '.');
    int looks_like_path = (strchr(arg, '/') != NULL) ||
                          (dot && strcmp(dot, ".toml") == 0);

    if (!looks_like_path) {
        /* Registry lookup: newest version of the named package. */
        ppm_registry_t *reg = NULL;
        if (ppm_cmd_open_registry(&reg) != PPM_OK) {
            ppm_error("could not open registry");
            return 1;
        }

        ppm_version_t *vs = NULL;
        size_t vn = 0;
        ppm_error_t err = ppm_registry_versions(reg, arg, &vs, &vn);
        if (err || vn == 0) {
            ppm_error("package '%s' not found in registry", arg);
            free(vs);
            ppm_registry_close(reg);
            return 1;
        }

        ppm_manifest_t *m = NULL;
        err = ppm_registry_manifest(reg, arg, &vs[0], &m); /* newest first */
        free(vs);
        if (err) {
            ppm_error("could not load manifest for '%s': %s",
                      arg, ppm_strerror(err));
            ppm_registry_close(reg);
            return 1;
        }
        print_manifest(m);
        ppm_manifest_free(m);
        ppm_registry_close(reg);
        return 0;
    }

    ppm_manifest_t *m = NULL;
    ppm_error_t err = ppm_manifest_load(arg, &m);
    if (err) {
        ppm_error("could not load manifest: %s", ppm_strerror(err));
        return 1;
    }
    if ((err = ppm_manifest_validate(m, PPM_MANIFEST_LOCAL))) {
        ppm_manifest_free(m);
        return 1;
    }
    print_manifest(m);
    ppm_manifest_free(m);
    return 0;
}
