import sys

import click

from axer.guided import guided_axiomatize
from common.cli_utils import EnumChoice, error_reporting, versioned
from common.z3_utils import set_pretty_print
from problems import Problem
from problems.cli_utils import problem_options

from .axioms import Semantics
from .bruteforce import bruteforce_axiomatize


@click.command(
    help="Add induction axioms according to semantics",
    context_settings=dict(
        show_default=True,
        help_option_names=["-h", "--help"],
    ),
)
@versioned
@click.option(
    "--guided/--bruteforce",
    "-g/-b",
    default=False,
    help="Use guided axiom search "
    "(by first building an infinite model) "
    "or plain bruteforce search.",
)
@click.option(
    "--quiet/--no-quiet",
    "-q/-Q",
    default=False,
    help="When in quiet mode, the found axiom will not be shown.",
)
@click.option("--semantics", "-s", type=EnumChoice(Semantics), default=Semantics.FINITE)
@error_reporting
@problem_options
def main(
    problems: set[Problem], quiet: bool, guided: bool, semantics: Semantics
) -> None:
    set_pretty_print()

    failed = False
    for problem in problems:
        if guided:
            axiom = guided_axiomatize(problem.formula, semantics=semantics)
        else:
            axiom = bruteforce_axiomatize(problem.formula, semantics=semantics)

        if axiom is None:
            failed = True
            if quiet:
                click.secho(".", fg="red", bold=True, nl=False)
            else:
                click.secho(f"{problem.name}: no axiom found", fg="red")
        else:
            if quiet:
                click.secho(".", fg="green", bold=True, nl=False)
            else:
                click.secho(problem.name, fg="green", bold=True, underline=True)
                click.secho(axiom.sexpr())

    if quiet:
        click.echo()

    if failed:
        sys.exit(-1)


if __name__ == "__main__":
    main()
