using System.Text.Json;
using AxCopilot.Models;

namespace AxCopilot.Services.Agent;

/// <summary>
/// Phase 17-B: AgentLoopService — TaskState Working Memory + 이벤트 로그 통합.
/// 세션 전반에 걸쳐 구조화된 작업 상태를 유지하고,
/// 컨텍스트 압축(auto-compact) 시에도 핵심 작업 정보를 보존합니다.
/// </summary>
public partial class AgentLoopService
{
    // ── 지연 초기화 (첫 사용 시 생성) ────────────────────────────────────
    private TaskStateService? _taskState;

    /// <summary>현재 세션의 TaskState Working Memory 서비스.</summary>
    private TaskStateService TaskStateManager => _taskState ??= new TaskStateService();

    // ─────────────────────────────────────────────────────────────────────

    /// <summary>
    /// 세션 시작 시 TaskState를 초기화합니다.
    /// 기존 세션 ID 파일이 있으면 로드, 없으면 새로 생성합니다.
    /// </summary>
    internal async Task InitTaskStateAsync(string userQuery, string sessionId)
    {
        if (!_settings.Settings.Llm.EnableTaskState) return;
        try
        {
            await TaskStateManager.InitializeAsync(sessionId);
            if (!string.IsNullOrWhiteSpace(userQuery))
                await TaskStateManager.UpdateCurrentTaskAsync(userQuery);
        }
        catch (Exception ex)
        {
            LogService.Warn($"[TaskState] 초기화 실패: {ex.Message}");
        }
    }

    /// <summary>
    /// 파일 관련 도구 성공 시 반환된 파일 경로를 Working Memory에 추가합니다.
    /// fire-and-forget으로 실행하여 에이전트 루프를 차단하지 않습니다.
    /// </summary>
    internal void TrackToolFile(string? filePath)
    {
        if (!_settings.Settings.Llm.EnableTaskState) return;
        if (string.IsNullOrWhiteSpace(filePath)) return;

        _ = Task.Run(async () =>
        {
            try { await TaskStateManager.AddReferencedFileAsync(filePath); }
            catch (Exception) { /* 추적 실패는 루프에 영향 없음 */ }
        });
    }

    /// <summary>
    /// 컨텍스트 압축 전 TaskState Working Memory를 시스템 메시지에 주입합니다.
    /// 기존 Working Memory 섹션이 있으면 in-place 교체하여 중복 추가를 방지합니다.
    /// </summary>
    internal void InjectTaskStateContext(List<ChatMessage> messages)
    {
        if (!_settings.Settings.Llm.EnableTaskState) return;
        try
        {
            var injection = _taskState?.BuildCompactContextInjection() ?? "";
            if (string.IsNullOrEmpty(injection)) return;

            const string marker = "## 현재 작업 상태 (Working Memory)";
            var sysMsg = messages.FirstOrDefault(m => m.Role == "system");

            if (sysMsg != null)
            {
                var idx = sysMsg.Content.IndexOf(marker, StringComparison.Ordinal);
                if (idx >= 0)
                    // 기존 섹션 교체 (이전 Working Memory를 최신으로 덮어씀)
                    sysMsg.Content = sysMsg.Content[..idx] + injection;
                else
                    // 시스템 메시지 끝에 추가
                    sysMsg.Content += "\n" + injection;
            }
            else
            {
                // 시스템 메시지 자체가 없으면 새로 삽입
                messages.Insert(0, new ChatMessage { Role = "system", Content = injection });
            }
        }
        catch (Exception ex)
        {
            LogService.Warn($"[TaskState] 컨텍스트 주입 실패: {ex.Message}");
        }
    }

    /// <summary>
    /// 컨텍스트 압축 완료 후 TaskState ContextSummary를 비동기 갱신합니다.
    /// fire-and-forget으로 실행하여 루프를 차단하지 않습니다.
    /// </summary>
    internal void UpdateTaskStateSummaryAsync(string summary)
    {
        if (!_settings.Settings.Llm.EnableTaskState) return;
        if (string.IsNullOrWhiteSpace(summary)) return;

        _ = Task.Run(async () =>
        {
            try { await TaskStateManager.UpdateContextSummaryAsync(summary); }
            catch (Exception) { /* 저장 실패는 무시 */ }
        });
    }
}
