using System;
using CncModels.Constants;
using CncModels.Dto;
using CncModels.Dto.Production;
using CncService;
using CncService.Impl;
using Xunit;

namespace CncService.Tests
{
    /// <summary>
    /// ProductionService 产量管理测试
    /// 测试场景：查询、日汇总、日期范围总产量、产量修正、参数校验
    /// </summary>
    [Collection("Database")]
    public class ProductionServiceTests : IDisposable
    {
        private readonly ProductionService _service;

        public ProductionServiceTests()
        {
            TestDb.TruncateAll();
            _service = ServiceFactory.CreateProductionService();
        }

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

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

        [Fact]
        public void GetList_无数据_返回空列表()
        {
            var result = _service.GetList(new ProductionQuery { 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_有产量数据_返回分页结果()
        {
            // 插入机床+日产量数据
            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_daily_production (machine_id, production_date, program_name, total_quantity, created_at, updated_at)
                VALUES (1, CURDATE(), 'O0001', 100, NOW(), NOW())");

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

        // ======== GetSummary ========

        [Fact]
        public void GetSummary_今日无产量_返回0()
        {
            var summary = _service.GetSummary(null, null, null, null, null);
            Assert.NotNull(summary);
            Assert.Equal(0, summary.TotalQuantity);
        }

        [Fact]
        public void GetSummary_指定日期有产量_返回正确数量()
        {
            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_daily_production (machine_id, production_date, program_name, total_quantity, created_at, updated_at)
                VALUES (1, CURDATE(), 'O0001', 150, NOW(), NOW())");

            var summary = _service.GetSummary(DateTime.Today, null, null, null, null);
            Assert.Equal(150, summary.TotalQuantity);
        }

        // ======== GetTotalByDateRange ========

        [Fact]
        public void GetTotalByDateRange_范围内无数据_返回0()
        {
            var total = _service.GetTotalByDateRange(
                new DateTime(2020, 1, 1),
                new DateTime(2020, 1, 31),
                null);
            Assert.Equal(0m, total);
        }

        // ======== Adjust ========

        [Fact]
        public void Adjust_正常修正_返回true()
        {
            var result = _service.Adjust(new ProductionAdjustRequest
            {
                TargetTable = "cnc_daily_production",
                TargetId = 1,
                FieldName = "total_quantity",
                NewValue = "200",
                Reason = "数据修正测试"
            });
            Assert.True(result);
        }

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

        [Fact]
        public void Adjust_修正记录已插入数据库()
        {
            _service.Adjust(new ProductionAdjustRequest
            {
                TargetTable = "cnc_daily_production",
                TargetId = 1,
                FieldName = "total_quantity",
                NewValue = "200",
                Reason = "测试原因"
            });

            var count = TestDb.QuerySingle<int>("SELECT COUNT(*) FROM cnc_production_adjustment");
            Assert.Equal(1, count);
        }
    }
}
