using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Xunit;
using Haoliang.Models.Device;
using Haoliang.Models.DataCollection;
using Haoliang.Core.Services;

namespace Haoliang.Tests
{
    public class DeviceCollectionServiceTests
    {
        private readonly IDeviceCollectionService _collectionService;

        public DeviceCollectionServiceTests()
        {
            // 这里应该使用mock对象或测试数据库
            _collectionService = new DeviceCollectionService(null, null, null, null, null, null);
        }

        [Fact]
        public async Task CollectDeviceDataAsync_ShouldParseValidJson()
        {
            // Arrange
            var sampleJson = @"{
                ""device"": ""FANUC_01"",
                ""desc"": ""CNC Machine"",
                ""tags"": [
                    {
                        ""id"": ""_io_status"",
                        ""desc"": ""I/O Status"",
                        ""quality"": 0,
                        ""value"": 1,
                        ""time"": ""2024-01-01T10:00:00""
                    },
                    {
                        ""id"": ""Tag5"",
                        ""desc"": ""NC Program"",
                        ""quality"": 0,
                        ""value"": ""O1234"",
                        ""time"": ""2024-01-01T10:00:00""
                    },
                    {
                        ""id"": ""Tag8"",
                        ""desc"": ""Cumulative Count"",
                        ""quality"": 0,
                        ""value"": 12345.00000,
                        ""time"": ""2024-01-01T10:00:00""
                    }
                ]
            }";

            // Act
            var result = await _collectionService.CollectDeviceDataAsync(1);

            // Assert
            Assert.NotNull(result);
            Assert.Equal("FANUC_01", result.DeviceCode);
            Assert.Equal("O1234", result.NCProgram);
            Assert.Equal(12345, result.CumulativeCount);
        }

        [Fact]
        public async Task CollectDeviceDataAsync_ShouldHandleInvalidJson()
        {
            // Arrange
            var invalidJson = @"{
                ""device"": ""FANUC_01"",
                ""desc"": ""CNC Machine"",
                ""tags"": [
                    {
                        ""id"": ""invalid_tag"",
                        ""value"": ""invalid_value""
                    }
                ]
            }";

            // Act & Assert
            await Assert.ThrowsAsync<JsonException>(() => 
                _collectionService.CollectDeviceDataAsync(1));
        }

        [Fact]
        public async Task PingDeviceAsync_ShouldReturnTrueForValidIp()
        {
            // Arrange
            var validIp = "8.8.8.8"; // Google DNS

            // Act
            var result = await _collectionService.PingDeviceAsync(validIp);

            // Assert
            Assert.True(result);
        }
    }

    public class ProductionServiceTests
    {
        private readonly IProductionService _productionService;

        public ProductionServiceTests()
        {
            _productionService = new ProductionService(null, null, null);
        }

        [Fact]
        public async Task CalculateProductionAsync_ShouldCalculateDifference()
        {
            // Arrange
            var current = new DeviceCurrentStatus
            {
                DeviceId = 1,
                NCProgram = "O1234",
                CumulativeCount = 15000,
                RecordTime = DateTime.Now
            };

            var last = new DeviceCurrentStatus
            {
                DeviceId = 1,
                NCProgram = "O1234",
                CumulativeCount = 12000,
                RecordTime = DateTime.Now.AddMinutes(-5)
            };

            // Act
            var result = await _productionService.CalculateProductionAsync(1);

            // Assert
            Assert.Equal(3000, result);
        }

        [Fact]
        public async Task CalculateProductionAsync_ShouldHandleNegativeValues()
        {
            // Arrange
            var current = new DeviceCurrentStatus
            {
                DeviceId = 1,
                NCProgram = "O1234",
                CumulativeCount = 10000,
                RecordTime = DateTime.Now
            };

            var last = new DeviceCurrentStatus
            {
                DeviceId = 1,
                NCProgram = "O1234",
                CumulativeCount = 12000, // 比当前值大，应该产生负数
                RecordTime = DateTime.Now.AddMinutes(-5)
            };

            // Act
            var result = await _productionService.CalculateProductionAsync(1);

            // Assert
            Assert.Equal(0, result); // 负数应该被保护为0
        }

        [Fact]
        public async Task CalculateProductionAsync_ShouldHandleProgramSwitch()
        {
            // Arrange
            var current = new DeviceCurrentStatus
            {
                DeviceId = 1,
                NCProgram = "O5678", // 不同的程序
                CumulativeCount = 20000,
                RecordTime = DateTime.Now
            };

            var last = new DeviceCurrentStatus
            {
                DeviceId = 1,
                NCProgram = "O1234",
                CumulativeCount = 15000,
                RecordTime = DateTime.Now.AddMinutes(-5)
            };

            // Act
            var result = await _productionService.CalculateProductionAsync(1);

            // Assert
            Assert.Equal(20000, result); // 新程序以当前累计数为起点
        }
    }

    public class AlarmServiceTests
    {
        private readonly IAlarmService _alarmService;

        public AlarmServiceTests()
        {
            _alarmService = new AlarmManager(null, null, null);
        }

        [Fact]
        public async Task CreateAlarmAsync_ShouldCreateAlarm()
        {
            // Arrange
            var alarm = new Alarm
            {
                DeviceId = 1,
                DeviceCode = "FANUC_01",
                AlarmType = AlarmType.DeviceOffline,
                Severity = AlarmSeverity.Critical,
                Title = "Device Offline",
                Description = "The device has been offline for more than 5 minutes",
                AlarmStatus = AlarmStatus.Active
            };

            // Act
            var result = await _alarmService.CreateAlarmAsync(alarm);

            // Assert
            Assert.NotNull(result);
            Assert.Equal(AlarmStatus.Active, result.AlarmStatus);
            Assert.NotNull(result.CreateTime);
        }

        [Fact]
        public async Task ResolveAlarmAsync_ShouldMarkAsResolved()
        {
            // Arrange
            var alarm = new Alarm
            {
                DeviceId = 1,
                DeviceCode = "FANUC_01",
                AlarmType = AlarmType.DeviceOffline,
                Severity = AlarmSeverity.Warning,
                Title = "Device Offline",
                Description = "The device has been offline",
                AlarmStatus = AlarmStatus.Active
            };

            var createdAlarm = await _alarmService.CreateAlarmAsync(alarm);

            // Act
            var result = await _alarmService.ResolveAlarmAsync(createdAlarm.AlarmId, "Device reconnected");

            // Assert
            Assert.True(result);
            
            // 验证状态确实改变了
            var resolvedAlarm = await _alarmService.GetAlarmByIdAsync(createdAlarm.AlarmId);
            Assert.Equal(AlarmStatus.Resolved, resolvedAlarm.AlarmStatus);
            Assert.NotNull(resolvedAlarm.ResolvedTime);
            Assert.Equal("Device reconnected", resolvedAlarm.ResolutionNote);
        }
    }

    public class TemplateServiceTests
    {
        private readonly ITemplateService _templateService;

        public TemplateServiceTests()
        {
            _templateService = new TemplateManager(null, null, null, null);
        }

        [Fact]
        public async Task CreateTemplateAsync_ShouldCreateValidTemplate()
        {
            // Arrange
            var template = new CNCBrandTemplate
            {
                TemplateName = "FANUC Standard",
                BrandName = "FANUC",
                Description = "Standard FANUC template",
                IsEnabled = true,
                Version = "1.0",
                TemplateJson = @"{
                    ""device"": {
                        ""status"": ""_io_status""
                    },
                    ""production"": {
                        ""program"": ""Tag5"",
                        ""count"": ""Tag8""
                    }
                }"
            };

            // Act
            var result = await _templateService.CreateTemplateAsync(template);

            // Assert
            Assert.NotNull(result);
            Assert.Equal("FANUC Standard", result.TemplateName);
            Assert.True(result.IsEnabled);
            Assert.NotNull(result.CreateTime);
        }

        [Fact]
        public async Task ValidateTemplateAsync_ShouldRejectInvalidTemplate()
        {
            // Arrange
            var invalidTemplate = new CNCBrandTemplate
            {
                TemplateName = "", // 空模板名
                BrandName = "FANUC",
                Description = "Invalid template",
                IsEnabled = true,
                Version = "1.0",
                TemplateJson = "" // 空JSON
            };

            // Act
            var result = await _templateService.ValidateTemplateAsync(invalidTemplate);

            // Assert
            Assert.False(result);
        }
    }

    public class SystemServiceTests
    {
        private readonly ISystemConfigService _configService;
        private readonly ILoggingService _loggingService;

        public SystemServiceTests()
        {
            _configService = new SystemConfigManager(null, null);
            _loggingService = new LoggingManager(null, null);
        }

        [Fact]
        public async Task GetConfigAsync_ShouldReturnExistingConfig()
        {
            // Arrange
            await _configService.SetConfigAsync("test.config", "test.value");

            // Act
            var result = await _configService.GetConfigAsync("test.config");

            // Assert
            Assert.NotNull(result);
            Assert.Equal("test.value", result.ConfigValue);
        }

        [Fact]
        public async Task SetConfigAsync_ShouldUpdateConfig()
        {
            // Arrange
            var newConfig = await _configService.SetConfigAsync("test.config", "new.value");

            // Act
            var result = await _configService.GetConfigAsync("test.config");

            // Assert
            Assert.NotNull(result);
            Assert.Equal("new.value", result.ConfigValue);
        }

        [Fact]
        public async Task LogAsync_ShouldLogMessage()
        {
            // Arrange
            var message = "Test log message";

            // Act
            await _loggingService.LogAsync(LogLevel.Information, message);

            // 这里可以添加数据库验证，检查日志是否正确存储
        }
    }
}