using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace JiShe.CollectBus.PluginFileWatcher
{
    /// <summary>
    /// 文件监控相关工具类
    /// </summary>
    public static class FileWatcherUtils
    {
        /// <summary>
        /// 检测文件是否被锁定
        /// </summary>
        /// <param name="filePath">要检查的文件路径</param>
        /// <returns>如果文件被锁定则返回true，否则返回false</returns>
        public static bool IsFileLocked(string filePath)
        {
            if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
                return false;

            try
            {
                using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
                {
                    // 文件可以被完全访问，没有被锁定
                    stream.Close();
                }
                return false;
            }
            catch (IOException)
            {
                // 文件被锁定或正在被其他进程使用
                return true;
            }
            catch (Exception)
            {
                // 其他错误（权限不足、路径无效等）
                return true;
            }
        }

        /// <summary>
        /// 尝试处理一个可能被锁定的文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="action">成功解锁后要执行的操作</param>
        /// <param name="config">健壮性配置</param>
        /// <returns>处理结果：true表示成功处理，false表示处理失败</returns>
        public static async Task<bool> TryHandleLockedFileAsync(string filePath, Func<Task> action, RobustnessConfig config)
        {
            if (!config.EnableFileLockDetection)
            {
                // 如果禁用了锁检测，直接执行操作
                try
                {
                    await action();
                    return true;
                }
                catch
                {
                    return false;
                }
            }

            // 如果文件不存在或不是锁定状态，直接执行操作
            if (!File.Exists(filePath) || !IsFileLocked(filePath))
            {
                try
                {
                    await action();
                    return true;
                }
                catch
                {
                    return false;
                }
            }

            // 文件被锁定，根据策略处理
            switch (config.LockedFileStrategy.ToLower())
            {
                case "skip":
                    // 跳过这个文件
                    Console.WriteLine($"文件被锁定，已跳过: {filePath}");
                    return false;

                case "retry":
                    // 重试几次
                    for (int i = 0; i < config.FileLockRetryCount; i++)
                    {
                        await Task.Delay(config.FileLockRetryDelayMs);
                        
                        if (!IsFileLocked(filePath))
                        {
                            try
                            {
                                await action();
                                Console.WriteLine($"文件锁已释放，成功处理: {filePath}");
                                return true;
                            }
                            catch
                            {
                                // 继续重试
                            }
                        }
                    }
                    Console.WriteLine($"文件仍然被锁定，重试{config.FileLockRetryCount}次后放弃: {filePath}");
                    return false;

                case "log":
                default:
                    // 只记录不处理
                    Console.WriteLine($"文件被锁定，已记录: {filePath}");
                    return false;
            }
        }

        /// <summary>
        /// 检查文件系统监控器是否健康
        /// </summary>
        /// <param name="watcher">要检查的监控器</param>
        /// <param name="lastEventTime">最后一次事件的时间</param>
        /// <param name="config">健壮性配置</param>
        /// <returns>如果监控器健康则返回true，否则返回false</returns>
        public static bool IsWatcherHealthy(FileSystemWatcher watcher, DateTime lastEventTime, RobustnessConfig config)
        {
            if (watcher == null || !watcher.EnableRaisingEvents)
                return false;

            // 如果配置了超时时间，检查是否超时
            if (config.WatcherTimeoutSeconds > 0)
            {
                // 如果最后事件时间超过了超时时间，认为监控器可能已经失效
                TimeSpan timeSinceLastEvent = DateTime.UtcNow - lastEventTime;
                if (timeSinceLastEvent.TotalSeconds > config.WatcherTimeoutSeconds)
                {
                    // 执行一个简单的测试：尝试改变一些属性看是否抛出异常
                    try
                    {
                        var currentFilter = watcher.Filter;
                        watcher.Filter = currentFilter;
                        return true; // 如果没有异常，认为监控器仍然正常
                    }
                    catch
                    {
                        return false; // 抛出异常，认为监控器已经失效
                    }
                }
            }

            // 默认情况下认为监控器健康
            return true;
        }
    }
} 