"""Generate sample configuration files for COSIPY.

Usage:

Entry point:
``cosipy-setup [-y] [-o <path>]``

From source:
``python -m cosipy.utilities.setup_cosipy.setup_cosipy -i <input> -o <output> -s <static> [-u <path>] [-b <date>] [-e <date>]``

Options and arguments:

Optional switches:
    -h, --help              Show this help message and exit.
    -y, --yes               Silently overwrite existing configuration
                                files.

Optional arguments:
    -o, --output <path>     Relative path to target configuration
                                directory.
"""

import argparse
import inspect
import os
import shutil


def get_user_arguments() -> argparse.Namespace:
    """Parse user arguments when run as main.

    Optional switches:
        -h, --help              Show this help message and exit.
        -y, --yes               Silently overwrite existing
                                    configuration files.

    Optional arguments:
        -o, --output <path>     Relative path to target configuration
                                    directory.

    Returns:
        Namespace of user arguments.
    """

    tagline = "Generate configuration files for COSIPY"
    parser = argparse.ArgumentParser(
        prog="cosipy.utilities.gen_config", description=tagline
    )

    # Optional switches
    parser.add_argument(
        "-y",
        "--yes",
        action="store_true",
        default=False,
        dest="overwrite",
        help="silently overwrite existing configuration files",
    )

    # Optional arguments
    parser.add_argument(
        "-o",
        "--output",
        default=None,
        dest="output_path",
        type=str,
        metavar="<path>",
        required=False,
        help="relative path to target configuration directory",
    )

    arguments = parser.parse_args()

    return arguments


def check_file_exists(file_path):
    if not os.path.isfile(file_path):
        raise FileNotFoundError(f"{file_path} not found.")


def get_sample_directory() -> str:
    """Get the path to the sample directory.

    Returns:
        Path to sample configuration directory.
    """
    # Package is not installed in working directory
    filename = inspect.getfile(inspect.currentframe())
    filename = filename.rsplit("/", 1)
    src_dir = f"{filename[0]}"

    return src_dir


def copy_file_to_target(
    basename: str,
    source_dir: str,
    target_dir: str,
    silent_overwrite: bool = False,
):
    """Copy a file to a target directory.

    Args:
        basename: Name of file.
        source_dir: Source directory of file.
        target_dir: Target directory of the copied file.
        silent_overwrite: Silently overwrite existing files in target
            directory. Default False.
    """

    target_path = f"{target_dir}/{basename}"
    source_path = f"{source_dir}/{basename}"
    overwrite = True  # otherwise no file created if missing

    if not silent_overwrite and os.path.isfile(target_path):
        prompt = f"{basename} already exists in {target_dir}/\nReplace target? [y/N] "
        overwrite = get_user_confirmation(prompt)
    if overwrite:
        shutil.copyfile(source_path, target_path, follow_symlinks=True)
    else:
        print("Skipping...")

def get_user_confirmation(prompt: str) -> bool:
    """Get user confirmation.

    Args:
        prompt: Prompt to display to user.

    Returns:
        True if user confirms, False otherwise.
    """
    user_input: str = input(prompt).lower().strip()
    if user_input not in ("y", "yes", "n", "no", ""):
        print("Please enter 'yes' or 'no'.\n")
        return get_user_confirmation(prompt)
    return user_input in ("y", "yes")

def main():
    args = get_user_arguments()

    sample_path = get_sample_directory()
    if not args.output_path:
        target_path = os.getcwd()
    else:
        target_path = args.output_path
        os.makedirs(target_path, exist_ok=True)
    if target_path == sample_path:
        raise ValueError("The target and source paths cannot be identical.")

    config_files = [
        "config.toml",
        "constants.toml",
        "slurm_config.toml",
        "utilities_config.toml",
    ]
    for file in config_files:
        check_file_exists(file_path=f"{sample_path}/{file}")
        copy_file_to_target(
            basename=file,
            source_dir=sample_path,
            target_dir=target_path,
            silent_overwrite=args.overwrite,
        )


if __name__ == "__main__":
    main()
