using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace AxCopilot.Services.Agent;

/// <summary>
/// Phase 17-E: AX.md 및 .ax/rules/*.md의 @파일경로 지시어를 재귀 해석.
/// 최대 5단계 깊이, 순환 참조 감지.
/// </summary>
public class AxMdIncludeResolver
{
    private const int MaxDepth = 5;
    public const long OversizeWarningChars = 40_000;

    private static readonly Regex _includePattern =
        new(@"^@(.+)$", RegexOptions.Multiline | RegexOptions.Compiled);

    /// <summary>@파일경로 지시어를 재귀 해석하여 최종 텍스트 반환.</summary>
    public async Task<string> ResolveAsync(
        string content,
        string basePath,
        int depth = 0,
        HashSet<string>? visited = null)
    {
        if (depth >= MaxDepth) return content;
        visited ??= new HashSet<string>(StringComparer.OrdinalIgnoreCase);

        var lines = content.Split('\n');
        var result = new StringBuilder();

        foreach (var line in lines)
        {
            var trimmed = line.TrimEnd('\r');
            var match = _includePattern.Match(trimmed);

            if (match.Success)
            {
                var includePath = match.Groups[1].Value.Trim();
                var fullPath = Path.IsPathRooted(includePath)
                    ? includePath
                    : Path.GetFullPath(Path.Combine(basePath, includePath));

                if (visited.Contains(fullPath))
                {
                    result.AppendLine($"<!-- @include 순환 참조 무시: {includePath} -->");
                    continue;
                }

                if (!File.Exists(fullPath))
                {
                    result.AppendLine($"<!-- @include 파일 없음: {includePath} -->");
                    continue;
                }

                visited.Add(fullPath);
                var includedContent = await File.ReadAllTextAsync(fullPath, Encoding.UTF8);

                // 재귀 해석
                var resolved = await ResolveAsync(
                    includedContent,
                    Path.GetDirectoryName(fullPath) ?? basePath,
                    depth + 1,
                    visited);

                result.AppendLine(resolved);
                visited.Remove(fullPath); // 병렬 포함 지원을 위해 방문 후 제거
            }
            else
            {
                result.AppendLine(trimmed);
            }
        }

        return result.ToString();
    }

    /// <summary>파일이 40,000자 임계값을 초과하는지 확인.</summary>
    public static bool IsOversized(string content) => content.Length > OversizeWarningChars;
}
