using System.IO;
using System.Text;

namespace AxCopilot.Services.Agent;

/// <summary>
/// Phase 25-C: 도구 결과 크기 제한.
/// CC의 maxResultSizeChars와 동등: 초과 시 임시 파일 저장 + 프리뷰 반환.
/// 컨텍스트 오버플로우를 방지합니다.
/// </summary>
public static class ToolResultSizer
{
    /// <summary>기본 최대 결과 문자 수 (50,000자 ≈ ~12,500 토큰).</summary>
    public const int DefaultMaxChars = 50_000;

    /// <summary>프리뷰에 포함할 머리/꼬리 문자 수.</summary>
    private const int PreviewHeadChars = 2_000;
    private const int PreviewTailChars = 1_000;

    /// <summary>
    /// 도구 결과가 최대 크기를 초과하면 임시 파일에 저장하고 프리뷰를 반환합니다.
    /// </summary>
    /// <param name="output">원본 도구 출력</param>
    /// <param name="toolName">도구 이름 (파일명에 사용)</param>
    /// <param name="maxChars">최대 문자 수</param>
    /// <returns>크기 제한이 적용된 결과. 초과 시 프리뷰 + 파일 경로 안내.</returns>
    public static ToolResultSizeInfo Apply(string output, string toolName, int maxChars = DefaultMaxChars)
    {
        if (string.IsNullOrEmpty(output) || output.Length <= maxChars)
            return new ToolResultSizeInfo { Output = output, WasTruncated = false };

        // 임시 파일에 전체 결과 저장
        var tempDir = Path.Combine(Path.GetTempPath(), "AxCopilot", "tool-results");
        if (!Directory.Exists(tempDir))
            Directory.CreateDirectory(tempDir);

        var fileName = $"{toolName}_{DateTime.Now:yyyyMMdd_HHmmss}_{Guid.NewGuid():N8}.txt";
        var filePath = Path.Combine(tempDir, fileName);

        try
        {
            File.WriteAllText(filePath, output, Encoding.UTF8);
        }
        catch (Exception)
        {
            // 파일 저장 실패 시 단순 트런케이션
            return new ToolResultSizeInfo
            {
                Output = output[..maxChars] + $"\n\n[결과가 {output.Length:#,0}자로 잘렸습니다 (최대 {maxChars:#,0}자)]",
                WasTruncated = true,
            };
        }

        // 프리뷰 생성: 머리 + ... + 꼬리
        var head = output[..PreviewHeadChars];
        var tail = output[^PreviewTailChars..];
        var preview = $"""
            {head}

            ... [{output.Length:#,0}자 중 {output.Length - PreviewHeadChars - PreviewTailChars:#,0}자 생략] ...

            {tail}

            [전체 결과: {filePath}]
            [file_read 도구로 전체 내용을 읽을 수 있습니다]
            """;

        return new ToolResultSizeInfo
        {
            Output = preview,
            WasTruncated = true,
            SpilloverFilePath = filePath,
            OriginalLength = output.Length,
        };
    }

    /// <summary>오래된 임시 결과 파일을 정리합니다 (기본 24시간).</summary>
    public static void CleanupOldResults(TimeSpan? maxAge = null)
    {
        var age = maxAge ?? TimeSpan.FromHours(24);
        var tempDir = Path.Combine(Path.GetTempPath(), "AxCopilot", "tool-results");
        if (!Directory.Exists(tempDir)) return;

        try
        {
            foreach (var file in Directory.GetFiles(tempDir, "*.txt"))
            {
                if (File.GetCreationTimeUtc(file) < DateTime.UtcNow - age)
                {
                    try { File.Delete(file); } catch (Exception) { }
                }
            }
        }
        catch (Exception) { }
    }
}

/// <summary>도구 결과 크기 제한 적용 결과.</summary>
public class ToolResultSizeInfo
{
    public string Output { get; init; } = "";
    public bool WasTruncated { get; init; }
    public string? SpilloverFilePath { get; init; }
    public int OriginalLength { get; init; }
}
