using System.Threading;
using System.Threading.Tasks;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.AdminUI.ScriptAnalysis;

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

public sealed class CtxCompletionGuardTests
{
    private sealed class FakeCatalog : IScriptTagCatalog
    {
        public Task<IReadOnlyList<string>> GetPathsAsync(string? f, CancellationToken ct)
            => Task.FromResult<IReadOnlyList<string>>(new[] { "Line1.Speed" });
        public Task<ScriptTagInfo?> GetTagInfoAsync(string path, CancellationToken ct)
            => Task.FromResult<ScriptTagInfo?>(new ScriptTagInfo(path, "Virtual tag", "Double", null));
        public Task<IReadOnlyList<string>> GetEquipmentReferenceNamesAsync(string equipmentId, string? f, CancellationToken ct)
            => Task.FromResult<IReadOnlyList<string>>(System.Array.Empty<string>());
    }

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

    [Fact] public async Task Completion_on_ctx_GetTag_literal_offers_catalog_paths()
    {
        // "return ctx.GetTag(" + '""' + ')' — col 20 lands on the closing quote of the empty string literal.
        var res = await Svc.CompleteAsync(new CompletionsRequest("return ctx.GetTag(\"\")", 1, 20));
        res.Items.ShouldContain(i => i.InsertText == "Line1.Speed");
    }

    [Fact] public async Task Completion_on_non_ctx_receiver_does_NOT_offer_catalog_paths()
    {
        // Same shape but receiver is "foo" — must NOT offer catalog paths.
        var res = await Svc.CompleteAsync(new CompletionsRequest("return foo.GetTag(\"\")", 1, 20));
        res.Items.ShouldNotContain(i => i.InsertText == "Line1.Speed");
    }

    [Fact] public async Task Hover_on_ctx_SetVirtualTag_literal_warns_write_is_dropped()
    {
        var md = (await Svc.Hover(new HoverRequest("return ctx.SetVirtualTag(\"V\", 1);", 1, 27))).Markdown;
        md.ShouldNotBeNull();
        md!.ShouldContain("single-tag mode");
    }

    [Fact] public async Task Hover_on_ctx_GetTag_literal_has_no_dropped_write_note()
    {
        var md = (await Svc.Hover(new HoverRequest("return ctx.GetTag(\"V\").Value;", 1, 20))).Markdown;
        md.ShouldNotBeNull();
        md!.ShouldNotContain("single-tag mode");
    }

    [Fact] public async Task Hover_on_non_ctx_receiver_literal_is_not_treated_as_a_tag_path()
    {
        var md = (await Svc.Hover(new HoverRequest("return bar.GetTag(\"V\");", 1, 20))).Markdown;
        (md is null || !md.Contains("Tag path")).ShouldBeTrue();
    }
}
