using System.Text;
using Metin2Launcher.Manifest;
using NSec.Cryptography;
using Xunit;

namespace Metin2Launcher.Tests;

public class SignatureVerifierTests
{
    private static (byte[] pub, byte[] sig, byte[] msg) MakeSignedMessage(string text)
    {
        var algo = SignatureAlgorithm.Ed25519;
        using var key = Key.Create(algo, new KeyCreationParameters
        {
            ExportPolicy = KeyExportPolicies.AllowPlaintextExport,
        });
        var pub = key.PublicKey.Export(KeyBlobFormat.RawPublicKey);
        var msg = Encoding.UTF8.GetBytes(text);
        var sig = algo.Sign(key, msg);
        return (pub, sig, msg);
    }

    [Fact]
    public void Verify_returns_true_for_valid_signature()
    {
        var (pub, sig, msg) = MakeSignedMessage("hello metin2");
        Assert.True(SignatureVerifier.Verify(msg, sig, pub));
        Assert.True(SignatureVerifier.Verify(msg, sig, Convert.ToHexString(pub)));
    }

    [Fact]
    public void Verify_returns_false_for_tampered_message()
    {
        var (pub, sig, msg) = MakeSignedMessage("hello metin2");
        msg[0] ^= 0x01;
        Assert.False(SignatureVerifier.Verify(msg, sig, pub));
    }

    [Fact]
    public void Verify_returns_false_for_tampered_signature()
    {
        var (pub, sig, msg) = MakeSignedMessage("hello metin2");
        sig[0] ^= 0x01;
        Assert.False(SignatureVerifier.Verify(msg, sig, pub));
    }

    [Fact]
    public void Verify_returns_false_for_wrong_public_key()
    {
        var (_, sig, msg) = MakeSignedMessage("hello metin2");
        var algo = SignatureAlgorithm.Ed25519;
        using var other = Key.Create(algo, new KeyCreationParameters
        {
            ExportPolicy = KeyExportPolicies.AllowPlaintextExport,
        });
        var wrongPub = other.PublicKey.Export(KeyBlobFormat.RawPublicKey);
        Assert.False(SignatureVerifier.Verify(msg, sig, wrongPub));
    }

    [Fact]
    public void Verify_returns_false_for_malformed_hex_key()
    {
        var (_, sig, msg) = MakeSignedMessage("hello");
        Assert.False(SignatureVerifier.Verify(msg, sig, "not-hex"));
        Assert.False(SignatureVerifier.Verify(msg, sig, ""));
    }

    [Fact]
    public void Verify_returns_false_for_wrong_key_length()
    {
        var (_, sig, msg) = MakeSignedMessage("hello");
        Assert.False(SignatureVerifier.Verify(msg, sig, new byte[16]));
    }
}
