import argparse
import os
import sys
from pathlib import Path

from brake.colors import Color, colorize
from brake.graph import TargetGraph
from brake.runner import TargetGraphRunner


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description="A minimalistic yet powerful build tool",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    parser.add_argument(
        "-j",
        "--max-jobs",
        type=int,
        default=os.cpu_count(),
        help="The maximum number of jobs to run in parallel",
    )
    parser.add_argument(
        "-f",
        "--file",
        help="Path to the file containing the brake targets",
        type=Path,
        default="Brakefile",
    )
    subparsers = parser.add_subparsers()
    run_parser = subparsers.add_parser("run", help="Run a task")
    run_parser.add_argument("target", help="The target to run", nargs="?", default=None)
    run_parser.set_defaults(func=run_target)

    help_parser = subparsers.add_parser("help", help="Display the targets help")
    help_parser.set_defaults(func=show_targets_help)

    mermaid_parser = subparsers.add_parser("graph", help="Display the targets as a graph")
    mermaid_parser.add_argument(
        "--syntax",
        help="The graph syntax to display the graph in",
        choices=("dot", "mermaid"),
        default="dot",
    )
    mermaid_parser.set_defaults(func=show_targets_graph)
    args = parser.parse_args()
    if not hasattr(args, "func") or not args.func:
        print(parser.format_help())
        sys.exit(0)
    return args


def run_target(graph: TargetGraph, args: argparse.Namespace):
    runner = TargetGraphRunner(target_graph=graph)
    try:
        runner.run(args.target, max_workers=args.max_jobs)
    except Exception as exc:
        print(colorize(str(exc), color=Color.RED))
        sys.exit(1)


def show_targets_help(graph: TargetGraph, args: argparse.Namespace):
    print("\n".join(graph.help()))


def show_targets_graph(graph: TargetGraph, args: argparse.Namespace):
    if args.syntax == "dot":
        lines = graph.as_dot()
    else:
        lines = graph.as_mermaid()
    print("\n".join(lines))


def run():
    args = parse_args()
    graph_str = args.file.read_text()
    graph = TargetGraph.from_str(graph_str)
    os.chdir(args.file.parent)
    if errors := graph.validate():
        for error in errors:
            print(colorize(str(error), color=Color.RED))
        sys.exit(1)
    args.func(graph, args)


if __name__ == "__main__":
    run()
