// SPDX-FileCopyrightText: Peter Pentchev <roam@ringlet.net>
// SPDX-License-Identifier: BSD-2-Clause
//! Parse the command-line arguments for the generate-tests tool.

use camino::Utf8Path;
use clap::Parser as _;
use clap_derive::Parser;
use eyre::{Result, WrapErr as _, bail, eyre};
use log::LevelFilter;
use simple_logger::SimpleLogger;

use generate_tests::defs::{Config, OutputTarget};

/// The command-line interface arguments definition.
#[derive(Debug, Parser)]
struct Cli {
    /// Check-only mode; report whether the file would have been modified.
    #[clap(long)]
    check_only: bool,

    /// The path to the shell program to generate.
    #[clap(long, short = 'o')]
    output_file: String,

    /// Verbose operation: display diagnostic messages.
    #[clap(long, short = 'v')]
    verbose: bool,
}

/// Initialize the logging subsystem provided by the `log` library.
fn setup_logging(verbose: bool) -> Result<()> {
    SimpleLogger::new()
        .with_level(if verbose {
            LevelFilter::Debug
        } else {
            LevelFilter::Info
        })
        .init()
        .context("Could not initialize the tracing logger")
}

/// Parse the command-line arguments.
pub fn parse_args() -> Result<Config> {
    let args = Cli::try_parse().context("Could not parse the command-line arguments")?;
    setup_logging(args.verbose)?;

    let output_file = if args.output_file == "-" {
        if args.check_only {
            bail!("Check-only mode requires an output file to be specified");
        }
        OutputTarget::Stdout
    } else {
        let opath = Utf8Path::new(&args.output_file);
        let oparent = opath.parent().ok_or_else(|| {
            eyre!(
                "Could not determine the parent directory for the output file {output_file}",
                output_file = args.output_file
            )
        })?;
        let oparent_canon = if oparent.as_os_str().is_empty() {
            Utf8Path::new(".")
                .canonicalize_utf8()
                .context("Could not canonicalize the current working directory")?
        } else {
            oparent.canonicalize_utf8().with_context(|| {
                format!(
                    "Could not canonicalize {oparent} for the output file {output_file}",
                    output_file = args.output_file,
                )
            })?
        };
        OutputTarget::File(oparent_canon.join(opath.file_name().ok_or_else(|| {
            eyre!(
                "No filename portion in the output file path {output_file}",
                output_file = args.output_file
            )
        })?))
    };

    Config::builder()
        .check_only(args.check_only)
        .root_dir(
            camino::absolute_utf8(".")
                .context("Could not get the current working directory as valid UTF-8")?,
        )
        .output_file(output_file)
        .build()
        .context("Could not build the generate-tests internal config object")
}
