using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Testing;
using Microsoft.CodeAnalysis.Testing;
using NUnit.Framework;
using VerifyCS =
    Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier<Robust.Analyzers.PrototypeAnalyzer, Microsoft.CodeAnalysis.Testing.DefaultVerifier>;


namespace Robust.Analyzers.Tests;

public sealed class PrototypeFixerTest
{
    private static Task Verifier(string code, string fixedCode, params DiagnosticResult[] expected)
    {
        var test = new CSharpCodeFixTest<PrototypeAnalyzer, PrototypeFixer, DefaultVerifier>()
        {
            TestState =
            {
                Sources = { code },
            },
            FixedState =
            {
                Sources = { fixedCode },
            }
        };

        test.TestState.Sources.Add(("PrototypeAttribute.cs", PrototypeAttributeDef));
        test.FixedState.Sources.Add(("PrototypeAttribute.cs", PrototypeAttributeDef));

        test.TestState.ExpectedDiagnostics.AddRange(expected);

        return test.RunAsync();
    }

    private const string PrototypeAttributeDef = """
        using System;

        namespace Robust.Shared.Prototypes
        {
            public class PrototypeAttribute : Attribute
            {
                public string? Type { get; internal set; }
                public readonly int LoadPriority = 1;

                public PrototypeAttribute(string? type = null, int loadPriority = 1)
                {
                    Type = type;
                    LoadPriority = loadPriority;
                }

                public PrototypeAttribute(int loadPriority)
                {
                    Type = null;
                    LoadPriority = loadPriority;
                }
            }
            public interface IPrototype;
        }
    """;

    [Test]
    public async Task Test()
    {
        const string code = """
            using Robust.Shared.Prototypes;

            [Prototype]
            public sealed partial class GoodAutoPrototype : IPrototype;

            [Prototype("someOtherName")]
            public sealed partial class GoodUnmatchedPrototype : IPrototype;

            [Prototype("badMatched")]
            public sealed partial class BadMatchedPrototype : IPrototype;
            """;

        const string fixedCode = """
            using Robust.Shared.Prototypes;

            [Prototype]
            public sealed partial class GoodAutoPrototype : IPrototype;

            [Prototype("someOtherName")]
            public sealed partial class GoodUnmatchedPrototype : IPrototype;

            [Prototype]
            public sealed partial class BadMatchedPrototype : IPrototype;
            """;

        await Verifier(code, fixedCode,
            // /0/Test0.cs(9,2): warning RA0033: Prototype BadMatchedPrototype has explicitly set type "badMatched" that matches autogenerated value
            VerifyCS.Diagnostic(PrototypeAnalyzer.PrototypeRedundantTypeRule).WithSpan(9, 12, 9, 24).WithArguments("BadMatchedPrototype", "badMatched")
        );
    }
}
