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

namespace CncWebApi.Tests
{
    /// <summary>
    /// SettingsController单元测试
    /// 系统配置CRUD + 车间管理CRUD + 修改密码
    /// </summary>
    [Collection("Database")]
    public class SettingsControllerTests
    {
        private readonly SettingsController _controller;

        public SettingsControllerTests()
        {
            TestDb.TruncateAll();
            _controller = ControllerFactory.CreateSettingsController();
        }

        #region 系统配置

        #region GetSysConfigList - 配置列表

        /// <summary>
        /// 测试：获取系统配置列表，种子数据有admin_username和admin_password_hash
        /// </summary>
        [Fact]
        public void GetSysConfigList_ShouldReturnConfigs()
        {
            var result = _controller.GetSysConfigList();
            var response = ControllerFactory.Extract<List<SysConfigListItem>>(result);
            ControllerFactory.AssertSuccess(response);
            Assert.NotNull(response.Data);
            Assert.True(response.Data.Count >= 2); // 至少有username和password_hash
        }

        #endregion

        #region UpdateSysConfig - 编辑配置

        /// <summary>
        /// 测试：更新配置值成功
        /// </summary>
        [Fact]
        public void UpdateSysConfig_ValidRequest_ShouldSuccess()
        {
            // 获取第一个配置ID
            var list = ControllerFactory.Extract<List<SysConfigListItem>>(_controller.GetSysConfigList());
            int configId = list.Data[0].Id;

            var result = _controller.UpdateSysConfig(configId, new UpdateSysConfigRequest { ConfigValue = "new_value" });
            ControllerFactory.AssertSuccess(ControllerFactory.Extract<object>(result));
        }

        /// <summary>
        /// 测试：请求为null时抛出异常
        /// </summary>
        [Fact]
        public void UpdateSysConfig_NullRequest_ShouldThrow()
        {
            var ex = Assert.Throws<BusinessException>(() => _controller.UpdateSysConfig(1, null));
            Assert.Equal(ErrorCode.BadRequest, ex.Code);
        }

        #endregion

        #region ChangePassword - 修改密码

        /// <summary>
        /// 测试：修改密码成功
        /// </summary>
        [Fact]
        public void ChangePassword_ValidRequest_ShouldSuccess()
        {
            // 设置真实密码哈希
            TestDb.SetRealPasswordHash("old_password");

            var result = _controller.ChangePassword(new ChangePasswordRequest
            {
                OldPassword = "old_password",
                NewPassword = "new_password123"
            });

            ControllerFactory.AssertSuccess(ControllerFactory.Extract<object>(result));
            // 验证密码哈希已更新
            var newHash = TestDb.QuerySingle<string>("SELECT config_value FROM cnc_sys_config WHERE config_key = 'admin_password_hash'");
            Assert.True(BCrypt.Net.BCrypt.Verify("new_password123", newHash));
        }

        /// <summary>
        /// 测试：请求为null时抛出异常
        /// </summary>
        [Fact]
        public void ChangePassword_NullRequest_ShouldThrow()
        {
            Assert.Throws<BusinessException>(() => _controller.ChangePassword(null));
        }

        #endregion

        #endregion

        #region 车间管理

        #region GetWorkshopList - 车间列表

        /// <summary>
        /// 测试：车间列表返回种子数据（A栋、B栋）
        /// </summary>
        [Fact]
        public void GetWorkshopList_ShouldReturnSeedData()
        {
            var result = _controller.GetWorkshopList(null);
            var response = ControllerFactory.Extract<List<WorkshopListItem>>(result);
            ControllerFactory.AssertSuccess(response);
            Assert.Equal(2, response.Data.Count); // A栋、B栋
        }

        /// <summary>
        /// 测试：关键字搜索车间
        /// </summary>
        [Fact]
        public void GetWorkshopList_WithKeyword_ShouldFilter()
        {
            var result = _controller.GetWorkshopList("A");
            var response = ControllerFactory.Extract<List<WorkshopListItem>>(result);
            Assert.Single(response.Data);
            Assert.Equal("A栋", response.Data[0].Name);
        }

        #endregion

        #region CreateWorkshop - 新增车间

        /// <summary>
        /// 测试：新增车间成功
        /// </summary>
        [Fact]
        public void CreateWorkshop_ValidRequest_ShouldReturnId()
        {
            var result = _controller.CreateWorkshop(new CreateWorkshopRequest { Name = "C栋", SortOrder = 3 });
            var response = ControllerFactory.Extract<object>(result);
            ControllerFactory.AssertSuccess(response);
        }

        /// <summary>
        /// 测试：重复车间名抛出异常
        /// </summary>
        [Fact]
        public void CreateWorkshop_DuplicateName_ShouldThrow()
        {
            Assert.Throws<BusinessException>(() =>
                _controller.CreateWorkshop(new CreateWorkshopRequest { Name = "A栋", SortOrder = 1 }));
        }

        #endregion

        #region UpdateWorkshop - 编辑车间

        /// <summary>
        /// 测试：编辑车间名称
        /// </summary>
        [Fact]
        public void UpdateWorkshop_ValidRequest_ShouldSuccess()
        {
            var result = _controller.UpdateWorkshop(1, new UpdateWorkshopRequest { Name = "A栋改名", SortOrder = 1 });
            ControllerFactory.AssertSuccess(ControllerFactory.Extract<object>(result));

            var list = ControllerFactory.Extract<List<WorkshopListItem>>(_controller.GetWorkshopList(null));
            Assert.Contains(list.Data, w => w.Name == "A栋改名");
        }

        /// <summary>
        /// 测试：编辑不存在的车间抛出异常
        /// </summary>
        [Fact]
        public void UpdateWorkshop_NotExisting_ShouldThrow()
        {
            Assert.Throws<BusinessException>(() =>
                _controller.UpdateWorkshop(999, new UpdateWorkshopRequest { Name = "测试", SortOrder = 1 }));
        }

        #endregion

        #region DeleteWorkshop - 删除车间

        /// <summary>
        /// 测试：删除车间成功
        /// </summary>
        [Fact]
        public void DeleteWorkshop_Existing_ShouldSuccess()
        {
            // 新增一个车间来删除
            _controller.CreateWorkshop(new CreateWorkshopRequest { Name = "删除用", SortOrder = 99 });
            int id = TestDb.QuerySingle<int>("SELECT MAX(id) FROM cnc_workshop");

            var result = _controller.DeleteWorkshop(id);
            ControllerFactory.AssertSuccess(ControllerFactory.Extract<object>(result));
        }

        /// <summary>
        /// 测试：删除不存在的车间不抛异常（Service层影响0行）
        /// </summary>
        [Fact]
        public void DeleteWorkshop_NotExisting_ShouldNotThrow()
        {
            var result = _controller.DeleteWorkshop(999);
            Assert.NotNull(result);
        }

        #endregion

        #region ToggleWorkshop - 启停车间

        /// <summary>
        /// 测试：切换车间启用状态
        /// </summary>
        [Fact]
        public void ToggleWorkshop_ShouldSuccess()
        {
            var result = _controller.ToggleWorkshop(1);
            ControllerFactory.AssertSuccess(ControllerFactory.Extract<object>(result));
        }

        /// <summary>
        /// 测试：切换不存在的车间不抛异常（Service层影响0行）
        /// </summary>
        [Fact]
        public void ToggleWorkshop_NotExisting_ShouldNotThrow()
        {
            var result = _controller.ToggleWorkshop(999);
            Assert.NotNull(result);
        }

        #endregion

        #endregion
    }
}
