/**
 * External dependencies.
 */
import { SelectControl, TextControl } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { store as editorStore } from '@wordpress/editor';
import { useState, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies.
 */
import API from '@spectra-pro-helpers/api';
import urls from '@spectra-pro-constants/urls';

/**
 * Renders controls for selecting or entering a custom field meta key for dynamic links.
 *
 * Displays a select control with available meta fields for the current post and a text
 * input for custom meta keys when selected. Updates the dynamic content settings with
 * the selected or entered meta key.
 *
 * @since x.x.x
 *
 * @param {Object}   props               - The component props.
 * @param {Object}   props.settings      - The dynamic content settings from the context.
 * @param {Function} props.updateSetting - Function to update settings in the context.
 * @param {string}   [props.type='text'] - The type of content ('text' or 'url').
 * @return {Element} The custom field selection controls.
 */
const LinkPostMetaField = ( { settings, updateSetting, type = 'text' } ) => {
	// Extract the selected meta key from settings.
	const selectedMetaKey = settings.source?.postCustomField || '';

	// State for loading status and available meta keys.
	const [ isLoading, setIsLoading ] = useState( true );
	const [ metaKeys, setMetaKeys ] = useState( () => {
		// Initial options including saved value if it exists
		const initialOptions = [
		{ label: __( 'Choose', 'spectra-pro' ), value: '' },
		{ label: __( 'Custom Input', 'spectra-pro' ), value: 'custom' },
		];

		// If we have a saved value that's not 'custom' or empty, add it to initial options
		if ( selectedMetaKey && selectedMetaKey !== 'custom' && selectedMetaKey !== '' ) {
			initialOptions.splice( 1, 0, { label: selectedMetaKey, value: selectedMetaKey } );
		}
		
		return initialOptions;
	} );

	// Get the current post ID from the editor store.
	const postId = useSelect( ( select ) => select( editorStore ).getCurrentPostId(), [] );

	// Initialize API client for fetching post custom fields.
	const postCustomFieldsAPI = new API( urls.postCustomFields );

	// Fetch meta fields when postId changes.
	useEffect( () => {
		if ( ! postId ) {
			setIsLoading( false );
			return;
		}

		/**
		 * Fetches available meta fields for the current post.
		 */
		const fetchMetaFields = async () => {
			setIsLoading( true );

			try {
				// Fetch meta fields via API.
				const response = await postCustomFieldsAPI.list( { post_id: postId, type } );

				// Transform response data into select options.
				const metaFields = Object.entries( response?.data || {} )
					.map( ( [ , val ] ) => {
						if ( val && typeof val === 'object' && 'label' in val && 'value' in val ) {
							return {
								label: val.label,
								value: val.value,
							};
						}
						return null;
					} )
					.filter( Boolean );

				const metaOptions = [
					{ label: __( 'Choose', 'spectra-pro' ), value: '' },
					...metaFields,
					{ label: __( 'Custom Input', 'spectra-pro' ), value: 'custom' },
				];

				setMetaKeys( metaOptions );
			} catch ( error ) {
				// On error, keep at least the initial options with saved value
				const errorOptions = [
					{ label: __( 'Choose', 'spectra-pro' ), value: '' },
					{ label: __( 'Custom Input', 'spectra-pro' ), value: 'custom' },
				];
				
				// Preserve saved value even on error
				if ( selectedMetaKey && selectedMetaKey !== 'custom' && selectedMetaKey !== '' ) {
					errorOptions.splice( 1, 0, { label: selectedMetaKey, value: selectedMetaKey } );
				}
				
				setMetaKeys( errorOptions );
			} finally {
				setIsLoading( false );
			}
		};

		fetchMetaFields();
	}, [ postId, selectedMetaKey ] );

	return (
		<>
			<SelectControl
				label={ __( 'Custom Field', 'spectra-pro' ) }
				value={ selectedMetaKey }
				options={ isLoading ? [ 
					{ label: __( 'Loading…', 'spectra-pro' ), value: '' },
					// Preserve saved value during loading
					...( selectedMetaKey && selectedMetaKey !== '' ? [{ label: selectedMetaKey, value: selectedMetaKey }] : [] )
				] : metaKeys }
				onChange={ ( newValue ) => updateSetting( 'source.postCustomField', newValue ) }
			/>
			{ selectedMetaKey === 'custom' && ! isLoading && (
				<TextControl
					label={ __( 'Custom Meta Key', 'spectra-pro' ) }
					value={ settings.source?.postMetaKey || '' }
					onChange={ ( newValue ) => updateSetting( 'source.postMetaKey', newValue ) }
				/>
			) }
		</>
	);
};

export default LinkPostMetaField;
