using System.Reflection;
using NATS.Server.Configuration;

namespace NATS.Server.Core.Tests.Configuration;

public class ConfigPedanticParityBatch1Tests
{
    [Fact]
    public void ParseWithChecks_matches_parse_for_basic_input()
    {
        const string config = "port: 4222\nhost: 127.0.0.1\n";

        var regular = NatsConfParser.Parse(config);
        var withChecks = NatsConfParser.ParseWithChecks(config);

        withChecks["port"].ShouldBe(regular["port"]);
        withChecks["host"].ShouldBe(regular["host"]);
    }

    [Fact]
    public void ParseFileWithChecks_and_digest_wrappers_are_available_and_stable()
    {
        var path = Path.GetTempFileName();
        try
        {
            File.WriteAllText(path, "port: 4222\n");

            var parsed = NatsConfParser.ParseFileWithChecks(path);
            parsed["port"].ShouldBe(4222L);

            var (cfg1, d1) = NatsConfParser.ParseFileWithChecksDigest(path);
            var (cfg2, d2) = NatsConfParser.ParseFileWithDigest(path);
            var (_, d1Repeat) = NatsConfParser.ParseFileWithChecksDigest(path);

            cfg1["port"].ShouldBe(4222L);
            cfg2["port"].ShouldBe(4222L);
            d1.ShouldStartWith("sha256:");
            d2.ShouldStartWith("sha256:");
            d1.ShouldBe(d1Repeat);
            d1.ShouldNotBe(d2);
        }
        finally
        {
            File.Delete(path);
        }
    }

    [Fact]
    public void PedanticToken_accessors_match_expected_values()
    {
        var token = new Token(TokenType.Integer, "42", 3, 7);
        var pedantic = new PedanticToken(token, value: 42L, usedVariable: true, sourceFile: "test.conf");

        pedantic.Value().ShouldBe(42L);
        pedantic.Line().ShouldBe(3);
        pedantic.Position().ShouldBe(7);
        pedantic.IsUsedVariable().ShouldBeTrue();
        pedantic.SourceFile().ShouldBe("test.conf");
        pedantic.MarshalJson().ShouldBe("42");
    }

    [Fact]
    public void Parser_exposes_pedantic_compatibility_hooks()
    {
        var parserType = typeof(NatsConfParser);
        parserType.GetMethod("CleanupUsedEnvVars", BindingFlags.NonPublic | BindingFlags.Static).ShouldNotBeNull();

        var parserStateType = parserType.GetNestedType("ParserState", BindingFlags.NonPublic);
        parserStateType.ShouldNotBeNull();
        parserStateType!.GetMethod("PushItemKey", BindingFlags.NonPublic | BindingFlags.Instance).ShouldNotBeNull();
        parserStateType.GetMethod("PopItemKey", BindingFlags.NonPublic | BindingFlags.Instance).ShouldNotBeNull();
    }

    [Fact]
    public void Bcrypt_prefix_values_are_preserved_for_2a_and_2b()
    {
        var parsed2a = NatsConfParser.Parse("pwd: $2a$abc\n");
        var parsed2b = NatsConfParser.Parse("pwd: $2b$abc\n");

        parsed2a["pwd"].ShouldBe("$2a$abc");
        parsed2b["pwd"].ShouldBe("$2b$abc");
    }
}
