namespace LiquidCode.Tester.Worker.Services;

/// <summary>
/// Output checker service - always uses Isolate sandbox for checker execution
/// </summary>
public class OutputCheckerService : IOutputCheckerService
{
    private readonly ILogger<OutputCheckerService> _logger;
    private readonly CheckerServiceIsolate _checkerService;

    public OutputCheckerService(
        ILogger<OutputCheckerService> logger,
        CheckerServiceIsolate checkerService)
    {
        _logger = logger;
        _checkerService = checkerService;

        _logger.LogInformation("Checker service configured to use Isolate sandbox");
    }

    public async Task<bool> CheckOutputAsync(string actualOutput, string expectedOutputPath)
    {
        try
        {
            var expectedOutput = await File.ReadAllTextAsync(expectedOutputPath);

            // Normalize outputs for comparison
            var normalizedActual = NormalizeOutput(actualOutput);
            var normalizedExpected = NormalizeOutput(expectedOutput);

            var match = normalizedActual == normalizedExpected;

            if (!match)
            {
                _logger.LogDebug("Output mismatch. Expected length: {ExpectedLength}, Actual length: {ActualLength}",
                    normalizedExpected.Length, normalizedActual.Length);
            }

            return match;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error checking output against {ExpectedFile}", expectedOutputPath);
            return false;
        }
    }

    private string NormalizeOutput(string output)
    {
        // Remove trailing whitespace from each line and normalize line endings
        var lines = output.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)
            .Select(line => line.TrimEnd())
            .ToList();

        // Remove trailing empty lines
        while (lines.Count > 0 && string.IsNullOrWhiteSpace(lines[^1]))
        {
            lines.RemoveAt(lines.Count - 1);
        }

        // Remove leading empty lines
        while (lines.Count > 0 && string.IsNullOrWhiteSpace(lines[0]))
        {
            lines.RemoveAt(0);
        }

        return string.Join("\n", lines);
    }

    public async Task<bool> CheckOutputWithCheckerAsync(
        string actualOutput,
        string inputFilePath,
        string expectedOutputPath,
        string? checkerPath)
    {
        // If custom checker is available, use it
        if (!string.IsNullOrEmpty(checkerPath) && File.Exists(checkerPath))
        {
            _logger.LogDebug("Using custom checker in Isolate: {CheckerPath}", checkerPath);

            var checkerResult = await _checkerService.CheckAsync(
                checkerPath, inputFilePath, actualOutput, expectedOutputPath);

            if (!checkerResult.Accepted)
            {
                _logger.LogWarning("Custom checker verdict: {Verdict} - {Message}",
                    checkerResult.Verdict, checkerResult.Message);
            }

            return checkerResult.Accepted;
        }

        // Fall back to standard string comparison
        _logger.LogDebug("No custom checker, using standard comparison");
        return await CheckOutputAsync(actualOutput, expectedOutputPath);
    }
}
