using System.Collections.Concurrent;
using System.IO;

namespace AxCopilot.Services.Agent;

public enum BackgroundAgentStatus { Pending, Running, Completed, Failed }

public class BackgroundAgentTask
{
    public string Id { get; init; } = "";
    public string AgentType { get; init; } = "";
    public string Description { get; init; } = "";
    public string Context { get; init; } = "";
    public string WorkingDirectory { get; init; } = "";
    public BackgroundAgentStatus Status { get; set; } = BackgroundAgentStatus.Pending;
    public string? Result { get; set; }
    public string? Error { get; set; }
    public DateTime StartedAt { get; init; } = DateTime.UtcNow;
    public DateTime? CompletedAt { get; set; }
}

public class AgentCompletedEventArgs : EventArgs
{
    public BackgroundAgentTask Task { get; init; } = null!;
    public string? Result { get; init; }
    public string? Error { get; init; }
}

/// <summary>
/// Phase 18-A: 비동기 서브에이전트 실행 + 완료 알림.
/// 완료 시 AgentCompleted 이벤트 발화 → 트레이 알림 연결.
/// </summary>
public class BackgroundAgentService
{
    private const int MaxResultLength = 100_000;
    private readonly ConcurrentDictionary<string, BackgroundAgentTask> _running = new();
    private readonly AgentTypeMemoryRepository _memoryRepo;

    /// <summary>에이전트 완료 시 발화. UI 스레드에서 처리 주의.</summary>
    public event EventHandler<AgentCompletedEventArgs>? AgentCompleted;

    public BackgroundAgentService(AgentTypeMemoryRepository memoryRepo)
    {
        _memoryRepo = memoryRepo;
    }

    /// <summary>백그라운드 에이전트 작업 시작. 즉시 반환, 완료 시 AgentCompleted 이벤트.</summary>
    public string Start(
        string agentType,
        string description,
        string context,
        string workingDirectory,
        Func<string, string, string, CancellationToken, Task<string>> agentRunner,
        CancellationToken ct = default)
    {
        var id = Guid.NewGuid().ToString("N")[..8];
        var task = new BackgroundAgentTask
        {
            Id = id,
            AgentType = agentType,
            Description = description,
            Context = context,
            WorkingDirectory = workingDirectory,
            Status = BackgroundAgentStatus.Pending,
        };
        _running[id] = task;

        _ = Task.Run(async () =>
        {
            task.Status = BackgroundAgentStatus.Running;
            try
            {
                // 에이전트 타입별 메모리 로드
                var memory = await _memoryRepo.LoadMemoryAsync(agentType);
                var fullContext = string.IsNullOrEmpty(memory)
                    ? context
                    : context + $"\n\n## 이전 학습:\n{memory}";

                var result = await agentRunner(agentType, description, fullContext, ct);

                // 결과 크기 제한
                if (result.Length > MaxResultLength)
                    result = result[..MaxResultLength] + "\n\n[결과가 100,000자를 초과하여 잘림]";

                task.Result = result;
                task.Status = BackgroundAgentStatus.Completed;
                task.CompletedAt = DateTime.UtcNow;

                AgentCompleted?.Invoke(this, new AgentCompletedEventArgs
                {
                    Task = task, Result = result
                });
            }
            catch (Exception ex)
            {
                task.Status = BackgroundAgentStatus.Failed;
                task.Error = ex.Message;
                task.CompletedAt = DateTime.UtcNow;

                AgentCompleted?.Invoke(this, new AgentCompletedEventArgs
                {
                    Task = task, Error = ex.Message
                });
            }
            finally { _running.TryRemove(id, out _); }
        }, ct);

        return id;
    }

    /// <summary>현재 실행 중인 에이전트 목록.</summary>
    public IReadOnlyList<BackgroundAgentTask> GetActive()
        => _running.Values.ToList();

    /// <summary>에이전트 ID로 상태 확인.</summary>
    public BackgroundAgentTask? GetById(string id)
        => _running.TryGetValue(id, out var t) ? t : null;
}
