"""Define a CLI for running LLG3D simulations."""

import argparse

from .parameters import arg_parameters
from . import solvers


def parse_args(args: list[str] | None) -> argparse.Namespace:
    """
    Argument parser for LLG3D.

    Automatically adds arguments from :class:`~llg3d.parameters.arg_parameters`.

    Args:
        args: List of command line arguments

    Returns:
        argparse.Namespace: Parsed arguments
    """
    ArgumentParser: type[argparse.ArgumentParser]
    if solvers.size > 1:
        # Use the MPI version of the ArgumentParser
        from .solvers.mpi import ArgumentParser

    else:
        # Use the original version of the ArgumentParser
        from argparse import ArgumentParser

    parser = ArgumentParser(
        description=__doc__,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )

    # Automatically add arguments from the parameter dictionary
    for name, parameter in arg_parameters.items():
        if "action" not in parameter:
            parameter["type"] = type(parameter["default"])
        parser.add_argument(f"--{name}", **parameter)  # type: ignore[arg-type]

    return parser.parse_args(args)


def main(arg_list: list[str] | None = None):
    """
    Evaluates the command line and runs the simulation.

    Args:
        arg_list: List of command line arguments
    """
    if solvers.size > 1:  # Ensure MPI global variables are initialized
        from .solvers.mpi import initialize_mpi

        initialize_mpi()

    args = parse_args(arg_list)

    Solver = solvers.get_solver_class(args.solver)
    s = Solver(**vars(args))
    if solvers.rank == 0:
        # Display the solver parameters
        print(s)
    s.run()
    s.save()
