using LiquidCode.Tester.Worker.Services;
using Microsoft.Extensions.Logging;
using Moq;

namespace LiquidCode.Tester.Worker.Tests;

public class OutputCheckerServiceTests : IDisposable
{
    private readonly OutputCheckerService _service;
    private readonly string _testDirectory;

    public OutputCheckerServiceTests()
    {
        var logger = new Mock<ILogger<OutputCheckerService>>();
        var checkerLogger = new Mock<ILogger<CheckerService>>();
        var checkerService = new CheckerService(checkerLogger.Object);
        _service = new OutputCheckerService(logger.Object, checkerService);
        _testDirectory = Path.Combine(Path.GetTempPath(), "OutputCheckerTests", Guid.NewGuid().ToString());
        Directory.CreateDirectory(_testDirectory);
    }

    [Fact]
    public async Task CheckOutputAsync_ExactMatch_ReturnsTrue()
    {
        // Arrange
        var expectedOutput = "Hello, World!";
        var actualOutput = "Hello, World!";
        var expectedFilePath = CreateTempFile(expectedOutput);

        // Act
        var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);

        // Assert
        Assert.True(result);
    }

    [Fact]
    public async Task CheckOutputAsync_DifferentOutput_ReturnsFalse()
    {
        // Arrange
        var expectedOutput = "Hello, World!";
        var actualOutput = "Goodbye, World!";
        var expectedFilePath = CreateTempFile(expectedOutput);

        // Act
        var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);

        // Assert
        Assert.False(result);
    }

    [Fact]
    public async Task CheckOutputAsync_TrailingWhitespace_ReturnsTrue()
    {
        // Arrange
        var expectedOutput = "Hello, World!";
        var actualOutput = "Hello, World!   \n\n";
        var expectedFilePath = CreateTempFile(expectedOutput);

        // Act
        var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);

        // Assert
        Assert.True(result);
    }

    [Fact]
    public async Task CheckOutputAsync_LeadingWhitespace_ReturnsTrue()
    {
        // Arrange
        var expectedOutput = "Hello, World!";
        var actualOutput = "   \n\nHello, World!";
        var expectedFilePath = CreateTempFile(expectedOutput);

        // Act
        var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);

        // Assert
        Assert.True(result);
    }

    [Fact]
    public async Task CheckOutputAsync_DifferentLineEndings_ReturnsTrue()
    {
        // Arrange
        var expectedOutput = "Line1\nLine2\nLine3";
        var actualOutput = "Line1\r\nLine2\r\nLine3";
        var expectedFilePath = CreateTempFile(expectedOutput);

        // Act
        var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);

        // Assert
        Assert.True(result);
    }

    [Fact]
    public async Task CheckOutputAsync_MultipleLines_ExactMatch_ReturnsTrue()
    {
        // Arrange
        var expectedOutput = "Line 1\nLine 2\nLine 3";
        var actualOutput = "Line 1\nLine 2\nLine 3";
        var expectedFilePath = CreateTempFile(expectedOutput);

        // Act
        var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);

        // Assert
        Assert.True(result);
    }

    [Fact]
    public async Task CheckOutputAsync_EmptyOutputs_ReturnsTrue()
    {
        // Arrange
        var expectedOutput = "";
        var actualOutput = "";
        var expectedFilePath = CreateTempFile(expectedOutput);

        // Act
        var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);

        // Assert
        Assert.True(result);
    }

    [Fact]
    public async Task CheckOutputAsync_OnlyWhitespace_ReturnsTrue()
    {
        // Arrange
        var expectedOutput = "   \n\n   ";
        var actualOutput = "   \n\n   ";
        var expectedFilePath = CreateTempFile(expectedOutput);

        // Act
        var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);

        // Assert
        Assert.True(result);
    }

    [Fact]
    public async Task CheckOutputAsync_CaseSensitive_ReturnsFalse()
    {
        // Arrange
        var expectedOutput = "Hello, World!";
        var actualOutput = "hello, world!";
        var expectedFilePath = CreateTempFile(expectedOutput);

        // Act
        var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);

        // Assert
        Assert.False(result);
    }

    private string CreateTempFile(string content)
    {
        var filePath = Path.Combine(_testDirectory, $"test_{Guid.NewGuid()}.txt");
        File.WriteAllText(filePath, content);
        return filePath;
    }

    public void Dispose()
    {
        if (Directory.Exists(_testDirectory))
        {
            Directory.Delete(_testDirectory, true);
        }
    }
}
