import {
	CreateOauthConnectionPayload,
	IntegrationRecord,
} from '@event-inc/types';
import { OauthConnection } from '../oauthconnection';
import {
	makeHttpNetworkCall,
	matchResultAndHandleHttpError,
} from '@event-inc/utils';
import { identity } from 'ramda';
import { version1 } from './configs.apis';

export const createOauthConnectionApi = async (
	headers: Record<string, string>,
	url: string,
	payload: CreateOauthConnectionPayload
) => {
	const { type, config } = payload;

	const { clientId, clientSecret, code, redirectUri } = config;

	const oauthConnection = new OauthConnection({
		OAUTH_APP_CLIENT_ID: clientId,
		OAUTH_APP_CLIENT_SECRET: clientSecret,
		type,
	});

	const oauthDetails = oauthConnection.getOauthDetails();

	// Get the access token and refresh token
	const response = await makeHttpNetworkCall({
		method: 'POST',
		url: oauthDetails.endpoint,
		headers: oauthDetails.headers,
		data: {
			grant_type: 'authorization_code',
			code: code,
			redirect_uri: redirectUri,
		},
	});

	const { data } = matchResultAndHandleHttpError(response, identity);

	const { access_token: accessToken, refresh_token: refreshToken } = data as {
		access_token: string;
		refresh_token: string;
	};

	// Create the source integration
	const sourceIntegration = await makeHttpNetworkCall<IntegrationRecord>({
		method: 'POST',
		url: `${url}/${version1}/integrations/create`,
		headers,
		data: {
			integrationDefinitionId: oauthDetails.sourceIntegrationDefinitionId,
			name: payload.label,
			group: payload.group,
			authFormData: {
				name: payload.label,
				...oauthConnection.getOauthFormData({ accessToken, refreshToken }),
			},
		},
	});

	const { data: source } = matchResultAndHandleHttpError(
		sourceIntegration,
		identity
	);

	// Create the destination integration
	const destinationIntegration = await makeHttpNetworkCall<IntegrationRecord>({
		method: 'POST',
		url: `${url}/${version1}/integrations/create`,
		headers,
		data: {
			connectionBundleId: source?.connectionBundleId,
			integrationDefinitionId: oauthDetails.destinationIntegrationDefinitionId,
			name: payload.label,
			group: payload.group,
			authFormData: {
				name: payload.label,
				...oauthConnection.getOauthFormData({ accessToken, refreshToken }),
			},
		},
	});

	const { data: destination } = matchResultAndHandleHttpError(
		destinationIntegration,
		identity
	);

	return { source, destination };
};

export const createOauthSourceApi = async (
	headers: Record<string, string>,
	url: string,
	payload: CreateOauthConnectionPayload
) => {
	const { type, config } = payload;

	const { clientId, clientSecret, code, redirectUri } = config;

	const oauthConnection = new OauthConnection({
		OAUTH_APP_CLIENT_ID: clientId,
		OAUTH_APP_CLIENT_SECRET: clientSecret,
		type,
	});

	const oauthDetails = oauthConnection.getOauthDetails();

	// Get the access token and refresh token
	const response = await makeHttpNetworkCall({
		method: 'POST',
		url: oauthDetails.endpoint,
		headers: oauthDetails.headers,
		data: {
			grant_type: 'authorization_code',
			code: code,
			redirect_uri: redirectUri,
		},
	});

	const { data } = matchResultAndHandleHttpError(response, identity);

	const { access_token: accessToken, refresh_token: refreshToken } = data as {
		access_token: string;
		refresh_token: string;
	};

	// Create the source integration
	return makeHttpNetworkCall<IntegrationRecord>({
		method: 'POST',
		url: `${url}/${version1}/integrations/create`,
		headers,
		data: {
			integrationDefinitionId: oauthDetails.sourceIntegrationDefinitionId,
			name: payload.label,
			group: payload.group,
			authFormData: {
				name: payload.label,
				...oauthConnection.getOauthFormData({ accessToken, refreshToken }),
			},
		},
	});
};

export const createOauthDestinationApi = async (
	headers: Record<string, string>,
	url: string,
	payload: CreateOauthConnectionPayload
) => {
	const { type, config } = payload;

	const { clientId, clientSecret, code, redirectUri } = config;

	const oauthConnection = new OauthConnection({
		OAUTH_APP_CLIENT_ID: clientId,
		OAUTH_APP_CLIENT_SECRET: clientSecret,
		type,
	});

	const oauthDetails = oauthConnection.getOauthDetails();

	// Get the access token and refresh token
	const response = await makeHttpNetworkCall({
		method: 'POST',
		url: oauthDetails.endpoint,
		headers: oauthDetails.headers,
		data: {
			grant_type: 'authorization_code',
			code: code,
			redirect_uri: redirectUri,
		},
	});

	const { data } = matchResultAndHandleHttpError(response, identity);

	const { access_token: accessToken, refresh_token: refreshToken } = data as {
		access_token: string;
		refresh_token: string;
	};

	// Create the destination integration
	return makeHttpNetworkCall<IntegrationRecord>({
		method: 'POST',
		url: `${url}/${version1}/integrations/create`,
		headers,
		data: {
			integrationDefinitionId: oauthDetails.destinationIntegrationDefinitionId,
			name: payload.label,
			group: payload.group,
			authFormData: {
				name: payload.label,
				...oauthConnection.getOauthFormData({ accessToken, refreshToken }),
			},
		},
	});
};

