using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;
using MemoryPack;

namespace Phantom.Common.Data.Agent;

[MemoryPackable(GenerateType.VersionTolerant)]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
public sealed partial class AuthToken {
	internal const int Length = 12;

	[MemoryPackOrder(0)]
	[MemoryPackInclude]
	private readonly byte[] bytes;

	internal AuthToken(byte[]? bytes) {
		if (bytes == null) {
			throw new ArgumentNullException(nameof(bytes));
		}

		if (bytes.Length != Length) {
			throw new ArgumentOutOfRangeException(nameof(bytes), "Invalid token length: " + bytes.Length + ". Token length must be exactly " + Length + " bytes.");
		}

		this.bytes = bytes;
	}

	public bool FixedTimeEquals(AuthToken providedAuthToken) {
		return CryptographicOperations.FixedTimeEquals(bytes, providedAuthToken.bytes);
	}

	internal void WriteTo(Span<byte> span) {
		bytes.CopyTo(span);
	}

	public static AuthToken Generate() {
		return new AuthToken(RandomNumberGenerator.GetBytes(Length));
	}
}