using AxCopilot.Models;

namespace AxCopilot.Services.Agent;

/// <summary>
/// Phase 17-A: AgentLoopService — Reflexion(자기성찰 메모리) 통합.
/// 세션 시작 시 과거 교훈을 시스템 메시지에 주입하고,
/// 세션 완료 후 LLM 자기평가를 비동기로 저장합니다.
/// </summary>
public partial class AgentLoopService
{
    // ── 지연 초기화 (첫 사용 시 생성) ────────────────────────────────────
    private ReflexionRepository? _reflexionRepo;
    private ReflexionEvaluatorService? _reflexionEval;

    private ReflexionRepository ReflexionRepo =>
        _reflexionRepo ??= new ReflexionRepository();

    private ReflexionEvaluatorService ReflexionEval =>
        _reflexionEval ??= new ReflexionEvaluatorService(_llm, ReflexionRepo);

    /// <summary>
    /// 세션 시작 시 과거 유사 작업 교훈을 시스템 메시지 끝에 주입합니다.
    /// Reflexion이 비활성화되었거나 교훈이 없으면 아무것도 하지 않습니다.
    /// </summary>
    internal async Task InjectReflexionContextAsync(List<ChatMessage> messages, string userQuery)
    {
        var reflexion = _settings.Settings.Llm.Reflexion;
        if (reflexion?.Enabled != true) return;
        if (string.IsNullOrWhiteSpace(userQuery)) return;

        try
        {
            var taskType = TaskTypeClassifier.Classify(userQuery);
            var maxEntries = reflexion.MaxContextEntries > 0 ? reflexion.MaxContextEntries : 5;
            var context = await ReflexionRepo.BuildContextPromptAsync(taskType, maxEntries);
            if (string.IsNullOrEmpty(context)) return;

            // 시스템 메시지 찾기 (첫 번째 system 역할 메시지)
            var sysMsg = messages.FirstOrDefault(m => m.Role == "system");
            if (sysMsg != null)
                sysMsg.Content += "\n" + context;
            // 시스템 메시지가 없으면 리스트 앞에 추가
            else
                messages.Insert(0, new ChatMessage { Role = "system", Content = context });
        }
        catch (Exception)
        {
            // 교훈 주입 실패는 루프 진행에 영향 없음 (무시)
        }
    }

    /// <summary>
    /// 세션 완료 후 자기평가를 비동기(fire-and-forget)로 실행·저장합니다.
    /// 실패 시 루프에 영향 없음.
    /// </summary>
    internal void FireAndForgetReflexionEval(
        string userQuery,
        string agentResult,
        string sessionId,
        bool isSuccess,
        int toolCallCount,
        int iterationCount)
    {
        var reflexion = _settings.Settings.Llm.Reflexion;
        if (reflexion?.Enabled != true) return;
        if (!isSuccess && reflexion.EvaluateOnSuccess) return; // 성공 시만 평가 설정일 때 실패면 스킵
        if (string.IsNullOrWhiteSpace(userQuery)) return;
        if (toolCallCount == 0) return; // 도구 사용 없는 단순 대화는 평가 불필요

        // CancellationToken 없이 fire-and-forget — 루프 취소에 영향받지 않음
        _ = Task.Run(async () =>
        {
            try
            {
                await ReflexionEval.EvaluateAndSaveAsync(
                    userQuery, agentResult, sessionId,
                    isSuccess, toolCallCount, iterationCount,
                    CancellationToken.None);
            }
            catch (Exception)
            {
                // 평가 저장 실패 — UI 방해 없이 조용히 무시
            }
        });
    }
}
