using System.IO;

namespace AxCopilot.Services.Agent;

/// <summary>
/// 파일 시스템 감시 서비스.
/// SessionStart 훅의 watchPaths에 등록된 경로를 모니터링하고
/// 변경 시 FileChanged 이벤트를 발생시킵니다.
/// </summary>
public class FileWatcherService : IDisposable
{
    private readonly List<FileSystemWatcher> _watchers = new();
    private readonly List<Action<string>> _callbacks = new();

    /// <summary>파일 변경 콜백을 등록합니다.</summary>
    public void RegisterCallback(Action<string> onChanged)
        => _callbacks.Add(onChanged);

    /// <summary>glob 패턴 경로를 감시 목록에 추가.</summary>
    public void Watch(string pattern, Action<string> onChanged)
    {
        try
        {
            // 패턴에서 디렉토리와 파일 패턴 분리
            var (dir, filePattern) = SplitPattern(pattern);
            if (!Directory.Exists(dir)) return;

            var watcher = new FileSystemWatcher(dir)
            {
                Filter = filePattern.Replace("**", "*"),
                IncludeSubdirectories = pattern.Contains("**"),
                NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName,
                EnableRaisingEvents = true
            };

            void Handler(object _, FileSystemEventArgs e)
            {
                try { onChanged(e.FullPath); }
                catch (Exception) { }
            }

            watcher.Changed += Handler;
            watcher.Created += Handler;
            _watchers.Add(watcher);
        }
        catch (Exception) { }
    }

    /// <summary>모든 등록된 감시 경로 제거.</summary>
    public void ClearAll()
    {
        foreach (var w in _watchers) { w.EnableRaisingEvents = false; w.Dispose(); }
        _watchers.Clear();
    }

    private static (string dir, string pattern) SplitPattern(string glob)
    {
        var parts = glob.Replace('/', '\\').Split('\\');
        var dirParts = parts.TakeWhile(p => !p.Contains('*')).ToArray();
        var patternParts = parts.SkipWhile(p => !p.Contains('*')).ToArray();

        var dir = dirParts.Length > 0 ? string.Join('\\', dirParts) : ".";
        if (!Path.IsPathRooted(dir)) dir = Path.GetFullPath(dir);
        var pattern = patternParts.Length > 0 ? string.Join('\\', patternParts) : "*";

        return (dir, pattern);
    }

    public void Dispose()
    {
        ClearAll();
    }
}
