/**
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * This file is part of osm2pgsql (https://osm2pgsql.org/).
 *
 * Copyright (C) 2006-2025 by the osm2pgsql developer community.
 * For a full list of authors see the git log.
 */

#include "command-line-app.hpp"

#include "logging.hpp"
#include "util.hpp"

#include <map>

command_line_app_t::command_line_app_t(std::string app_description)
: CLI::App(std::move(app_description))
{
    set_help_flag(); // Disable autogenerated help option

    add_flag("-h,--help", "Print this help message and exit.");
    add_flag("-V,--version", "Show version and exit.");

    init_database_options();
    init_logging_options();
}

bool command_line_app_t::want_help() const { return count("--help"); }

bool command_line_app_t::want_version() const { return count("--version"); }

void command_line_app_t::init_database_options()
{
    add_option_function<std::string>("-d,--database",
                                     [&](std::string const &value) {
                                         m_connection_params.set("dbname",
                                                                 value);
                                     })
        ->description("Database name or PostgreSQL conninfo string.")
        ->type_name("DB")
        ->group("Database options");

    add_option_function<std::string>("-U,--user",
                                     [&](std::string const &value) {
                                         m_connection_params.set("user", value);
                                     })
        ->description("Database user.")
        ->type_name("USERNAME")
        ->group("Database options");

    add_flag_function("-W,--password",
                      [&](int64_t) {
                          m_connection_params.set("password",
                                                  util::get_password());
                      })
        ->description("Force password prompt.")
        ->group("Database options");

    add_option_function<std::string>("-H,--host",
                                     [&](std::string const &value) {
                                         m_connection_params.set("host", value);
                                     })
        ->description(
            "Database server hostname or unix domain socket location.")
        ->type_name("HOST")
        ->group("Database options");

    add_option_function<std::string>("-P,--port",
                                     [&](std::string const &value) {
                                         m_connection_params.set("port", value);
                                     })
        ->description("Database server port.")
        ->type_name("PORT")
        ->group("Database options");
}

void command_line_app_t::init_logging_options()
{
    static std::map<std::string, log_level> const log_levels_map{
        {"debug", log_level::debug},
        {"info", log_level::info},
        {"warn", log_level::warn},
        {"warning", log_level::warn},
        {"error", log_level::error}};

    add_option_function<std::string>(
        "--log-level",
        [](std::string const &level) {
            get_logger().set_level(log_levels_map.find(level)->second);
        })
        ->description(
            "Set log level ('debug', 'info' (default), 'warn', or 'error').")
        ->check(CLI::IsMember(log_levels_map))
        ->default_val("info")
        ->run_callback_for_default()
        ->option_text("LEVEL")
        ->group("Logging options");

    add_option_function<std::string>(
        "--log-progress",
        [&](std::string const &arg) {
            if (arg == "true") {
                get_logger().enable_progress();
            } else if (arg == "false") {
                get_logger().disable_progress();
            } else if (arg == "auto") {
                get_logger().auto_progress();
            } else {
                throw fmt_error("Unknown value for --log-progress option: {}",
                                arg);
            }
        })
        ->description(
            "Log progress to console ('true', 'false', 'auto' (default)).")
        ->option_text("PROGRESS")
        ->group("Logging options");

    add_flag_function("--log-sql", [](int64_t) { get_logger().enable_sql(); })
        ->description("Enable logging of SQL commands for debugging.")
        ->group("Logging options");

    add_flag_function("--log-sql-data",
                      [](int64_t) { get_logger().enable_sql_data(); })
        ->description("Enable logging of all data added to the database.")
        ->group("Logging options");
}
