using Microsoft.Extensions.Logging.Abstractions;
using ScadaLink.SiteRuntime.Scripts;

namespace ScadaLink.SiteRuntime.Tests.Scripts;

/// <summary>
/// WP-19: Script Trust Model tests — validates forbidden API detection and compilation.
/// </summary>
public class ScriptCompilationServiceTests
{
    private readonly ScriptCompilationService _service;

    public ScriptCompilationServiceTests()
    {
        _service = new ScriptCompilationService(NullLogger<ScriptCompilationService>.Instance);
    }

    [Fact]
    public void Compile_ValidScript_Succeeds()
    {
        var result = _service.Compile("test", "1 + 1");
        Assert.True(result.IsSuccess);
        Assert.NotNull(result.CompiledScript);
        Assert.Empty(result.Errors);
    }

    [Fact]
    public void Compile_InvalidSyntax_ReturnsErrors()
    {
        var result = _service.Compile("bad", "this is not valid C# {{{");
        Assert.False(result.IsSuccess);
        Assert.NotEmpty(result.Errors);
    }

    [Fact]
    public void ValidateTrustModel_SystemIO_Forbidden()
    {
        var violations = _service.ValidateTrustModel("System.IO.File.ReadAllText(\"test\")");
        Assert.NotEmpty(violations);
        Assert.Contains(violations, v => v.Contains("System.IO"));
    }

    [Fact]
    public void ValidateTrustModel_Process_Forbidden()
    {
        var violations = _service.ValidateTrustModel(
            "System.Diagnostics.Process.Start(\"cmd\")");
        Assert.NotEmpty(violations);
    }

    [Fact]
    public void ValidateTrustModel_Reflection_Forbidden()
    {
        var violations = _service.ValidateTrustModel(
            "typeof(string).GetType().GetMethods(System.Reflection.BindingFlags.Public)");
        Assert.NotEmpty(violations);
    }

    [Fact]
    public void ValidateTrustModel_Sockets_Forbidden()
    {
        var violations = _service.ValidateTrustModel(
            "new System.Net.Sockets.TcpClient()");
        Assert.NotEmpty(violations);
    }

    [Fact]
    public void ValidateTrustModel_HttpClient_Forbidden()
    {
        var violations = _service.ValidateTrustModel(
            "new System.Net.Http.HttpClient()");
        Assert.NotEmpty(violations);
    }

    [Fact]
    public void ValidateTrustModel_AsyncAwait_Allowed()
    {
        // System.Threading.Tasks should be allowed (async/await support)
        var violations = _service.ValidateTrustModel(
            "await System.Threading.Tasks.Task.Delay(100)");
        Assert.Empty(violations);
    }

    [Fact]
    public void ValidateTrustModel_CancellationToken_Allowed()
    {
        var violations = _service.ValidateTrustModel(
            "System.Threading.CancellationToken.None");
        Assert.Empty(violations);
    }

    [Fact]
    public void ValidateTrustModel_CleanCode_NoViolations()
    {
        var code = @"
            var x = 1 + 2;
            var list = new List<int> { 1, 2, 3 };
            var sum = list.Sum();
            sum";
        var violations = _service.ValidateTrustModel(code);
        Assert.Empty(violations);
    }

    [Fact]
    public void Compile_ForbiddenApi_FailsValidation()
    {
        var result = _service.Compile("evil", "System.IO.File.Delete(\"/tmp/test\")");
        Assert.False(result.IsSuccess);
        Assert.NotEmpty(result.Errors);
    }
}
