/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include <stdlib.h>

#include "analyze.h"
#include "analyze-condition.h"
#include "analyze-verify-util.h"
#include "condition.h"
#include "conf-parser.h"
#include "load-fragment.h"
#include "service.h"

static int parse_condition(Unit *u, const char *line) {
        assert(u);
        assert(line);

        for (ConditionType t = 0; t < _CONDITION_TYPE_MAX; t++) {
                ConfigParserCallback callback;
                Condition **target;
                const char *p, *name;

                name = condition_type_to_string(t);
                p = startswith(line, name);
                if (p)
                        target = &u->conditions;
                else {
                        name = assert_type_to_string(t);
                        p = startswith(line, name);
                        if (!p)
                                continue;

                        target = &u->asserts;
                }

                p += strspn(p, WHITESPACE);

                if (*p != '=')
                        continue;
                p++;

                p += strspn(p, WHITESPACE);

                if (condition_takes_path(t))
                        callback = config_parse_unit_condition_path;
                else
                        callback = config_parse_unit_condition_string;

                return callback(NULL, "(cmdline)", 0, NULL, 0, name, t, p, target, u);
        }

        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line);
}

_printf_(7, 8)
static int log_helper(void *userdata, int level, int error, const char *file, int line, const char *func, const char *format, ...) {
        Unit *u = ASSERT_PTR(userdata);
        va_list ap;
        int r;

        /* "upgrade" debug messages */
        level = MIN(LOG_INFO, level);

        va_start(ap, format);
        r = log_object_internalv(level, error, file, line, func,
                                 NULL,
                                 u->id,
                                 NULL,
                                 NULL,
                                 format, ap);
        va_end(ap);

        return r;
}

static int verify_conditions(char **lines, LookupScope scope, const char *unit, const char *root) {
        _cleanup_(manager_freep) Manager *m = NULL;
        Unit *u;
        int r, q = 1;

        if (unit) {
                _cleanup_strv_free_ char **filenames = NULL;
                _cleanup_free_ char *var = NULL;

                filenames = strv_new(unit);
                if (!filenames)
                        return log_oom();

                r = verify_generate_path(&var, filenames);
                if (r < 0)
                        return log_error_errno(r, "Failed to generate unit load path: %m");

                assert_se(set_unit_path(var) >= 0);
        }

        r = manager_new(scope, MANAGER_TEST_RUN_MINIMAL, &m);
        if (r < 0)
                return log_error_errno(r, "Failed to initialize manager: %m");

        log_debug("Starting manager...");
        r = manager_startup(m, /* serialization= */ NULL, /* fds= */ NULL, root);
        if (r < 0)
                return r;

        if (unit) {
                _cleanup_free_ char *prepared = NULL;

                r = verify_prepare_filename(unit, &prepared);
                if (r < 0)
                        return log_error_errno(r, "Failed to prepare filename %s: %m", unit);

                r = manager_load_startable_unit_or_warn(m, NULL, prepared, &u);
                if (r < 0)
                        return r;
        } else {
                r = unit_new_for_name(m, sizeof(Service), "test.service", &u);
                if (r < 0)
                        return log_error_errno(r, "Failed to create test.service: %m");

                STRV_FOREACH(line, lines) {
                        r = parse_condition(u, *line);
                        if (r < 0)
                                return r;
                }
        }

        r = condition_test_list(u->asserts, environ, assert_type_to_string, log_helper, u);
        if (u->asserts)
                log_notice("Asserts %s.", r > 0 ? "succeeded" : "failed");

        q = condition_test_list(u->conditions, environ, condition_type_to_string, log_helper, u);
        if (u->conditions)
                log_notice("Conditions %s.", q > 0 ? "succeeded" : "failed");

        return r > 0 && q > 0 ? 0 : -EIO;
}

int verb_condition(int argc, char *argv[], void *userdata) {
        int r;

        r = verify_conditions(strv_skip(argv, 1), arg_scope, arg_unit, arg_root);
        if (r < 0)
                return r;

        return EXIT_SUCCESS;
}
