using Sdt.Core;
using Spectre.Console;

namespace Sdt.Tui;

public sealed class EventsScreen(string projectRoot, string projectName, string version)
{
    private readonly string _projectRoot = projectRoot;
    private readonly string _projectName = projectName;
    private readonly string _version = version;
    private readonly RunEventLogReader _reader = new();

    public void Run()
    {
        while (true)
        {
            AnsiConsole.Clear();
            RenderHeader("EVENTS");
            var files = _reader.ListEventFiles(_projectRoot);
            if (files.Count == 0)
            {
                AnsiConsole.MarkupLine(Theme.Warn("No event logs found yet."));
                AnsiConsole.MarkupLine(Theme.Faint("Run a workflow/debug action first, then return here."));
                AnsiConsole.MarkupLine("\n" + Theme.Faint("Press any key to go back..."));
                Console.ReadKey(intercept: true);
                return;
            }

            var table = new Table()
                .Border(TableBorder.Rounded)
                .BorderStyle(Theme.DimStyle)
                .AddColumn(new TableColumn($"[{Theme.Amber}]File[/]"))
                .AddColumn(new TableColumn($"[{Theme.Amber}]Updated[/]").Width(21))
                .AddColumn(new TableColumn($"[{Theme.Amber}]Size[/]").Width(10));
            foreach (var file in files.Take(12))
            {
                table.AddRow(
                    Theme.G(file.Name),
                    Theme.Faint(file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")),
                    Theme.Faint($"{Math.Max(1, file.SizeBytes / 1024)} KB"));
            }
            AnsiConsole.Write(table);
            AnsiConsole.WriteLine();

            var choices = files
                .Take(20)
                .Select(f => new MenuItem(
                    $"[{Theme.Green}]{Markup.Escape(f.Name)}[/]  [{Theme.GreenDim}]{f.LastWriteTime:yyyy-MM-dd HH:mm:ss}[/]",
                    f.Path))
                .ToList();
            choices.Add(new MenuItem(Theme.Faint("← Back"), "__back__"));

            var selected = AnsiConsole.Prompt(
                new SelectionPrompt<MenuItem>()
                    .Title($"[{Theme.Green}]Select an event log to view:[/]")
                    .PageSize(20)
                    .UseConverter(m => m.Display)
                    .AddChoices(choices));

            if (selected.Value == "__back__")
                return;

            ShowEventFile(selected.Value);
        }
    }

    private void ShowEventFile(string filePath)
    {
        var events = _reader.ReadEvents(filePath);
        AnsiConsole.Clear();
        RenderHeader("EVENTS VIEWER");
        AnsiConsole.MarkupLine(Theme.Faint(Path.GetFileName(filePath)));
        AnsiConsole.MarkupLine(Theme.Faint(filePath));
        AnsiConsole.WriteLine();

        if (events.Count == 0)
        {
            AnsiConsole.MarkupLine(Theme.Warn("No parseable events in selected file."));
            AnsiConsole.MarkupLine("\n" + Theme.Faint("Press any key to return..."));
            Console.ReadKey(intercept: true);
            return;
        }

        var table = new Table()
            .Border(TableBorder.Rounded)
            .BorderStyle(Theme.DimStyle)
            .AddColumn(new TableColumn($"[{Theme.Amber}]Time[/]").Width(12))
            .AddColumn(new TableColumn($"[{Theme.Amber}]Type[/]").Width(26))
            .AddColumn(new TableColumn($"[{Theme.Amber}]Message[/]"))
            .AddColumn(new TableColumn($"[{Theme.Amber}]Status[/]").Width(10));

        foreach (var evt in events.TakeLast(120))
        {
            var status = evt.Success switch
            {
                true => Theme.Ok("ok"),
                false => Theme.Fail("fail"),
                null => Theme.Faint("-"),
            };
            var message = evt.Message;
            if (!string.IsNullOrWhiteSpace(evt.Tool))
                message += $" [{evt.Tool}]";
            if (evt.ExitCode is not null)
                message += $" (exit {evt.ExitCode})";

            table.AddRow(
                Theme.Faint(evt.OccurredAt.ToString("HH:mm:ss")),
                Theme.G(evt.Type.ToString()),
                Theme.Faint(message),
                status);
        }

        AnsiConsole.Write(table);
        AnsiConsole.MarkupLine("\n" + Theme.Faint("Press any key to return..."));
        Console.ReadKey(intercept: true);
    }

    private void RenderHeader(string section)
    {
        AnsiConsole.Write(new FigletText("SDT").Color(Theme.GreenColor));
        AnsiConsole.Write(
            new Rule($"[bold {Theme.GreenBold}]{Markup.Escape(_projectName)}[/]  [{Theme.GreenDim}]v{Markup.Escape(_version)}[/]  [{Theme.Amber}]{Markup.Escape(section)}[/]")
                .RuleStyle(Theme.DimStyle));
        AnsiConsole.MarkupLine(Theme.Faint($"root: {_projectRoot}") + "\n");
    }
}
