using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.Pumps;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Moq;
using Options = Microsoft.Extensions.Options.Options;

namespace adas_core.Test.Services;

[TestFixture]
public class ConfigPumpsServiceTest
{
    /// <summary>
    /// Initializes the test environment by creating mock dependencies and instantiating the <see cref="ConfigPumpsService"/> under test.
    /// </summary>
    [SetUp]
        public void Setup()
        {
            //configPumpsServiceMock = new Mock<IConfigPumpsService>();
            _configPumpsRepositoryMock = new Mock<IConfigPumpsRepository>();
    
            _optionsApiSettings = Options.Create(_apiSettings);
    
            _logger = new Mock<ILogger<ConfigPumpsService>>();
    
            _configPumpsService = new ConfigPumpsService(
                _configPumpsRepositoryMock.Object,
                _optionsApiSettings,
                _logger.Object,
                _httpContextAccessor.Object,
                _auditService.Object);
        }

    private ConfigPumpsService _configPumpsService;

    //Mock<IConfigPumpsService> configPumpsServiceMock;
    private Mock<IConfigPumpsRepository> _configPumpsRepositoryMock;

    private readonly ApiSettings _apiSettings = new()
    {
        ConfigPumpsRequired = true,
        ConfigPumpsKey = "PV1",
        ConfigObservation = new ConfigObservationSettings
        {
            Refresh = null
        }
    };

    private IOptions<ApiSettings> _optionsApiSettings;

    private Mock<ILogger<ConfigPumpsService>> _logger;

    private readonly Mock<IHttpContextAccessor> _httpContextAccessor = new();
    private readonly Mock<ILocalAuditService> _auditService = new();

    private static readonly DateTime Now = DateTime.Now;

    /// <summary>
    /// Verifies that the <see cref="ConfigPumpsService.Map"/> method returns the same <see cref="PumpObservation"/> instance unchanged when the <c>ConfigPumpsRequired</c> option is set to <c>false</c>, bypassing any pump configuration lookup or transformation.
    /// </summary>
    [Test]
        public async Task Map_configPumpsRequired_false_Return_same_pump()
        {
            _optionsApiSettings.Value.ConfigPumpsRequired = false;
    
            var pump = new PumpObservation
            {
                Code = "code",
                Name = "name",
                Time = Now
            };
    
            var configPumpsService = new ConfigPumpsService(
                _configPumpsRepositoryMock.Object,
                _optionsApiSettings,
                _logger.Object,
                _httpContextAccessor.Object,
                _auditService.Object);
    
            var result = await configPumpsService.Map(pump);
    
            Assert.That(pump, Is.EqualTo(result));
        }

    /// <summary>
    /// Verifies that when pump configuration is required and the pump has no alarm type,
    /// the <c>Map</c> method returns the same pump instance unchanged.
    /// </summary>
    [Test]
        public async Task Map_not_alarmType_Return_same_pump()
        {
            _optionsApiSettings.Value.ConfigPumpsRequired = true;
    
            var pump = new PumpObservation
            {
                Code = "code",
                Name = "name",
                Time = Now
            };
    
            var result = await _configPumpsService.Map(pump);
    
            Assert.That(pump, Is.EqualTo(result));
        }

    /// <summary>
    /// Verifies that the <see cref="ConfigPumpsService.Map"/> method returns the original <see cref="PumpObservation"/> unchanged when the configuration pump item is empty, ensuring that no <c>UiConfiguration</c> is assigned in that case.
    /// </summary>
    [Test]
        public async Task Map_Not_uiConfiguration_Return_same_pump()
        {
            _optionsApiSettings.Value.ConfigPumpsRequired = true;
    
            var pump = new PumpObservation
            {
                Code = "code",
                Name = "name",
                Time = Now,
                AlarmType = PumpEnum.AlarmType.Attention
            };
    
            var configPumpItem = new ConfigPumpItem();
    
            var configPumps = new ConfigPumps
            {
                Id = "PV1",
                Items = [configPumpItem]
            };
            _configPumpsRepositoryMock.Setup(c => c.FindById(It.IsAny<string>())).ReturnsAsync(configPumps);
    
            var result = await _configPumpsService.Map(pump);
            using (Assert.EnterMultipleScope())
            {
                Assert.That(pump, Is.EqualTo(result));
                Assert.That(result.UiConfiguration, Is.Null);
            }
        }

    /// <summary>
    /// Verifies that mapping a <see cref="PumpObservation"/> returns the expected pump UI
    /// configuration when a matching <see cref="ConfigPumpItem"/> is found for the pump's
    /// alarm type, ensuring the resulting UI configuration contains the expected label
    /// entries such as the "screenAlarmLabel" mapped to the alarm type.
    /// </summary>
    [Test]
        public async Task Map_uiConfiguration_Return_pump_uiConfiguration()
        {
            _optionsApiSettings.Value.ConfigPumpsRequired = true;
    
            var pump = new PumpObservation
            {
                Code = "code",
                Name = "name",
                Time = Now,
                AlarmType = PumpEnum.AlarmType.AirInLine
            };
    
    
            var configPumpItem = new ConfigPumpItem
            {
                AlarmType = PumpEnum.AlarmType.AirInLine,
                UiConfiguration = new Dictionary<string, object> { { "screenAlarmLabel", PumpEnum.AlarmType.AirInLine } }
            };
    
            var configPumps = new ConfigPumps
            {
                Id = "PV1",
                Items = [configPumpItem]
            };
    
            _configPumpsRepositoryMock.Setup(c => c.FindById(It.IsAny<string>())).ReturnsAsync(configPumps);
    
            var result = await _configPumpsService.Map(pump);
    
            Assert.That(result.UiConfiguration, Is.Not.Null);
            using (Assert.EnterMultipleScope())
            {
                Assert.That(result.UiConfiguration, Has.Count.EqualTo(1));
                Assert.That(result.UiConfiguration!["screenAlarmLabel"], Is.EqualTo(PumpEnum.AlarmType.AirInLine));
            };
        }
}