using System.Text.Json;

namespace Sdt.Core;

public sealed record RunEventLogFile(
    string Path,
    string Name,
    DateTimeOffset LastWriteTime,
    long SizeBytes);

public sealed class RunEventLogReader
{
    public IReadOnlyList<RunEventLogFile> ListEventFiles(string projectRoot)
    {
        var eventsRoot = Path.Combine(projectRoot, ".sdt", "events");
        if (!Directory.Exists(eventsRoot))
            return [];

        return Directory.EnumerateFiles(eventsRoot, "*.jsonl", SearchOption.TopDirectoryOnly)
            .Select(path =>
            {
                var info = new FileInfo(path);
                return new RunEventLogFile(
                    Path: path,
                    Name: info.Name,
                    LastWriteTime: info.LastWriteTime,
                    SizeBytes: info.Length);
            })
            .OrderByDescending(f => f.LastWriteTime)
            .ToList();
    }

    public IReadOnlyList<RunEvent> ReadEvents(string filePath)
    {
        var results = new List<RunEvent>();
        if (!File.Exists(filePath))
            return results;

        foreach (var line in File.ReadLines(filePath))
        {
            if (string.IsNullOrWhiteSpace(line))
                continue;

            if (TryParseLine(line, out var evt))
                results.Add(evt!);
        }

        return results;
    }

    internal static bool TryParseLine(string jsonLine, out RunEvent? evt)
    {
        evt = null;
        try
        {
            using var doc = JsonDocument.Parse(jsonLine);
            var root = doc.RootElement;

            var category = root.TryGetProperty("category", out var c) ? c.GetString() : null;
            var typeRaw = root.TryGetProperty("type", out var t) ? t.GetString() : null;
            var message = root.TryGetProperty("message", out var m) ? m.GetString() : null;
            var workflowId = root.TryGetProperty("workflowId", out var wf) ? wf.GetString() : null;
            var stepId = root.TryGetProperty("stepId", out var st) ? st.GetString() : null;
            var tool = root.TryGetProperty("tool", out var tl) ? tl.GetString() : null;
            var success = root.TryGetProperty("success", out var s) && s.ValueKind != JsonValueKind.Null ? s.GetBoolean() : (bool?)null;
            var exitCode = root.TryGetProperty("exitCode", out var ec) && ec.ValueKind != JsonValueKind.Null ? ec.GetInt32() : (int?)null;
            DateTimeOffset? occurred = null;
            if (root.TryGetProperty("occurredAt", out var ts) && ts.ValueKind == JsonValueKind.String &&
                DateTimeOffset.TryParse(ts.GetString(), out var parsed))
            {
                occurred = parsed;
            }

            if (string.IsNullOrWhiteSpace(category) ||
                string.IsNullOrWhiteSpace(typeRaw) ||
                string.IsNullOrWhiteSpace(message) ||
                !Enum.TryParse<RunEventType>(typeRaw, ignoreCase: true, out var type))
            {
                return false;
            }

            evt = new RunEvent(
                Category: category!,
                Type: type,
                Message: message!,
                WorkflowId: workflowId,
                StepId: stepId,
                Tool: tool,
                Success: success,
                ExitCode: exitCode,
                Timestamp: occurred);
            return true;
        }
        catch
        {
            return false;
        }
    }
}
