using System;
using System.Threading;
using Xunit;
using CncCollector.Core;
using CncCollector.Config;
using CncModels.Entity;
using Moq; // 测试项目常用依赖，当前测试未直接使用 Mock，但保留以匹配项目风格

namespace CncCollector.Tests
{
    /// <summary>
    /// CollectWorker 的单元测试集合（针对构造与基本控制流程）。
    /// 使用无效的数据库连接和无效的 HTTP 地址，确保线程启动/停止的行为在异常情况下也能健壮执行。
    /// </summary>
    public class CollectWorkerTests : IDisposable
    {
        private CollectWorker _worker;
        private CollectAddress _address;
        private CollectorConfig _config;

        /// <summary>
        /// 创建一个 CollectWorker 实例，方便各测试用例复用。
        /// 注：为了测试稳定性，数据库连接字符串与 URL 使用无效值。
        /// </summary>
        private void CreateWorker()
        {
            _address = new CollectAddress
            {
                Id = 1,
                Name = "TestAddress",
                Url = "http://invalid.localhost/health", // 无效地址，避免真实网络请求
                BrandId = 1,
                CollectInterval = 1 // 1 秒间隔，便于测试快速循环
            };

            _config = new CollectorConfig();

            // 无效连接字符串，确保不会真正连接到数据库
            string businessConn = "Server=.;Database=NonExistingDb;User Id=invalid;Password=invalid;";
            string logConn = "Server=.;Database=NonExistingLogDb;User Id=invalid;Password=invalid;";

            // 允许 tracker 和 analysisEngine 为 null，因为在无效 URL 的测试路径下通常不会进入需要它们的分支
            _worker = new CollectWorker(_address, _config, null, null, businessConn, logConn);
        }

        public void Dispose()
        {
            if (_worker != null)
            {
                try { _worker.Stop(); } catch { /* 忽略停止时的异常，确保测试清理安全 */ }
            }
        }

        /// <summary>
        /// 构造函数_正常创建_属性正确
        /// 验证 AddressId, AddressName, IsRunning, LastCollectTime, SuccessCount, FailCount
        /// </summary>
        [Fact]
        public void 构造函数_正常创建_属性正确()
        {
            CreateWorker();

            Assert.Equal(1, _worker.AddressId);
            Assert.Equal("TestAddress", _worker.AddressName);
            Assert.False(_worker.IsRunning);
            Assert.Null(_worker.LastCollectTime);
            Assert.Equal(0L, _worker.SuccessCount);
            Assert.Equal(0L, _worker.FailCount);
        }

        /// <summary>
        /// IsRunning_初始值_false
        /// </summary>
        [Fact]
        public void IsRunning_初始值_false()
        {
            CreateWorker();
            Assert.False(_worker.IsRunning);
        }

        /// <summary>
        /// LastCollectTime_初始值_null
        /// </summary>
        [Fact]
        public void LastCollectTime_初始值_null()
        {
            CreateWorker();
            Assert.Null(_worker.LastCollectTime);
        }

        /// <summary>
        /// SuccessCount_初始值_0
        /// </summary>
        [Fact]
        public void SuccessCount_初始值_0()
        {
            CreateWorker();
            Assert.Equal(0L, _worker.SuccessCount);
        }

        /// <summary>
        /// FailCount_初始值_0
        /// </summary>
        [Fact]
        public void FailCount_初始值_0()
        {
            CreateWorker();
            Assert.Equal(0L, _worker.FailCount);
        }

        /// <summary>
        /// Start_调用后_IsRunning变true
        /// 注：Start 会启动后台线程，测试后需要 Stop
        /// </summary>
        [Fact]
        public void Start_调用后_IsRunning变true()
        {
            CreateWorker();
            _worker.Start();

            // 给予一点时间让后台线程启动
            Thread.Sleep(200);

            Assert.True(_worker.IsRunning);

            _worker.Stop();
            Thread.Sleep(100);
            Assert.False(_worker.IsRunning);
        }

        /// <summary>
        /// Stop_调用后_IsRunning变false
        /// </summary>
        [Fact]
        public void Stop_调用后_IsRunning变false()
        {
            CreateWorker();
            _worker.Stop();
            Assert.False(_worker.IsRunning);
        }

        /// <summary>
        /// Start_调用两次_不崩溃
        /// </summary>
        [Fact]
        public void Start_调用两次_不崩溃()
        {
            CreateWorker();
            _worker.Start();
            Thread.Sleep(100);
            // 再次调用 Start，应该不抛出异常
            _worker.Start();
            _worker.Stop();
            Thread.Sleep(100);
            Assert.False(_worker.IsRunning);
        }

        /// <summary>
        /// Stop_未启动就调用_不崩溃
        /// </summary>
        [Fact]
        public void Stop_未启动就调用_不崩溃()
        {
            CreateWorker();
            // 直接停止，未启动状态也应稳定
            _worker.Stop();
            _worker.Stop();
            Assert.False(_worker.IsRunning);
        }
    }
}
