using System.Net;
using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Services;
using adas_core.module.Relays.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Moq;
using Moq.Protected;
using Options = Microsoft.Extensions.Options.Options;

namespace adas_core.Test.Services;

[TestFixture]
public class RelayServiceTest
{
    /// <summary>
    /// Sets up the test environment by initializing mocks and dependencies required for unit testing the <see cref="RelayService"/>, including logger, HTTP client factory, HTTP message handler, relay settings, point-of-care service, and relay repository.
    /// </summary>
    [SetUp]
        public void Setup()
        {
            _logger = new Mock<ILogger<RelayService>>();
            _httpClientFactoryMock = new Mock<IHttpClientFactory>();
            _httpMessageHandlerMock = new Mock<HttpMessageHandler>();
            _relaySettings.RecordingOrApiUrl = "http://localhost:8080";
            _relaySettings.Cache = true;
            _optionsRelaySettings = Options.Create(_relaySettings);
            _pocServiceMock = new Mock<IPointOfCareService>();
            _relayRepositoryMock = new Mock<IRelayRepository>();
    
            _relayService = new RelayService(
                //optionsApiSettings,
                _logger.Object,
                _httpClientFactoryMock.Object,
                _optionsRelaySettings,
                _pocServiceMock.Object,
                _relayRepositoryMock.Object);
        }

    private RelayService _relayService = null!;
    private Mock<IHttpClientFactory> _httpClientFactoryMock = null!;
    private Mock<HttpMessageHandler> _httpMessageHandlerMock = null!;
    private readonly RelaySettings _relaySettings = new();
    private IOptions<RelaySettings> _optionsRelaySettings = null!;
    private Mock<IPointOfCareService> _pocServiceMock = null!;
    private Mock<IRelayRepository> _relayRepositoryMock = null!;

    //readonly ApiSettings apiSettings = new ()
    //{
    //};
    //IOptions<ApiSettings> optionsApiSettings;

    private Mock<ILogger<RelayService>> _logger = null!;

    /// <summary>
    /// Verifies that the relay service successfully powers off a relay by issuing an HTTP request through the configured HTTP client factory.
    /// </summary>
    [Test]
        public async Task PowerOffAsync()
        {
            var relay = new Relay
            {
                Driver = "KMTronicV2",
                Ip = "10.133.10.169",
                Port = 80,
                RelayNumber = 1,
                RelayName = "Relay1",
                Total = 8,
                Username = "adas",
                Password = "!HULPM22"
            };
    
    
            var httpResponseMessage = new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent("Test content")
            };
    
            _httpMessageHandlerMock.Protected()
                .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
                    ItExpr.IsAny<CancellationToken>())
                .ReturnsAsync(httpResponseMessage);
    
    
            var client = new HttpClient(_httpMessageHandlerMock.Object);
    
            _httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
    
            await _relayService.PowerOff(relay);
        }

    /// <summary>
    /// Verifies that <see cref="RelayService.PowerOn"/> correctly sends a power-on request to the configured relay device using the HTTP client.
    /// </summary>
    [Test]
        public async Task PowerOnAsync()
        {
            var relay = new Relay
            {
                Driver = "KMTronicV2",
                Ip = "10.133.10.169",
                Port = 80,
                RelayNumber = 1,
                RelayName = "Relay1",
                Total = 8,
                Username = "adas",
                Password = "!HULPM22"
            };
    
    
            var httpResponseMessage = new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent("Test content")
            };
    
            _httpMessageHandlerMock.Protected()
                .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
                    ItExpr.IsAny<CancellationToken>())
                .ReturnsAsync(httpResponseMessage);
    
    
            var client = new HttpClient(_httpMessageHandlerMock.Object);
    
            _httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
    
            await _relayService.PowerOn(relay);
        }

    /// <summary>
    /// Verifies that <c>CheckRelayStatus</c> returns <see cref="RelayEnum.Status.On"/> when the mocked HTTP response indicates the relay is on.
    /// </summary>
    [Test]
        public async Task CheckRelayStatus_Return_On()
        {
            var relay = new Relay
            {
                Driver = "KMTronicV2",
                Ip = "10.133.10.169",
                Port = 80,
                RelayNumber = 1,
                RelayName = "Relay1",
                Total = 8,
                Username = "adas",
                Password = "!HULPM22"
            };
    
            var httpResponseMessage = new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent("\"On")
            };
    
            _httpMessageHandlerMock.Protected()
                .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
                    ItExpr.IsAny<CancellationToken>())
                .ReturnsAsync(httpResponseMessage);
    
            //httpMessageHandlerMock.Protected()
            //    .Setup<Task<string>>("ReadAsStringAsync", ItExpr.IsAny<string>(), ItExpr.IsAny<CancellationToken>())
            //    .ReturnsAsync("\\On");
    
    
            var client = new HttpClient(_httpMessageHandlerMock.Object);
    
            _httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
    
            await _relayService.PowerOn(relay);
            var result = await _relayService.CheckRelayStatus(relay);
    
            //Assert.That(result, Is.Not.Null);
            Assert.That(result, Is.EqualTo(RelayEnum.Status.On));
        }

    [Test]
    public async Task CheckRelayStatus_Return_Off()
    {
        var relay = new Relay
        {
            Driver = "KMTronicV2",
            Ip = "10.133.10.169",
            Port = 80,
            RelayNumber = 1,
            RelayName = "Relay1",
            Total = 8,
            Username = "adas",
            Password = "!HULPM22"
        };

        var httpResponseMessage = new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent("\"Off")
        };

        _httpMessageHandlerMock.Protected()
            .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
                ItExpr.IsAny<CancellationToken>())
            .ReturnsAsync(httpResponseMessage);


        var client = new HttpClient(_httpMessageHandlerMock.Object);

        _httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
        await _relayService.PowerOff(relay);
        var result = await _relayService.CheckRelayStatus(relay);

        //Assert.That(result, Is.Not.Null); //result nunca es null aquí
        Assert.That(result, Is.EqualTo(RelayEnum.Status.Off));
    }

    /// <summary>
    /// Verifies that <c>CheckRelayStatus</c> returns <see cref="RelayEnum.Status.Unknown"/> when the relay
    /// driver response does not match a recognized on/off state (e.g., the raw payload "\\Off" is not
    /// mapped to a known status).
    /// </summary>
    [Test]
        public async Task CheckRelayStatus_Return_Unknown()
        {
            var relay = new Relay
            {
                Driver = "KMTronicV2",
                Ip = "10.133.10.169",
                Port = 80,
                RelayNumber = 1,
                RelayName = "Relay1",
                Total = 8,
                Username = "adas",
                Password = "!HULPM22"
            };
    
    
            var httpResponseMessage = new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent("\\Off")
            };
    
            _httpMessageHandlerMock.Protected()
                .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
                    ItExpr.IsAny<CancellationToken>())
                .ReturnsAsync(httpResponseMessage);
    
    
            var client = new HttpClient(_httpMessageHandlerMock.Object);
    
            _httpClientFactoryMock.Setup(c => c.CreateClient(It.IsAny<string>())).Returns(client);
    
            var result = await _relayService.CheckRelayStatus(relay);
    
            //Assert.That(result, Is.Not.Null);
            Assert.That(result, Is.EqualTo(RelayEnum.Status.Unknown));
        }
}