using ColaFlow.Modules.Mcp.Application.DTOs.Notifications;
using ColaFlow.Modules.Mcp.Application.EventHandlers;
using ColaFlow.Modules.Mcp.Application.Services;
using ColaFlow.Modules.Mcp.Domain.Events;
using ColaFlow.Modules.Mcp.Domain.ValueObjects;
using Microsoft.Extensions.Logging;
using Moq;
using Xunit;

namespace ColaFlow.Modules.Mcp.Tests.EventHandlers;

public class PendingChangeApprovedNotificationHandlerTests
{
    private readonly Mock<IMcpNotificationService> _mockNotificationService;
    private readonly Mock<ILogger<PendingChangeApprovedNotificationHandler>> _mockLogger;
    private readonly PendingChangeApprovedNotificationHandler _handler;

    public PendingChangeApprovedNotificationHandlerTests()
    {
        _mockNotificationService = new Mock<IMcpNotificationService>();
        _mockLogger = new Mock<ILogger<PendingChangeApprovedNotificationHandler>>();

        _handler = new PendingChangeApprovedNotificationHandler(
            _mockNotificationService.Object,
            _mockLogger.Object);
    }

    [Fact]
    public async Task Handle_SendsNotification_WithCorrectData()
    {
        // Arrange
        var pendingChangeId = Guid.NewGuid();
        var tenantId = Guid.NewGuid();
        var approvedBy = Guid.NewGuid();
        var entityId = Guid.NewGuid();

        var diff = new DiffPreview(
            "CREATE",
            "Epic",
            entityId,
            null,
            null,
            "{\"name\":\"Test Epic\"}",
            new List<DiffField>());

        var domainEvent = new PendingChangeApprovedEvent(
            pendingChangeId,
            "create_epic",
            diff,
            approvedBy,
            tenantId);

        // Act
        await _handler.Handle(domainEvent, CancellationToken.None);

        // Assert
        _mockNotificationService.Verify(
            s => s.NotifyPendingChangeApprovedAsync(
                It.Is<PendingChangeApprovedNotification>(n =>
                    n.PendingChangeId == pendingChangeId &&
                    n.ToolName == "create_epic" &&
                    n.EntityType == "Epic" &&
                    n.Operation == "CREATE" &&
                    n.EntityId == entityId &&
                    n.ApprovedBy == approvedBy &&
                    n.TenantId == tenantId),
                It.IsAny<CancellationToken>()),
            Times.Once);
    }

    [Fact]
    public async Task Handle_DoesNotThrow_WhenNotificationServiceFails()
    {
        // Arrange
        var pendingChangeId = Guid.NewGuid();
        var tenantId = Guid.NewGuid();
        var approvedBy = Guid.NewGuid();

        var diff = new DiffPreview(
            "CREATE",
            "Epic",
            null,
            null,
            null,
            "{\"name\":\"Test Epic\"}",
            new List<DiffField>());

        var domainEvent = new PendingChangeApprovedEvent(
            pendingChangeId,
            "create_epic",
            diff,
            approvedBy,
            tenantId);

        _mockNotificationService.Setup(s => s.NotifyPendingChangeApprovedAsync(
                It.IsAny<PendingChangeApprovedNotification>(),
                It.IsAny<CancellationToken>()))
            .ThrowsAsync(new Exception("SignalR connection failed"));

        // Act & Assert - Should not throw
        await _handler.Handle(domainEvent, CancellationToken.None);
    }
}
