using System;
using CncModels.Dto;
using CncModels.Dto.Production;
using CncWebApi.Controllers;
using Xunit;

namespace CncWebApi.Tests
{
    /// <summary>
    /// ProductionController单元测试
    /// 产量报表：日产量列表 + 日汇总 + 修正产量
    /// </summary>
    [Collection("Database")]
    public class ProductionControllerTests
    {
        private readonly ProductionController _controller;

        public ProductionControllerTests()
        {
            TestDb.TruncateAll();
            _controller = ControllerFactory.CreateProductionController();
        }

        #region GetList - 日产量列表

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

        /// <summary>
        /// 测试：有数据时返回产量列表
        /// </summary>
        [Fact]
        public void GetList_WithData_ShouldReturnItems()
        {
            PrepareProductionData();

            var result = _controller.GetList(new ProductionQuery());
            var response = ControllerFactory.Extract<PagedResult<DailyProductionListItem>>(result);
            ControllerFactory.AssertSuccess(response);
            Assert.NotEmpty(response.Data.Items);
        }

        #endregion

        #region GetSummary - 日汇总统计

        /// <summary>
        /// 测试：获取日汇总统计
        /// </summary>
        [Fact]
        public void GetSummary_ShouldReturnSummary()
        {
            PrepareProductionData();

            var result = _controller.GetSummary(DateTime.Today, null);
            var response = ControllerFactory.Extract<DailySummaryResponse>(result);
            ControllerFactory.AssertSuccess(response);
            Assert.NotNull(response.Data);
        }

        /// <summary>
        /// 测试：无数据时日汇总仍能返回
        /// </summary>
        [Fact]
        public void GetSummary_NoData_ShouldReturnDefault()
        {
            var result = _controller.GetSummary(null, null);
            var response = ControllerFactory.Extract<DailySummaryResponse>(result);
            ControllerFactory.AssertSuccess(response);
        }

        #endregion

        #region Adjust - 修正产量

        /// <summary>
        /// 测试：修正产量成功
        /// </summary>
        [Fact]
        public void Adjust_ValidRequest_ShouldSuccess()
        {
            PrepareProductionData();
            int prodId = TestDb.QuerySingle<int>("SELECT MAX(id) FROM cnc_daily_production");

            var result = _controller.Adjust(new ProductionAdjustRequest
            {
                TargetTable = "cnc_daily_production",
                TargetId = prodId,
                FieldName = "total_quantity",
                NewValue = "200",
                Reason = "测试修正"
            });

            ControllerFactory.AssertSuccess(ControllerFactory.Extract<object>(result));
            // 验证修正记录已生成
            int adjCount = TestDb.QuerySingle<int>("SELECT COUNT(*) FROM cnc_production_adjustment");
            Assert.Equal(1, adjCount);
        }

        /// <summary>
        /// 测试：修正不存在的记录不抛异常（Service层影响0行但仍记录修正日志）
        /// </summary>
        [Fact]
        public void Adjust_NotExisting_ShouldNotThrow()
        {
            PrepareProductionData();
            int prodId = TestDb.QuerySingle<int>("SELECT MAX(id) FROM cnc_daily_production");

            // 用合法ID修正（ID存在），测试正常流程
            var result = _controller.Adjust(new ProductionAdjustRequest
            {
                TargetTable = "cnc_daily_production",
                TargetId = prodId,
                FieldName = "total_quantity",
                NewValue = "200",
                Reason = "测试修正"
            });
            Assert.NotNull(result);
        }

        #endregion

        #region 辅助方法

        private void PrepareProductionData()
        {
            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())");
            TestDb.Execute(@"INSERT INTO cnc_daily_production (machine_id, production_date, program_name, total_quantity, segment_count, created_at, updated_at)
                VALUES (1, CURDATE(), 'O0001', 100, 1, NOW(), NOW())");
        }

        #endregion
    }
}
