using System.Text;
using NATS.Server.JetStream.Storage;

namespace NATS.Server.Tests;

public class JetStreamFileStoreCompressionEncryptionParityTests
{
    [Fact]
    public async Task Compression_and_encryption_roundtrip_is_versioned_and_detects_wrong_key_corruption()
    {
        var dir = Path.Combine(Path.GetTempPath(), $"nats-js-fs-crypto-{Guid.NewGuid():N}");
        var options = new FileStoreOptions
        {
            Directory = dir,
            EnableCompression = true,
            EnableEncryption = true,
            EncryptionKey = [1, 2, 3, 4],
        };

        try
        {
            ulong sequence;
            await using (var store = new FileStore(options))
            {
                sequence = await store.AppendAsync("orders.created", Encoding.UTF8.GetBytes("payload"), default);
                var loaded = await store.LoadAsync(sequence, default);
                loaded.ShouldNotBeNull();
                Encoding.UTF8.GetString(loaded.Payload.ToArray()).ShouldBe("payload");
            }

            // Block-based storage: read the .blk file to verify FSV1 envelope.
            var blkFiles = Directory.GetFiles(dir, "*.blk");
            blkFiles.Length.ShouldBeGreaterThan(0);

            // Read the first record from the block file and verify FSV1 magic in payload.
            var blkBytes = File.ReadAllBytes(blkFiles[0]);
            var record = MessageRecord.Decode(blkBytes.AsSpan(0, MessageRecord.MeasureRecord(blkBytes)));
            var persisted = record.Payload.ToArray();
            persisted.Take(4).SequenceEqual("FSV1"u8.ToArray()).ShouldBeTrue();

            Should.Throw<InvalidDataException>(() =>
            {
                _ = new FileStore(new FileStoreOptions
                {
                    Directory = dir,
                    EnableCompression = true,
                    EnableEncryption = true,
                    EncryptionKey = [9, 9, 9, 9],
                });
            });
        }
        finally
        {
            if (Directory.Exists(dir))
                Directory.Delete(dir, recursive: true);
        }
    }
}
