/*
 * Copyright (c) 2026, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 LLC. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.wso2.micro.integrator.security.handler.oauth;

public class OAuthConstants {

    public static final String JWT_OAUTH_CONFIG = "rest_api.jwt_security_handler.";
    public static final String CACHE_EXPIRY = JWT_OAUTH_CONFIG + "cache_expiry";
    public static final String MAX_ISSUED_AT_AGE_SECONDS = JWT_OAUTH_CONFIG + "max_issued_at_age_seconds";
    public static final String CLOCK_SKEW_SECONDS = JWT_OAUTH_CONFIG + "clock_skew_seconds";
    public static final String TRUSTED_ISSUERS = JWT_OAUTH_CONFIG + "trusted_issuers";
    public static final String EXPECTED_AUDIENCE = JWT_OAUTH_CONFIG + "audience";
    public static final String ALLOWED_ALGORITHMS = JWT_OAUTH_CONFIG + "allowed_algorithms";
    public static final String TOKEN_MAX_LEN = JWT_OAUTH_CONFIG + "log_masking.token_max_len";
    public static final String TOKEN_MAX_VISIBLE_LEN = JWT_OAUTH_CONFIG + "log_masking.token_max_visible_len";
    public static final String TOKEN_MIN_VISIBLE_LEN_RATIO = JWT_OAUTH_CONFIG + "log_masking.token_min_visible_len_ratio";
    public static final String TOKEN_MASK_CHAR = JWT_OAUTH_CONFIG + "log_masking.token_mask_char";

    public static final String BEARER = "Bearer";
    public static final String DOT = ".";
    public static final String CONSUMER_KEY_SEGMENT_DELIMITER = " ";
    public static final String DESCRIPTION_SEPARATOR = ". ";
    public static final String SCOPE = "scope";
    public static final String SCOPE_DELIMITER = " ";
    public static final String OAUTH2_DEFAULT_SCOPE = "default";
    public static final String MEDIA_TYPE_JWT_ACCESS_TOKEN = "application/at+jwt";
    public static final String JWT_TYPE_AT_JWT = "at+jwt";
    public static final String ALL_AUDIENCES = "all";

    public static final String SCOPES = "Scopes";
    public static final String JWT_CLAIMS = "jwt_token_claims";

    public static final String DIGEST = "x5t#S256";
    public static final String CNF = "cnf";

    public static final String OAUTH_GLOBAL_CONNECTION_TIMEOUT = "http.client.global.connection.timeout";
    public static final String OAUTH_GLOBAL_CONNECTION_REQUEST_TIMEOUT = "http.client.global.connection.request.timeout";
    public static final String OAUTH_GLOBAL_SOCKET_TIMEOUT = "http.client.global.socket.timeout";
    public static final String OAUTH_GLOBAL_PROXY_ENABLED = "http.client.global.proxy.enabled";
    public static final String OAUTH_GLOBAL_PROXY_HOST = "http.client.global.proxy.host";
    public static final String OAUTH_GLOBAL_PROXY_PORT = "http.client.global.proxy.port";
    public static final String OAUTH_GLOBAL_PROXY_USERNAME = "http.client.global.proxy.username";
    public static final String OAUTH_GLOBAL_PROXY_PASSWORD = "http.client.global.proxy.password";
    public static final String OAUTH_GLOBAL_PROXY_PROTOCOL = "http.client.global.proxy.protocol";

    public static final String BASE64_ENCODED_CLIENT_CERTIFICATE_HEADER = "X-WSO2-CLIENT-CERTIFICATE";

    public static final long DEFAULT_TIMESTAMP_SKEW_IN_SECONDS = 300L;

    public static final int API_AUTH_GENERAL_ERROR       = 900900;
    public static final String API_AUTH_GENERAL_ERROR_MESSAGE = "Unclassified Authentication Failure";

    public static final int API_AUTH_INVALID_CREDENTIALS = 900901;

    public static final String SIGNATURE_VERIFICATION_FAILURE_MESSAGE =
            "Invalid JWT token. Signature verification failed.";

    public static final String API_AUTH_INVALID_CREDENTIALS_MESSAGE = "Invalid Credentials";
    public static final String API_AUTH_INVALID_CREDENTIALS_DESCRIPTION =
            "Make sure you have provided the correct security credentials";

    public static final int API_AUTH_MISSING_CREDENTIALS = 900902;
    public static final String API_AUTH_MISSING_CREDENTIALS_MESSAGE = "Missing Credentials";
    public static final String API_AUTH_MISSING_CREDENTIALS_DESCRIPTION =
            "Make sure your API invocation call has a header: ";

    public static final int API_AUTH_ACCESS_TOKEN_EXPIRED = 900903;
    public static final String API_AUTH_ACCESS_TOKEN_EXPIRED_MESSAGE = "Access Token Expired";
    public static final String API_AUTH_ACCESS_TOKEN_EXPIRED_DESCRIPTION =
            "Renew the access token and try again";

    public static final int API_AUTH_ACCESS_TOKEN_INACTIVE = 900904;
    public static final String API_AUTH_ACCESS_TOKEN_INACTIVE_MESSAGE = "Access Token Inactive";
    public static final String API_AUTH_ACCESS_TOKEN_INACTIVE_DESCRIPTION =
            "Generate a new access token and try again";

    public static final int API_AUTH_INCORRECT_ACCESS_TOKEN_TYPE = 900905;
    public static final String API_AUTH_INCORRECT_ACCESS_TOKEN_TYPE_MESSAGE = "Incorrect Access Token Type is provided";

    public static final int API_AUTH_INCORRECT_API_RESOURCE = 900906;
    public static final String API_AUTH_INCORRECT_API_RESOURCE_MESSAGE = "No matching resource found in the API for the given request";
    public static final String API_AUTH_INCORRECT_API_RESOURCE_DESCRIPTION =
            "Check the API documentation and add a proper REST resource path to the invocation URL";

    public static final int API_BLOCKED = 900907;
    public static final String API_BLOCKED_MESSAGE = "The requested API is temporarily blocked";

    public static final int API_AUTH_FORBIDDEN = 900908;
    public static final String API_AUTH_FORBIDDEN_MESSAGE = "Resource forbidden ";

    public static final int SUBSCRIPTION_INACTIVE = 900909;
    public static final String SUBSCRIPTION_INACTIVE_MESSAGE = "The subscription to the API is inactive";

    public static final int INVALID_SCOPE = 900910;
    public static final String INVALID_SCOPE_MESSAGE = "The access token does not allow you to access the requested resource";

    public static final int API_AUTH_MISSING_OPEN_API_DEF = 900911;
    public static final String API_AUTH_MISSING_OPEN_API_DEF_ERROR_MESSAGE = "Internal Server Error";

    public static final int API_AUTH_ACCESS_TOKEN_CLAIMS_MISMATCH = 900912;
    public static final String API_AUTH_ACCESS_TOKEN_CLAIMS_MISMATCH_MESSAGE = "Claim Mismatch";
    public static final String API_AUTH_ACCESS_TOKEN_CLAIMS_MISMATCH_DESCRIPTION =
            "The claim configured in the system and the claim provided in the token do not align. Please ensure the claims match.";

    public static final int API_AUTH_ACCESS_TOKEN_CLAIMS_INVALID = 900913;
    public static final String API_AUTH_ACCESS_TOKEN_CLAIMS_INVALID_MESSAGE = "Claim Invalid";
    public static final String API_AUTH_ACCESS_TOKEN_CLAIMS_INVALID_DESCRIPTION =
            "The configured resource access validation claim is not present in the token.";

    public static final int API_OAUTH_INVALID_AUDIENCES = 900914;
    public static final String API_OAUTH_INVALID_AUDIENCES_MESSAGE = "Access Denied";
    public static final String API_OAUTH_INVALID_AUDIENCES_DESCRIPTION = "The access token does not allow you to access the requested resource";

    /**
     * returns a String that corresponds to errorCode passed in
     *
     * @param errorCode
     * @return String
     */
    public static final String getAuthenticationFailureMessage(int errorCode) {
        String errorMessage;
        switch (errorCode) {
            case API_AUTH_ACCESS_TOKEN_EXPIRED:
                errorMessage = API_AUTH_ACCESS_TOKEN_EXPIRED_MESSAGE;
                break;
            case API_AUTH_ACCESS_TOKEN_INACTIVE:
                errorMessage = API_AUTH_ACCESS_TOKEN_INACTIVE_MESSAGE;
                break;
            case API_AUTH_GENERAL_ERROR:
                errorMessage = API_AUTH_GENERAL_ERROR_MESSAGE;
                break;
            case API_AUTH_MISSING_OPEN_API_DEF:
                errorMessage = API_AUTH_MISSING_OPEN_API_DEF_ERROR_MESSAGE;
                break;
            case API_AUTH_INVALID_CREDENTIALS:
                errorMessage = API_AUTH_INVALID_CREDENTIALS_MESSAGE;
                break;
            case API_AUTH_MISSING_CREDENTIALS:
                errorMessage = API_AUTH_MISSING_CREDENTIALS_MESSAGE;
                break;
            case API_AUTH_INCORRECT_API_RESOURCE:
                errorMessage = API_AUTH_INCORRECT_API_RESOURCE_MESSAGE;
                break;
            case API_AUTH_INCORRECT_ACCESS_TOKEN_TYPE:
                errorMessage = API_AUTH_INCORRECT_ACCESS_TOKEN_TYPE_MESSAGE;
                break;
            case API_OAUTH_INVALID_AUDIENCES:
                errorMessage = API_OAUTH_INVALID_AUDIENCES_MESSAGE;
                break;
            case API_BLOCKED:
                errorMessage = API_BLOCKED_MESSAGE;
                break;
            case API_AUTH_FORBIDDEN:
                errorMessage = API_AUTH_FORBIDDEN_MESSAGE;
                break;
            case SUBSCRIPTION_INACTIVE:
                errorMessage = SUBSCRIPTION_INACTIVE_MESSAGE;
                break;
            case INVALID_SCOPE:
                errorMessage = INVALID_SCOPE_MESSAGE;
                break;
            case API_AUTH_ACCESS_TOKEN_CLAIMS_MISMATCH:
                errorMessage = API_AUTH_ACCESS_TOKEN_CLAIMS_MISMATCH_MESSAGE;
                break;
            case API_AUTH_ACCESS_TOKEN_CLAIMS_INVALID:
                errorMessage = API_AUTH_ACCESS_TOKEN_CLAIMS_INVALID_MESSAGE;
                break;
            default:
                errorMessage = API_AUTH_GENERAL_ERROR_MESSAGE;
                break;
        }
        return errorMessage;
    }

    /**
     * This method is used to get an additional description for error message details.
     *
     * @param errorCode    The error code that is embedded in the exception
     * @param errorMessage The default error message of the exception
     * @return The error description including the original error message and some additional information
     */
    public static String getFailureMessageDetailDescription(int errorCode, String errorMessage){
        String errorDescription = errorMessage;
        switch (errorCode){
            case API_AUTH_INCORRECT_API_RESOURCE:
                errorDescription += DESCRIPTION_SEPARATOR + API_AUTH_INCORRECT_API_RESOURCE_DESCRIPTION;
                break;
            case API_AUTH_ACCESS_TOKEN_INACTIVE:
                errorDescription += DESCRIPTION_SEPARATOR + API_AUTH_ACCESS_TOKEN_INACTIVE_DESCRIPTION;
                break;
            case API_AUTH_MISSING_CREDENTIALS:
                errorDescription += DESCRIPTION_SEPARATOR + API_AUTH_MISSING_CREDENTIALS_DESCRIPTION;
                break;
            case API_AUTH_ACCESS_TOKEN_EXPIRED:
                errorDescription += DESCRIPTION_SEPARATOR + API_AUTH_ACCESS_TOKEN_EXPIRED_DESCRIPTION;
                break;
            case API_AUTH_INVALID_CREDENTIALS:
                errorDescription += DESCRIPTION_SEPARATOR + API_AUTH_INVALID_CREDENTIALS_DESCRIPTION;
                break;
            case API_AUTH_ACCESS_TOKEN_CLAIMS_MISMATCH:
                errorDescription += DESCRIPTION_SEPARATOR + API_AUTH_ACCESS_TOKEN_CLAIMS_MISMATCH_DESCRIPTION;
                break;
            case API_AUTH_ACCESS_TOKEN_CLAIMS_INVALID:
                errorDescription += DESCRIPTION_SEPARATOR + API_AUTH_ACCESS_TOKEN_CLAIMS_INVALID_DESCRIPTION;
                break;
            case API_OAUTH_INVALID_AUDIENCES:
                errorDescription += DESCRIPTION_SEPARATOR + API_OAUTH_INVALID_AUDIENCES_DESCRIPTION;
                break;
            default:
                // Do nothing since we are anyhow returning the original error description.
        }
        return errorDescription;
    }

    public static final String BEGIN_CERTIFICATE_STRING = "-----BEGIN CERTIFICATE-----";
    public static final String END_CERTIFICATE_STRING = "-----END CERTIFICATE-----";

}
