using System.CommandLine;
using System.CommandLine.Parsing;
using PkmnLib.Dynamic.AI;
using PkmnLib.Dynamic.Libraries;
using PkmnLib.Plugin.Gen7;
using Serilog;
using Serilog.Core;
using Serilog.Events;

namespace AIRunner;

internal static class Program
{
    private static List<PokemonAI>? _availableAIs;

    internal static LoggingLevelSwitch LogLevelSwitch { get; } = new();

    private static Task<int> Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration().MinimumLevel.ControlledBy(LogLevelSwitch).WriteTo.Console()
            .CreateLogger();
        Log.Information("Starting AI Runner...");
        AILogging.LogHandler = Log.Debug;
        var library = DynamicLibraryImpl.Create([
            new Gen7Plugin(),
        ]);
        _availableAIs = PokemonAI.InstantiateAis(library);

        var testCommand = new Command("test", "Run two AIs against each other")
        {
            new Option<bool>("--debug")
            {
                Description = "Enable debug logging.",
            },
            new Option<string>("--ai1")
            {
                Description = "The name of the first AI script to run against the second AI.",
                Required = true,
                Validators = { ValidateAI },
            },
            new Option<string>("--ai2")
            {
                Description = "The name of the second AI script to run against the first AI.",
                Required = true,
                Validators = { ValidateAI },
            },
            new Option<int>("--battles")
            {
                Description = "The number of battles to run between the two AIs.",
                Required = false,
                DefaultValueFactory = _ => 100,
                Validators =
                {
                    result =>
                    {
                        if (result.GetValueOrDefault<int>() <= 0)
                        {
                            result.AddError("--battles must be a positive integer.");
                        }
                    },
                },
            },
        };
        testCommand.SetAction(result =>
        {
            var debug = result.GetValue<bool>("--debug");
            LogLevelSwitch.MinimumLevel = debug ? LogEventLevel.Debug : LogEventLevel.Information;

            var ai1Name = result.GetRequiredValue<string>("--ai1");
            var ai2Name = result.GetRequiredValue<string>("--ai2");
            var ai1 = _availableAIs!.First(a =>
                string.Equals(a.Name, ai1Name, StringComparison.InvariantCultureIgnoreCase));
            var ai2 = _availableAIs!.First(a =>
                string.Equals(a.Name, ai2Name, StringComparison.InvariantCultureIgnoreCase));

            return TestCommandRunner.RunTestCommand(library, ai1, ai2, result.GetRequiredValue<int>("--battles"));
        });

        var rootCommand = new RootCommand("PkmnLib.NET AI Runner")
        {
            testCommand,
        };
        rootCommand.Description = "A tool to run AI scripts against each other in Pokémon battles.";
        var parseResult = rootCommand.Parse(args);
        return parseResult.InvokeAsync();

        static void ValidateAI(OptionResult result)
        {
            var aiName = result.GetValueOrDefault<string>();
            if (string.IsNullOrWhiteSpace(aiName))
            {
                result.AddError("must be a non-empty string.");
                return;
            }

            var ai = _availableAIs!.FirstOrDefault(a => a.Name == aiName);
            if (ai == null)
            {
                result.AddError(
                    $"AI '{aiName}' not found. Available AIs: {string.Join(", ", _availableAIs!.Select(a => a.Name))}");
            }
        }
    }
}