Current File : //home/abedqjib/krishanfoundation.com/wp-content/plugins/surerank/src/functions/api.js
import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';
import { TERM_SEO_DATA_URL, POST_SEO_DATA_URL } from '@Global/constants/api';
import { isCurrentPage } from '@/functions/utils';

export const API_BASE_URL = '/surerank/v1';

export const fetchMetaSettings = async () => {
	const queryParams = {};
	const isTerm =
		isCurrentPage( 'term.php' ) || !! surerank_seo_popup.is_taxonomy;
	if ( isTerm ) {
		queryParams.term_id = surerank_seo_popup?.term_id;
	} else {
		queryParams.post_id = surerank_seo_popup?.post_id;
	}
	queryParams.post_type = surerank_seo_popup?.post_type;
	queryParams.is_taxonomy = surerank_seo_popup?.is_taxonomy;

	try {
		const response = await apiFetch( {
			path: addQueryArgs(
				isTerm ? TERM_SEO_DATA_URL : POST_SEO_DATA_URL,
				queryParams
			),
			method: 'GET',
		} );
		if ( ! response.success ) {
			throw new Error( response.message );
		}
		return response;
	} catch ( error ) {
		throw new Error( error.message );
	}
};

/**
 * Fetch image data by URL.
 *
 * @param {string} imageUrl The URL of the image to fetch.
 * @return {Promise} A promise that resolves to the image data.
 */
export const fetchImageDataByUrl = async ( imageUrl ) => {
	if ( ! imageUrl ) {
		return null;
	}

	// Extract filename variations for better search
	const url = new URL( imageUrl );
	const pathname = url.pathname;
	const filename = pathname.split( '/' ).pop().split( '?' )[ 0 ];

	// Remove common optimization suffixes (webp, scaled, etc.)
	const baseFilename = filename
		.replace( /-\d+x\d+\.(jpg|jpeg|png|gif|webp)$/i, '' ) // Remove dimension suffixes
		.replace( /-scaled\.(jpg|jpeg|png|gif|webp)$/i, '' ) // Remove -scaled suffix
		.replace( /\.(webp)$/i, '' ) // Remove .webp extension
		.replace( /(-optimized|-compressed)/i, '' ); // Remove optimization keywords

	// Try multiple search strategies
	const searchStrategies = [
		// 1. Search by exact filename
		{ search: filename },
		// 2. Search by base filename without optimization suffixes
		{ search: baseFilename },
		// 3. Search by filename without extension
		{ search: filename.replace( /\.[^/.]+$/, '' ) },
		// 4. Search by base filename without extension
		{ search: baseFilename.replace( /\.[^/.]+$/, '' ) },
	];

	for ( const strategy of searchStrategies ) {
		try {
			const response = await apiFetch( {
				path: addQueryArgs( '/wp/v2/media', {
					search: strategy.search,
					media_type: 'image',
					slug: strategy.search, // Use slug for better matching
					per_page: 20, // Increase results to find better matches
				} ),
				method: 'GET',
			} );

			if ( response && response.length > 0 ) {
				// Try to find exact match first
				const exactMatch = response.find( ( media ) => {
					const mediaUrl = media.source_url || media.url;
					const mediaFilename = mediaUrl
						.split( '/' )
						.pop()
						.split( '?' )[ 0 ];
					return (
						mediaFilename === filename ||
						mediaUrl.includes( baseFilename ) ||
						mediaFilename.includes( baseFilename )
					);
				} );

				if ( exactMatch ) {
					return exactMatch;
				}

				// Return first result if no exact match
				return response[ 0 ];
			}
		} catch ( error ) {
			continue;
		}
	}

	// If all strategies fail, try a broader search using just the base name
	try {
		const broadSearch = baseFilename.split( '-' )[ 0 ]; // Get first part before any dashes
		const response = await apiFetch( {
			path: addQueryArgs( '/wp/v2/media', {
				search: broadSearch,
				media_type: 'image',
				per_page: 50,
			} ),
			method: 'GET',
		} );

		if ( response && response.length > 0 ) {
			return response[ 0 ];
		}
	} catch ( error ) {
		// eslint-disable-next-line no-console
		console.warn( 'Broad search failed', error );
	}

	return null;
};

/**
 * Fetch pages from the custom posts-list API
 * This searches only by page title (not content) for more accurate results
 *
 * @param {string} search - Search query
 * @return {Promise<Array>} Array of page objects with label and value
 */
export const fetchPages = async ( search = '' ) => {
	try {
		const response = await apiFetch( {
			path: `/surerank/v1/posts-list?post_type=page&per_page=200${
				search ? `&search=${ encodeURIComponent( search ) }` : ''
			}`,
			method: 'GET',
		} );

		// Response is already in {label, value} format from the backend
		return response;
	} catch ( error ) {
		return [];
	}
};

/**
 * Get migrated data for onboarding steps after migration done successfully.
 *
 * @return {Promise<Object>} A promise that resolves to the migrated data.
 */
export const getMigratedData = () => {
	return apiFetch( {
		path: `${ API_BASE_URL }/migration/migrated-data`,
		method: 'GET',
	} );
};

/**
 * Fetch AI authentication status
 * @return {Promise<Object>} The authentication status
 */
export const getAuth = () => {
	return apiFetch( { path: `${ API_BASE_URL }/ai/auth` } );
};

/**
 * Save AI access token
 * @param {string} accessKey The access token
 * @return {Promise<Object>} The response from the API
 */
export const saveAuthAccessToken = ( accessKey ) => {
	return apiFetch( {
		path: `${ API_BASE_URL }/ai/auth`,
		method: 'POST',
		data: { accessKey },
	} );
};

/**
 * Generate content
 * @param {string} type         - The type of content to generate.
 * @param {string} [postId]     - The optional post ID.
 * @param {string} [isTaxonomy] - The optional taxonomy flag.
 */
export const generateContent = ( type, postId, isTaxonomy ) => {
	const data = { type };
	if ( postId ) {
		data.post_id = postId;
	}
	if ( isTaxonomy ) {
		data.is_taxonomy = isTaxonomy;
	}
	return apiFetch( {
		path: `${ API_BASE_URL }/generate-content`,
		method: 'POST',
		data,
	} );
};

const sleep = ( ms ) => new Promise( ( resolve ) => setTimeout( resolve, ms ) );

const requestWithTimeout = async ( fetchOptions, timeoutMs ) => {
	const abortController = new AbortController();
	let timerId = null;

	try {
		timerId = setTimeout( () => {
			abortController.abort();
		}, timeoutMs );

		return await apiFetch( {
			...fetchOptions,
			signal: abortController.signal,
		} );
	} catch ( error ) {
		if ( error?.name === 'AbortError' ) {
			const timeoutError = new Error( 'request_timeout' );
			timeoutError.code = 'request_timeout';
			throw timeoutError;
		}
		throw error;
	} finally {
		if ( timerId ) {
			clearTimeout( timerId );
		}
	}
};

/**
 * Recommend schema types for a page/post using AI.
 *
 * @param {Object} params              Request payload.
 * @param {string} params.post_type    Post type.
 * @param {string} params.post_title   Post title.
 * @param {string} params.post_content Post content.
 * @return {Promise<Object>} API response with recommendations.
 */
export const recommendSchemas = async ( params ) => {
	let attempts = 0;
	let lastError;

	while ( attempts < 2 ) {
		try {
			const response = await requestWithTimeout(
				{
					path: `${ API_BASE_URL }/schemas/generator`,
					method: 'POST',
					data: params,
				},
				25000
			);
			return response;
		} catch ( error ) {
			lastError = error;
			attempts++;

			if ( attempts >= 2 ) {
				break;
			}

			await sleep( 500 );
		}
	}

	throw lastError;
};

/**
 * Track schema recommendation interactions.
 *
 * @param {string} eventKey Event key to track.
 * @return {Promise<Object>} API response.
 */
export const trackSchemaRecommendationEvent = ( eventKey ) =>
	apiFetch( {
		path: `${ API_BASE_URL }/schemas/recommendation-event`,
		method: 'POST',
		data: { event_key: eventKey },
	} );

/**
 * Save email reports settings
 * @param {Object}  settings                - The email reports settings to save.
 * @param {boolean} settings.enabled        - Whether email reports are enabled.
 * @param {string}  settings.recipientEmail - The recipient email address.
 * @param {string}  settings.dayOfWeek      - The day of the week for reports.
 */
export const saveEmailReportsSettings = ( settings ) => {
	return apiFetch( {
		path: `${ API_BASE_URL }/email-reports/settings`,
		method: 'POST',
		data: settings,
	} );
};

/**
 * Get email reports settings
 * @return {Promise<Object>} The email reports settings.
 */
export const getEmailReportsSettings = () => {
	return apiFetch( {
		path: `${ API_BASE_URL }/email-reports/settings`,
		method: 'GET',
	} );
};

/**
 * Send test email report
 * @param {string} recipientEmail - The recipient email address.
 * @return {Promise<Object>} The response from the API.
 */
export const sendTestEmailReport = ( recipientEmail ) => {
	return apiFetch( {
		path: `${ API_BASE_URL }/email-reports/send-test`,
		method: 'POST',
		data: { recipientEmail },
	} );
};

/**
 * Improve existing content with AI based on a prompt type.
 *
 * @since x.x.x
 * @param {string}      type             Prompt type (e.g. 'og_image_title').
 * @param {string}      input            Text to improve.
 * @param {Object}      [options]        Optional request options.
 * @param {AbortSignal} [options.signal] AbortController signal to cancel the request.
 * @return {Promise<Object>} Response with improved_text string.
 */
export const improveContent = ( type, input, { signal } = {} ) => {
	const fetchOptions = {
		path: `${ API_BASE_URL }/improve-content`,
		method: 'POST',
		data: { type, input },
	};

	if ( signal ) {
		fetchOptions.signal = signal;
	}

	return apiFetch( fetchOptions );
};