using System;
using System.Collections.Generic;
using CncModels.Dto;
using CncModels.Dto.Alert;
using CncService;
using CncWebApi.Controllers;
using Xunit;

namespace CncWebApi.Tests
{
    /// <summary>
    /// AlertController单元测试
    /// 告警CRUD + 统计 + 批量处理
    /// </summary>
    [Collection("Database")]
    public class AlertControllerTests
    {
        private readonly AlertController _controller;

        public AlertControllerTests()
        {
            TestDb.TruncateAll();
            // 预置机床（告警外键依赖）
            TestDb.Execute(@"INSERT INTO cnc_collect_address (name, url, brand_id, collect_interval, is_enabled, created_at, updated_at)
                VALUES ('测试地址', 'http://192.168.1.1', 1, 5, 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 ('CNC001', '机床1', 1, 1, '192.168.1.100', 1, 1, NOW(), NOW())");
            _controller = ControllerFactory.CreateAlertController();
        }

        #region 辅助方法

        /// <summary>
        /// 插入一条告警
        /// </summary>
        private int InsertAlert(string type = "offline", string title = "告警测试")
        {
            TestDb.Execute(@"INSERT INTO cnc_alert (machine_id, alert_type, title, is_resolved, created_at)
                VALUES (1, @type, @title, 0, NOW())", new { type, title });
            return TestDb.QuerySingle<int>("SELECT MAX(id) FROM cnc_alert");
        }

        #endregion

        #region GetList - 告警列表

        /// <summary>
        /// 测试：空数据库返回空列表
        /// </summary>
        [Fact]
        public void GetList_EmptyDb_ShouldReturnEmpty()
        {
            var result = _controller.GetList(new AlertQuery());
            var response = ControllerFactory.Extract<PagedResult<AlertListItem>>(result);
            ControllerFactory.AssertSuccess(response);
            Assert.Empty(response.Data.Items);
        }

        /// <summary>
        /// 测试：有告警数据时返回列表
        /// </summary>
        [Fact]
        public void GetList_WithData_ShouldReturnItems()
        {
            InsertAlert();
            var result = _controller.GetList(new AlertQuery());
            var response = ControllerFactory.Extract<PagedResult<AlertListItem>>(result);
            Assert.NotEmpty(response.Data.Items);
        }

        #endregion

        #region GetStatistics - 告警统计

        /// <summary>
        /// 测试：告警统计数据
        /// </summary>
        [Fact]
        public void GetStatistics_ShouldReturnStats()
        {
            InsertAlert();
            var result = _controller.GetStatistics();
            var response = ControllerFactory.Extract<AlertStatisticsResponse>(result);
            ControllerFactory.AssertSuccess(response);
            Assert.NotNull(response.Data);
        }

        #endregion

        #region Resolve - 处理告警

        /// <summary>
        /// 测试：处理单条告警成功
        /// </summary>
        [Fact]
        public void Resolve_Existing_ShouldSuccess()
        {
            int alertId = InsertAlert();
            var result = _controller.Resolve(alertId);
            ControllerFactory.AssertSuccess(ControllerFactory.Extract<object>(result));
            // 验证已处理
            int isResolved = TestDb.QuerySingle<int>("SELECT is_resolved FROM cnc_alert WHERE id = @id", new { id = alertId });
            Assert.Equal(1, isResolved);
        }

        /// <summary>
        /// 测试：处理不存在的告警不抛异常（Service层影响0行）
        /// </summary>
        [Fact]
        public void Resolve_NotExisting_ShouldNotThrow()
        {
            var result = _controller.Resolve(999);
            Assert.NotNull(result);
        }

        #endregion

        #region BatchResolve - 批量处理

        /// <summary>
        /// 测试：批量处理告警成功
        /// </summary>
        [Fact]
        public void BatchResolve_ValidIds_ShouldSuccess()
        {
            int id1 = InsertAlert("offline", "告警1");
            int id2 = InsertAlert("offline", "告警2");

            var result = _controller.BatchResolve(new BatchResolveRequest { Ids = new[] { id1, id2 } });
            var response = ControllerFactory.Extract<object>(result);
            ControllerFactory.AssertSuccess(response);
        }

        /// <summary>
        /// 测试：空ID数组抛出异常
        /// </summary>
        [Fact]
        public void BatchResolve_EmptyIds_ShouldThrow()
        {
            Assert.Throws<BusinessException>(() => _controller.BatchResolve(new BatchResolveRequest { Ids = new int[0] }));
        }

        #endregion
    }
}
