using LibApiKeyIdentity = ZB.MOM.WW.Auth.Abstractions.ApiKeys.ApiKeyIdentity;

namespace ZB.MOM.WW.MxGateway.Server.Security.Authentication;

/// <summary>
/// Maps the shared <see cref="ZB.MOM.WW.Auth.Abstractions.ApiKeys.ApiKeyIdentity"/> (which
/// carries the key's scopes plus the opaque constraints JSON blob) onto the gateway's
/// <see cref="ApiKeyIdentity"/> (which exposes the deserialized
/// <see cref="ApiKeyConstraints"/> the downstream authorization code enforces).
/// </summary>
/// <remarks>
/// The shared verifier does not interpret the constraints column; it returns the stored
/// JSON verbatim in <see cref="ZB.MOM.WW.Auth.Abstractions.ApiKeys.ApiKeyIdentity.Constraints"/>.
/// This mapper re-hydrates it via <see cref="ApiKeyConstraintSerializer"/> so the gateway's
/// constraint enforcement (<c>ConstraintEnforcer</c>) and request-identity accessor continue
/// to operate on the strongly-typed model unchanged.
/// </remarks>
public static class GatewayApiKeyIdentityMapper
{
    /// <summary>
    /// Converts a shared API-key identity into the gateway identity, deserializing the opaque
    /// constraints JSON into <see cref="ApiKeyConstraints"/>.
    /// </summary>
    /// <param name="identity">The shared identity returned by the library verifier.</param>
    /// <returns>The gateway identity carrying the effective constraints.</returns>
    public static ApiKeyIdentity ToGatewayIdentity(LibApiKeyIdentity identity)
    {
        ArgumentNullException.ThrowIfNull(identity);

        // The library stores the opaque constraints blob in Constraints as the ConstraintsJson
        // string (or null when the key has no constraints).
        string? constraintsJson = identity.Constraints as string;

        return new ApiKeyIdentity(
            KeyId: identity.KeyId,
            // The gateway token prefix is fixed ("mxgw"); the key id is its own field. KeyPrefix
            // is retained only for surface compatibility with the gateway identity record.
            KeyPrefix: "mxgw",
            DisplayName: identity.DisplayName,
            Scopes: identity.Scopes,
            Constraints: ApiKeyConstraintSerializer.Deserialize(constraintsJson));
    }
}
