namespace ZB.MOM.WW.Auth.ApiKeys;

internal sealed record ParsedApiKey(string KeyId, string Secret);

internal static class ApiKeyParser
{
    private const string BearerPrefix = "Bearer ";

    /// <summary>
    /// Attempts to parse an Authorization header value or a raw token into a <see cref="ParsedApiKey"/>.
    /// Accepts an optional case-insensitive "Bearer " scheme prefix before the token.
    /// Token format: <c>&lt;tokenPrefix&gt;_&lt;keyId&gt;_&lt;secret&gt;</c>.
    /// The secret may itself contain underscores; only the first underscore after the key-id is used as
    /// the key-id/secret separator.
    /// </summary>
    /// <param name="authorizationHeaderOrToken">Authorization header value or raw token string.</param>
    /// <param name="tokenPrefix">Expected token prefix (e.g. "mxgw"), without trailing underscore.</param>
    /// <returns>A <see cref="ParsedApiKey"/> on success, or <c>null</c> if the input is malformed.</returns>
    public static ParsedApiKey? TryParse(string? authorizationHeaderOrToken, string tokenPrefix)
    {
        if (string.IsNullOrWhiteSpace(authorizationHeaderOrToken))
            return null;

        string token = authorizationHeaderOrToken;

        // Strip optional "Bearer " prefix (case-insensitive).
        if (token.StartsWith(BearerPrefix, StringComparison.OrdinalIgnoreCase))
            token = token[BearerPrefix.Length..].Trim();

        // Token must start with "<prefix>_"
        string requiredPrefix = tokenPrefix + "_";
        if (!token.StartsWith(requiredPrefix, StringComparison.OrdinalIgnoreCase))
            return null;

        // Everything after "<prefix>_" is "<keyId>_<secret>"
        string keyPayload = token[requiredPrefix.Length..];

        int separatorIndex = keyPayload.IndexOf('_', StringComparison.Ordinal);

        // separatorIndex <= 0 means no underscore or empty keyId
        // separatorIndex == keyPayload.Length - 1 means empty secret
        if (separatorIndex <= 0 || separatorIndex == keyPayload.Length - 1)
            return null;

        string keyId = keyPayload[..separatorIndex];
        string secret = keyPayload[(separatorIndex + 1)..];

        if (string.IsNullOrWhiteSpace(keyId) || string.IsNullOrWhiteSpace(secret))
            return null;

        return new ParsedApiKey(keyId, secret);
    }
}
