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

#include "common.h"

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

#include "../util/log.h"
#include "../util/path.h"

/*
 * These three are baked in at configure time. Look at configure.ac and
 * src/Makefile.am for where they come from. Do not introduce an
 * override mechanism — ppm is a system package manager and the registry
 * is a single, canonical, build-time fact.
 */
#ifndef PPM_STORE_DIR
#  error "PPM_STORE_DIR must be defined by the build system"
#endif
#ifndef PPM_REGISTRY_DIR
#  error "PPM_REGISTRY_DIR must be defined by the build system"
#endif
#ifndef PPM_REGISTRY_URL
#  error "PPM_REGISTRY_URL must be defined by the build system"
#endif

const char *ppm_cmd_store_dir   (void) { return PPM_STORE_DIR;    }
const char *ppm_cmd_registry_dir(void) { return PPM_REGISTRY_DIR; }
const char *ppm_cmd_registry_url(void) { return PPM_REGISTRY_URL; }

ppm_error_t ppm_cmd_open_store(ppm_store_t **out) {
    return ppm_store_open(PPM_STORE_DIR, out);
}

ppm_error_t ppm_cmd_open_registry(ppm_registry_t **out) {
    if (ppm_path_is_dir(PPM_REGISTRY_DIR)) {
        return ppm_registry_open(PPM_REGISTRY_DIR, out);
    }

    /* First run on this machine: clone the canonical registry. */
    char *parent = strdup(PPM_REGISTRY_DIR);
    if (!parent) return PPM_ERR_NOMEM;
    char *slash = strrchr(parent, '/');
    if (slash && slash != parent) {
        *slash = '\0';
        ppm_error_t e = ppm_path_mkdirs(parent, 0755);
        if (e) {
            ppm_error("cannot create '%s' (need root?): %s",
                      parent, ppm_strerror(e));
            free(parent);
            return e;
        }
    }
    free(parent);

    ppm_info("cloning registry: %s -> %s", PPM_REGISTRY_URL, PPM_REGISTRY_DIR);
    return ppm_registry_clone(PPM_REGISTRY_URL, PPM_REGISTRY_DIR, out);
}

ppm_error_t ppm_cmd_require_root_or_writable_store(void) {
    /* Try to create the store dir; if we cannot, log a friendly hint. */
    ppm_error_t err = ppm_path_mkdirs(PPM_STORE_DIR, 0755);
    if (err == PPM_OK && access(PPM_STORE_DIR, W_OK) == 0) return PPM_OK;

    if (geteuid() != 0) {
        ppm_error("'%s' is not writable by uid %u.\n"
                  "       ppm is a system package manager; re-run with sudo.",
                  PPM_STORE_DIR, (unsigned)geteuid());
    } else {
        ppm_error("'%s' is not writable even as root: %s",
                  PPM_STORE_DIR, strerror(errno));
    }
    return PPM_ERR_PERMISSION;
}