using System;
using System.Collections.Generic;
using CncModels.Constants;
using CncModels.Dto;
using CncModels.Dto.Alert;
using CncService;
using CncService.Impl;
using Xunit;

namespace CncService.Tests
{
    /// <summary>
    /// AlertService 告警管理测试
    /// 测试场景：查询、解决告警、批量解决、统计、参数校验
    /// </summary>
    [Collection("Database")]
    public class AlertServiceTests : IDisposable
    {
        private readonly AlertService _service;

        public AlertServiceTests()
        {
            TestDb.TruncateAll();
            _service = ServiceFactory.CreateAlertService();
        }

        public void Dispose()
        {
            TestDb.TruncateAll();
        }

        /// <summary>辅助方法：插入测试告警（每次用唯一编码避免重复）</summary>
        private long InsertTestAlert(string alertType = "offline", int isResolved = 0)
        {
            // 只插入一次机床
            var machineCount = TestDb.QuerySingle<int>("SELECT COUNT(*) FROM cnc_machine");
            if (machineCount == 0)
            {
                TestDb.Execute(@"INSERT INTO cnc_collect_address (name, url, brand_id, collect_interval, is_enabled, created_at, updated_at)
                    VALUES ('测试地址', 'http://test', 1, 30, 1, NOW(), NOW())");
                TestDb.Execute(@"INSERT INTO cnc_machine (device_code, name, workshop_id, collect_address_id, ip_address, brand_id, is_enabled, created_at, updated_at)
                    VALUES ('M001', '机床1', 1, 1, '0.0.0.0', 1, 1, NOW(), NOW())");
            }
            TestDb.Execute(@"INSERT INTO cnc_alert (alert_type, machine_id, title, is_resolved, created_at)
                VALUES (@alertType, 1, '测试告警', @isResolved, NOW())",
                new { alertType, isResolved });
            return TestDb.QuerySingle<long>("SELECT MAX(id) FROM cnc_alert");
        }

        // ======== GetList ========

        [Fact]
        public void GetList_无数据_返回空列表()
        {
            var result = _service.GetList(new AlertQuery { Page = 1, PageSize = 20 });
            Assert.NotNull(result);
            Assert.Equal(0, result.Total);
        }

        [Fact]
        public void GetList_查询参数为null_抛出BadRequest异常()
        {
            var ex = Assert.Throws<BusinessException>(() => _service.GetList(null));
            Assert.Equal(ErrorCode.BadRequest, ex.Code);
        }

        [Fact]
        public void GetList_有告警数据_返回分页结果()
        {
            InsertTestAlert();
            InsertTestAlert("overload");

            var result = _service.GetList(new AlertQuery { Page = 1, PageSize = 20 });
            Assert.Equal(2, result.Total);
        }

        // ======== Resolve ========

        [Fact]
        public void Resolve_存在的ID_返回true()
        {
            var id = InsertTestAlert();
            var result = _service.Resolve(id);
            Assert.True(result);
        }

        [Fact]
        public void Resolve_无效ID_抛出BadRequest异常()
        {
            var ex = Assert.Throws<BusinessException>(() => _service.Resolve(0));
            Assert.Equal(ErrorCode.BadRequest, ex.Code);
        }

        [Fact]
        public void Resolve_负数ID_抛出BadRequest异常()
        {
            var ex = Assert.Throws<BusinessException>(() => _service.Resolve(-1));
            Assert.Equal(ErrorCode.BadRequest, ex.Code);
        }

        // ======== BatchResolve ========

        [Fact]
        public void BatchResolve_正常批量解决_返回成功数量()
        {
            var id1 = InsertTestAlert();
            var id2 = InsertTestAlert("overload");

            var count = _service.BatchResolve(new List<long> { id1, id2 });
            Assert.Equal(2, count);
        }

        [Fact]
        public void BatchResolve_列表为null_抛出BadRequest异常()
        {
            var ex = Assert.Throws<BusinessException>(() => _service.BatchResolve(null));
            Assert.Equal(ErrorCode.BadRequest, ex.Code);
        }

        [Fact]
        public void BatchResolve_空列表_抛出BadRequest异常()
        {
            var ex = Assert.Throws<BusinessException>(() => _service.BatchResolve(new List<long>()));
            Assert.Equal(ErrorCode.BadRequest, ex.Code);
        }

        // ======== GetStatistics ========

        [Fact]
        public void GetStatistics_无数据_返回全0()
        {
            var stats = _service.GetStatistics();
            Assert.NotNull(stats);
            Assert.Equal(0, stats.UnresolvedCount);
            Assert.NotNull(stats.UnresolvedByType);
        }

        [Fact]
        public void GetStatistics_有数据_返回正确统计()
        {
            InsertTestAlert("offline", 0);
            InsertTestAlert("overload", 0);
            InsertTestAlert("offline", 1); // 已解决

            var stats = _service.GetStatistics();
            Assert.True(stats.UnresolvedCount >= 2);
        }
    }
}
