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

namespace CncWebApi.Tests
{
    /// <summary>
    /// BrandController单元测试
    /// 品牌CRUD + 复制 + 启停 + 标准字段
    /// </summary>
    [Collection("Database")]
    public class BrandControllerTests
    {
        private readonly BrandController _controller;

        public BrandControllerTests()
        {
            TestDb.TruncateAll();
            _controller = ControllerFactory.CreateBrandController();
        }

        #region GetList - 品牌列表

        /// <summary>
        /// 测试：获取品牌列表，种子数据包含FANUC
        /// </summary>
        [Fact]
        public void GetList_ShouldReturnBrandList()
        {
            // Act
            var result = _controller.GetList();

            // Assert
            var response = ControllerFactory.Extract<List<BrandListItem>>(result);
            ControllerFactory.AssertSuccess(response);
            Assert.NotNull(response.Data);
            Assert.Single(response.Data); // 种子数据只有FANUC
            Assert.Equal("FANUC", response.Data[0].BrandName);
        }

        /// <summary>
        /// 测试：新增品牌后列表数量增加
        /// </summary>
        [Fact]
        public void GetList_AfterCreate_ShouldHaveTwoBrands()
        {
            // Arrange - 新增一个品牌
            _controller.Create(new CreateBrandRequest
            {
                BrandName = "Siemens",
                DeviceField = "device",
                TagsPath = "tags"
            });

            // Act
            var result = _controller.GetList();

            // Assert
            var response = ControllerFactory.Extract<List<BrandListItem>>(result);
            Assert.Equal(2, response.Data.Count);
        }

        #endregion

        #region GetById - 品牌详情

        /// <summary>
        /// 测试：获取FANUC品牌详情
        /// </summary>
        [Fact]
        public void GetById_ExistingBrand_ShouldReturnDetail()
        {
            // Act
            var result = _controller.GetById(1);

            // Assert
            var response = ControllerFactory.Extract<BrandDetailResponse>(result);
            ControllerFactory.AssertSuccess(response);
            Assert.NotNull(response.Data);
            Assert.Equal("FANUC", response.Data.BrandName);
            Assert.NotNull(response.Data.Mappings);
        }

        /// <summary>
        /// 测试：获取不存在的品牌抛出异常
        /// </summary>
        [Fact]
        public void GetById_NotExisting_ShouldThrowBusinessException()
        {
            // Act & Assert
            var ex = Assert.Throws<BusinessException>(() => _controller.GetById(999));
            Assert.Equal("品牌不存在", ex.Message);
        }

        #endregion

        #region Create - 新增品牌

        /// <summary>
        /// 测试：新增品牌成功
        /// </summary>
        [Fact]
        public void Create_ValidRequest_ShouldReturnNewId()
        {
            // Arrange
            var request = new CreateBrandRequest
            {
                BrandName = "Mitsubishi",
                DeviceField = "device",
                TagsPath = "tags"
            };

            // Act
            var result = _controller.Create(request);

            // Assert
            var response = ControllerFactory.Extract<object>(result);
            ControllerFactory.AssertSuccess(response);
            Assert.NotNull(response.Data);
        }

        /// <summary>
        /// 测试：新增重复品牌名抛出异常
        /// </summary>
        [Fact]
        public void Create_DuplicateName_ShouldThrowBusinessException()
        {
            // Arrange - FANUC已存在于种子数据
            var request = new CreateBrandRequest
            {
                BrandName = "FANUC",
                DeviceField = "device",
                TagsPath = "tags"
            };

            // Act & Assert
            var ex = Assert.Throws<BusinessException>(() => _controller.Create(request));
            Assert.Equal("品牌名称已存在", ex.Message);
        }

        #endregion

        #region Update - 编辑品牌

        /// <summary>
        /// 测试：编辑品牌名称成功
        /// </summary>
        [Fact]
        public void Update_ValidRequest_ShouldSuccess()
        {
            // Arrange
            var request = new UpdateBrandRequest
            {
                BrandName = "FANUC-Updated",
                DeviceField = "device",
                TagsPath = "tags"
            };

            // Act
            var result = _controller.Update(1, request);

            // Assert
            var response = ControllerFactory.Extract<object>(result);
            ControllerFactory.AssertSuccess(response);

            // 验证修改后名称
            var detail = ControllerFactory.Extract<BrandDetailResponse>(_controller.GetById(1));
            Assert.Equal("FANUC-Updated", detail.Data.BrandName);
        }

        /// <summary>
        /// 测试：编辑不存在的品牌抛出异常
        /// </summary>
        [Fact]
        public void Update_NotExisting_ShouldThrowBusinessException()
        {
            var request = new UpdateBrandRequest { BrandName = "Test", DeviceField = "d", TagsPath = "t" };
            Assert.Throws<BusinessException>(() => _controller.Update(999, request));
        }

        #endregion

        #region Delete - 删除品牌

        /// <summary>
        /// 测试：删除品牌成功
        /// </summary>
        [Fact]
        public void Delete_ExistingBrand_ShouldSuccess()
        {
            // 先新增一个品牌（避免删除种子FANUC）
            var createResult = _controller.Create(new CreateBrandRequest
            {
                BrandName = "ToDelete",
                DeviceField = "d",
                TagsPath = "t"
            });
            // 获取新品牌ID
            int newId = TestDb.QuerySingle<int>("SELECT MAX(id) FROM cnc_brand");

            // Act
            var result = _controller.Delete(newId);

            // Assert
            ControllerFactory.AssertSuccess(ControllerFactory.Extract<object>(result));
            // 删除后列表只剩FANUC
            var list = ControllerFactory.Extract<List<BrandListItem>>(_controller.GetList());
            Assert.Single(list.Data);
        }

        /// <summary>
        /// 测试：删除不存在的品牌抛出异常
        /// </summary>
        [Fact]
        public void Delete_NotExisting_ShouldThrowBusinessException()
        {
            Assert.Throws<BusinessException>(() => _controller.Delete(999));
        }

        #endregion

        #region Copy - 复制品牌

        /// <summary>
        /// 测试：复制FANUC品牌成功
        /// </summary>
        [Fact]
        public void Copy_ExistingBrand_ShouldReturnNewId()
        {
            // Act
            var result = _controller.Copy(1);

            // Assert
            var response = ControllerFactory.Extract<object>(result);
            ControllerFactory.AssertSuccess(response);
            // 列表应有两项
            var list = ControllerFactory.Extract<List<BrandListItem>>(_controller.GetList());
            Assert.Equal(2, list.Data.Count);
        }

        /// <summary>
        /// 测试：复制不存在的品牌抛出异常
        /// </summary>
        [Fact]
        public void Copy_NotExisting_ShouldThrowBusinessException()
        {
            Assert.Throws<BusinessException>(() => _controller.Copy(999));
        }

        #endregion

        #region ToggleEnabled - 启停品牌

        /// <summary>
        /// 测试：切换品牌启用状态成功
        /// </summary>
        [Fact]
        public void ToggleEnabled_ExistingBrand_ShouldSuccess()
        {
            // Act
            var result = _controller.ToggleEnabled(1);

            // Assert
            ControllerFactory.AssertSuccess(ControllerFactory.Extract<object>(result));
        }

        /// <summary>
        /// 测试：切换不存在的品牌不会抛异常（Service层不检查存在性，返回0行受影响）
        /// </summary>
        [Fact]
        public void ToggleEnabled_NotExisting_ShouldNotThrow()
        {
            // 不存在的ID，Service层执行UPDATE但影响0行，不抛异常
            var result = _controller.ToggleEnabled(999);
            Assert.NotNull(result);
        }

        #endregion

        // region FieldMapping IsEnabled - 字段映射启用开关
        #region FieldMapping IsEnabled - 字段映射启用开关

        /// <summary>
        /// 测试：获取品牌详情时映射响应包含IsEnabled
        /// </summary>
        [Fact]
        public void GetById_映射响应包含IsEnabled()
        {
            // 插入字段映射
            TestDb.Execute(@"INSERT INTO cnc_brand_field_mapping (brand_id, standard_field, field_name, match_by, data_type, is_required, is_enabled, created_at)
                VALUES (1, 'program_name', 'Tag5', 'id', 'string', 1, 1, NOW()),
                       (1, 'spindle_load', 'Tag21', 'id', 'number', 0, 0, NOW())");
            var result = _controller.GetById(1);
            var response = ControllerFactory.Extract<BrandDetailResponse>(result);
            ControllerFactory.AssertSuccess(response);
            Assert.Equal(2, response.Data.Mappings.Count);
            var disabled = response.Data.Mappings.First(m => m.StandardField == "spindle_load");
            Assert.Equal(0, disabled.IsEnabled);
        }

        /// <summary>
        /// 测试：复制品牌后映射启用状态一致
        /// </summary>
        [Fact]
        public void Copy_复制后映射启用状态一致()
        {
            TestDb.Execute(@"INSERT INTO cnc_brand_field_mapping (brand_id, standard_field, field_name, match_by, data_type, is_required, is_enabled, created_at)
                VALUES (1, 'program_name', 'Tag5', 'id', 'string', 1, 1, NOW()),
                       (1, 'spindle_load', 'Tag21', 'id', 'number', 0, 0, NOW())");
            var copyResult = _controller.Copy(1);
            var copyResponse = ControllerFactory.Extract<object>(copyResult);
            ControllerFactory.AssertSuccess(copyResponse);
            int newId = TestDb.QuerySingle<int>("SELECT MAX(id) FROM cnc_brand WHERE id <> 1");
            var detail = ControllerFactory.Extract<BrandDetailResponse>(_controller.GetById(newId));
            Assert.Equal(2, detail.Data.Mappings.Count);
            var enabledMapping = detail.Data.Mappings.First(m => m.StandardField == "program_name");
            var disabledMapping = detail.Data.Mappings.First(m => m.StandardField == "spindle_load");
            Assert.Equal(1, enabledMapping.IsEnabled);
            Assert.Equal(0, disabledMapping.IsEnabled);
        }

        #endregion
        #region GetStandardFields - 标准字段列表

        /// <summary>
        /// 测试：获取标准字段列表返回非空
        /// </summary>
        [Fact]
        public void GetStandardFields_ShouldReturnFields()
        {
            // Act
            var result = _controller.GetStandardFields();

            // Assert
            var response = ControllerFactory.Extract<List<StandardFieldResponse>>(result);
            ControllerFactory.AssertSuccess(response);
            Assert.NotNull(response.Data);
        }

        #endregion
    }
}
