using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using NSubstitute;
using ScadaLink.Commons.Entities.Sites;
using ScadaLink.Commons.Interfaces.Repositories;
using ScadaLink.Commons.Interfaces.Services;
using ScadaLink.Commons.Messages.Artifacts;
using ScadaLink.Communication;

namespace ScadaLink.DeploymentManager.Tests;

/// <summary>
/// WP-7: Tests for system-wide artifact deployment.
/// </summary>
public class ArtifactDeploymentServiceTests
{
    private readonly ISiteRepository _siteRepo;
    private readonly IDeploymentManagerRepository _deploymentRepo;
    private readonly ITemplateEngineRepository _templateRepo;
    private readonly IExternalSystemRepository _externalSystemRepo;
    private readonly INotificationRepository _notificationRepo;
    private readonly IAuditService _audit;

    public ArtifactDeploymentServiceTests()
    {
        _siteRepo = Substitute.For<ISiteRepository>();
        _deploymentRepo = Substitute.For<IDeploymentManagerRepository>();
        _templateRepo = Substitute.For<ITemplateEngineRepository>();
        _externalSystemRepo = Substitute.For<IExternalSystemRepository>();
        _notificationRepo = Substitute.For<INotificationRepository>();
        _audit = Substitute.For<IAuditService>();
    }

    [Fact]
    public async Task DeployToAllSitesAsync_NoSites_ReturnsFailure()
    {
        _siteRepo.GetAllSitesAsync().Returns(new List<Site>());

        var service = CreateService();

        var result = await service.DeployToAllSitesAsync("admin");

        Assert.True(result.IsFailure);
        Assert.Contains("No sites", result.Error);
    }

    [Fact]
    public void SiteArtifactResult_ContainsSiteInfo()
    {
        var result = new SiteArtifactResult("site1", "Site One", true, null);
        Assert.Equal("site1", result.SiteId);
        Assert.Equal("Site One", result.SiteName);
        Assert.True(result.Success);
        Assert.Null(result.ErrorMessage);
    }

    [Fact]
    public void ArtifactDeploymentSummary_CountsCorrectly()
    {
        var results = new List<SiteArtifactResult>
        {
            new("s1", "Site1", true, null),
            new("s2", "Site2", false, "error"),
            new("s3", "Site3", true, null)
        };
        var summary = new ArtifactDeploymentSummary("dep1", results, 2, 1);

        Assert.Equal(2, summary.SuccessCount);
        Assert.Equal(1, summary.FailureCount);
        Assert.Equal(3, summary.SiteResults.Count);
    }

    private ArtifactDeploymentService CreateService()
    {
        var comms = new CommunicationService(
            Options.Create(new CommunicationOptions()),
            NullLogger<CommunicationService>.Instance);

        return new ArtifactDeploymentService(
            _siteRepo, _deploymentRepo, _templateRepo, _externalSystemRepo, _notificationRepo,
            comms, _audit,
            Options.Create(new DeploymentManagerOptions()),
            NullLogger<ArtifactDeploymentService>.Instance);
    }

    private static DeployArtifactsCommand CreateCommand()
    {
        return new DeployArtifactsCommand(
            "dep1", null, null, null, null, null, null, DateTimeOffset.UtcNow);
    }
}
