using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.AdminUI.ScriptAnalysis;

namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.ScriptAnalysis;

public sealed class TagPathCompletionTests
{
    private sealed class FakeCatalog : IScriptTagCatalog
    {
        public Task<IReadOnlyList<string>> GetPathsAsync(string? filter, CancellationToken ct)
            => Task.FromResult<IReadOnlyList<string>>(new[] { "Motor.Speed", "Motor.Temp" });

        public Task<ScriptTagInfo?> GetTagInfoAsync(string path, CancellationToken ct)
            => Task.FromResult<ScriptTagInfo?>(null);

        public Task<IReadOnlyList<string>> GetEquipmentReferenceNamesAsync(string equipmentId, string? filter, CancellationToken ct)
            => Task.FromResult<IReadOnlyList<string>>(new[] { "Speed", "Temp" });
    }

    private static readonly ScriptAnalysisService Svc = new(new FakeCatalog());

    private static async Task<IReadOnlyList<string>> Labels(string code, int line, int col)
        => (await Svc.CompleteAsync(new CompletionsRequest(code, line, col))).Items.Select(i => i.Label).ToList();

    [Fact] public async Task Empty_literal_in_GetTag_offers_tag_paths()
    {
        // caret between the quotes of ctx.GetTag("") — verify/adjust the column so the caret is inside the literal.
        (await Labels("""ctx.GetTag("")""", 1, 13)).ShouldContain("Motor.Speed");
    }

    [Fact] public async Task Partial_literal_in_GetTag_offers_tag_paths()
    {
        (await Labels("""ctx.GetTag("Mot")""", 1, 15)).ShouldContain("Motor.Speed");
    }

    [Fact] public async Task SetVirtualTag_literal_also_offers_tag_paths()
    {
        (await Labels("""ctx.SetVirtualTag("")""", 1, 20)).ShouldContain("Motor.Speed");
    }

    [Fact] public async Task Outside_a_tag_literal_does_not_offer_tag_paths()
    {
        // a string literal NOT inside GetTag/SetVirtualTag → no tag-path suggestions
        (await Labels("""var s = "";""", 1, 10)).ShouldNotContain("Motor.Speed");
    }
}
