using System.IO;
using System.Text.Json;

namespace AxCopilot.Services.Agent;

/// <summary>
/// Phase 18-B: 에이전트 세션 이벤트 로그를 읽어 재생(replay)을 지원합니다.
/// AgentEventLog의 JSONL 파일을 순서대로 읽어 UI에 이벤트 스트림을 전달합니다.
/// </summary>
public class AgentReplayService
{
    private readonly string _sessionsDir;

    public AgentReplayService()
    {
        _sessionsDir = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
            "AxCopilot", "sessions");
    }

    /// <summary>저장된 세션 목록 반환 (최신순).</summary>
    public IReadOnlyList<ReplaySessionInfo> GetSessions()
    {
        if (!Directory.Exists(_sessionsDir)) return new List<ReplaySessionInfo>();

        var sessions = new List<ReplaySessionInfo>();
        foreach (var dir in Directory.GetDirectories(_sessionsDir))
        {
            var logFile = Path.Combine(dir, "events.jsonl");
            if (!File.Exists(logFile)) continue;

            var sessionId = Path.GetFileName(dir);
            var info = new FileInfo(logFile);
            sessions.Add(new ReplaySessionInfo
            {
                SessionId = sessionId,
                LogFilePath = logFile,
                CreatedAt = info.CreationTime,
                FileSizeBytes = info.Length
            });
        }

        return sessions.OrderByDescending(s => s.CreatedAt).ToList();
    }

    /// <summary>
    /// 세션 이벤트를 순서대로 재생합니다.
    /// 각 이벤트마다 onEvent 콜백을 호출하고, delayMs 간격으로 재생.
    /// </summary>
    public async Task ReplayAsync(
        string sessionId,
        Func<AgentEventRecord, Task> onEvent,
        int delayMs = 300,
        CancellationToken ct = default)
    {
        var logFile = Path.Combine(_sessionsDir, sessionId, "events.jsonl");
        if (!File.Exists(logFile)) return;

        var log = new AgentEventLog(sessionId);
        await foreach (var record in log.ReadAllAsync(ct))
        {
            if (ct.IsCancellationRequested) break;
            await onEvent(record);
            if (delayMs > 0)
                await Task.Delay(delayMs, ct);
        }
    }

    /// <summary>세션의 모든 이벤트를 한 번에 로드합니다 (타임라인 뷰용).</summary>
    public async Task<IReadOnlyList<AgentEventRecord>> LoadAllEventsAsync(
        string sessionId,
        CancellationToken ct = default)
    {
        var logFile = Path.Combine(_sessionsDir, sessionId, "events.jsonl");
        if (!File.Exists(logFile)) return new List<AgentEventRecord>();

        var records = new List<AgentEventRecord>();
        var log = new AgentEventLog(sessionId);
        await foreach (var record in log.ReadAllAsync(ct))
        {
            if (ct.IsCancellationRequested) break;
            records.Add(record);
        }
        return records;
    }

    /// <summary>오래된 세션 정리 (AgentEventLog 위임).</summary>
    public void CleanOldSessions(int retentionDays = 30)
        => AgentEventLog.CleanOldSessions(retentionDays);
}

/// <summary>재생 가능한 세션 정보.</summary>
public record ReplaySessionInfo
{
    public string SessionId { get; init; } = "";
    public string LogFilePath { get; init; } = "";
    public DateTime CreatedAt { get; init; }
    public long FileSizeBytes { get; init; }

    public string DisplayName => $"세션 {SessionId} ({CreatedAt:MM-dd HH:mm})";
    public string FileSizeLabel => FileSizeBytes < 1024
        ? $"{FileSizeBytes}B"
        : $"{FileSizeBytes / 1024}KB";
}
