/* eslint-disable max-len */
import { AuthSdkError } from '../../errors';
import { convertTokenParamsToOAuthParams } from './authorize';
import { httpRequest } from '../../http';

import { OktaAuthOAuthInterface, TokenParams } from '../types';

export interface PushedAuthorizationResponse {
	/**
	 * If `jwtAuthorizationRequest` is `true`, the endpoint should return the JWT to be used
	 * for the `client_assertion` value in the `/token` request.
	 */
	client_assertion?: string;
	expires_in: number;
	request_uri: string;
}

export interface PostToParEndpointResponse {
	requestUri: string;
	expiresAt: number;
}

export async function postToParEndpoint(sdk: OktaAuthOAuthInterface, tokenParams: TokenParams) {

	const { jwtAuthorizationRequest = false, pushAuthorizationUrl: url, extraParams, ...options } = tokenParams || {};

	const data = convertTokenParamsToOAuthParams(options);

	const headers = {
		'Content-Type': 'application/x-www-form-urlencoded',
	};

	if (!url) {
		throw new AuthSdkError(
			'In order to use push authorization request, a valid URL must be specified in the OktaAuth constructor that will generate the push authorization and return the appropriate response.'
		);
	}

	const now = Math.floor(Date.now() / 1000);

	const { client_assertion: clientAssertion, expires_in: expiresIn, request_uri: requestUri } = await httpRequest<PushedAuthorizationResponse>(sdk, {
		url,
		method: 'POST',
		args: {
			'jwt_authorization_request': jwtAuthorizationRequest,
			...extraParams,
			...data,
		},
		headers,
	});

	return { clientAssertion, expiresAt: expiresIn + now, requestUri };
}