import { __, sprintf } from '@wordpress/i18n';
import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
import { Button, SelectControl, TextControl, ToggleControl } from '@wordpress/components';
import { useState, useEffect } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import apiFetch from '@wordpress/api-fetch';

// Ensure imageSources always has the expected { tablet, mobile } shape so the
// sub-controls below can read from it without defensive guards everywhere.
const emptyOverride = () => ( { imageId: '', imageUrl: '' } );
const normaliseImageSources = ( raw ) => {
	if ( ! raw || typeof raw !== 'object' ) {
		return { tablet: emptyOverride(), mobile: emptyOverride() };
	}
	const pick = ( key ) => {
		const override = raw[ key ];
		if ( ! override || typeof override !== 'object' ) return emptyOverride();
		return {
			imageId: typeof override.imageId === 'string' ? override.imageId : '',
			imageUrl: typeof override.imageUrl === 'string' ? override.imageUrl : '',
		};
	};
	return { tablet: pick( 'tablet' ), mobile: pick( 'mobile' ) };
};

// Preview card shared by the main (desktop) picker and each responsive override.
// Shows a thumbnail of the selected media so editors can see what they picked.
function ImagePreview( { imageId, imageUrl, label } ) {
	const [ resolvedUrl, setResolvedUrl ] = useState( '' );
	const [ resolvedTitle, setResolvedTitle ] = useState( '' );
	const [ isLoading, setIsLoading ] = useState( false );

	useEffect( () => {
		let cancelled = false;

		if ( imageId ) {
			setIsLoading( true );
			apiFetch( { path: `/wp/v2/media/${ imageId }` } )
				.then( ( media ) => {
					if ( cancelled ) return;
					// Prefer a thumbnail size when available for a snappier preview.
					const thumb =
						media?.media_details?.sizes?.thumbnail?.source_url
						|| media?.media_details?.sizes?.medium?.source_url
						|| media?.source_url
						|| '';
					setResolvedUrl( thumb );
					setResolvedTitle( media?.title?.rendered || media?.slug || '' );
					setIsLoading( false );
				} )
				.catch( () => {
					if ( cancelled ) return;
					setResolvedUrl( '' );
					setResolvedTitle( '' );
					setIsLoading( false );
				} );
		} else if ( imageUrl ) {
			setResolvedUrl( imageUrl );
			setResolvedTitle( '' );
			setIsLoading( false );
		} else {
			setResolvedUrl( '' );
			setResolvedTitle( '' );
			setIsLoading( false );
		}

		return () => {
			cancelled = true;
		};
	}, [ imageId, imageUrl ] );

	if ( ! resolvedUrl && ! isLoading ) {
		return null;
	}

	return (
		<div
			className="axcelersblocks-image-preview"
			role="img"
			aria-label={ label || resolvedTitle || __( 'Selected image', 'axcelersblocks' ) }
		>
			{ isLoading ? (
				<span className="axcelersblocks-image-preview__loading">
					{ __( 'Loading preview…', 'axcelersblocks' ) }
				</span>
			) : (
				<>
					<img
						className="axcelersblocks-image-preview__img"
						src={ resolvedUrl }
						alt=""
					/>
					{ resolvedTitle && (
						<span className="axcelersblocks-image-preview__caption">
							{ resolvedTitle }
						</span>
					) }
				</>
			) }
		</div>
	);
}

// Small inline section that renders a Media Library picker + external URL
// input for a single responsive override (tablet / mobile).
function ResponsiveImageOverride( { label, description, override, onChange } ) {
	const { imageId, imageUrl } = override;

	const onSelectMedia = ( media ) => {
		if ( ! media ) return;
		onChange( { ...override, imageId: media.id?.toString?.() || '' } );
	};

	const clearLibrary = () => {
		onChange( { ...override, imageId: '' } );
	};

	return (
		<div className="axcelersblocks-responsive-image-override">
			<h4 className="axcelersblocks-settings-subtitle">{ label }</h4>
			{ description && (
				<p className="axcelersblocks-settings-help">{ description }</p>
			) }

			<ImagePreview imageId={ imageId } imageUrl={ imageUrl } label={ label } />

			<MediaUploadCheck>
				<MediaUpload
					onSelect={ onSelectMedia }
					allowedTypes={ [ 'image', 'image/svg+xml' ] }
					value={ imageId ? parseInt( imageId, 10 ) : undefined }
					render={ ( { open } ) => (
						<Button variant="secondary" onClick={ open }>
							{ imageId
								? __( 'Replace Image', 'axcelersblocks' )
								: __( 'Select Image', 'axcelersblocks' ) }
						</Button>
					) }
				/>
			</MediaUploadCheck>
			{ imageId && (
				<Button
					variant="link"
					isDestructive
					onClick={ clearLibrary }
					style={ { marginLeft: '10px' } }
				>
					{ __( 'Clear', 'axcelersblocks' ) }
				</Button>
			) }

			<TextControl
				label={ __( 'External Image URL', 'axcelersblocks' ) }
				value={ imageUrl }
				onChange={ ( val ) => onChange( { ...override, imageUrl: val } ) }
				placeholder="https://example.com/image.jpg"
			/>
		</div>
	);
}

// Fetch the site's responsive breakpoint widths so the help text matches the
// actual values configured in AxcelersBlocks → Responsive Settings. Defaults
// remain 1024px / 768px if the endpoint fails.
function useResponsiveBreakpoints() {
	const [ widths, setWidths ] = useState( { tablet: '1024px', mobile: '768px' } );

	useEffect( () => {
		let cancelled = false;
		apiFetch( { path: '/axcelersblocks/v1/device-settings' } )
			.then( ( settings ) => {
				if ( cancelled ) return;
				setWidths( {
					tablet: settings?.devices?.tablet?.width || '1024px',
					mobile: settings?.devices?.mobile?.width || '768px',
				} );
			} )
			.catch( () => {
				/* keep defaults */
			} );
		return () => {
			cancelled = true;
		};
	}, [] );

	return widths;
}

export default function MediaControls( { attributes, setAttributes, sizeSlug = 'full' } ) {
	const { imageId, imageUrl, alt, renderInlineSvg } = attributes;
	const imageSources = normaliseImageSources( attributes.imageSources );
	const breakpoints = useResponsiveBreakpoints();

	const registeredSizes = useSelect( ( select ) => {
		// Image sizes live on the block-editor store's settings, not the core store.
		const editor = select( 'core/block-editor' );
		return editor?.getSettings?.()?.imageSizes || [];
	}, [] );

	const sizeOptions = registeredSizes.length
		? registeredSizes.map( ( { slug, name } ) => ( { label: name, value: slug } ) )
		: [
			{ label: __( 'Thumbnail', 'axcelersblocks' ), value: 'thumbnail' },
			{ label: __( 'Medium', 'axcelersblocks' ), value: 'medium' },
			{ label: __( 'Large', 'axcelersblocks' ), value: 'large' },
			{ label: __( 'Full Size', 'axcelersblocks' ), value: 'full' },
		];

	const onSelectMedia = ( media ) => {
		if ( ! media ) return;
		setAttributes( {
			imageId: media.id?.toString?.() || '',
		} );
	};

	const clearLibrary = () => {
		setAttributes( { imageId: '' } );
	};

	const updateOverride = ( device, next ) => {
		setAttributes( {
			imageSources: {
				...imageSources,
				[ device ]: next,
			},
		} );
	};

	return (
		<div className="axcelersblocks-media-controls">
			{/* Use from Media Library (includes upload) */}
			<h3 className="axcelersblocks-settings-title">
				{ __( 'Use from Media Library', 'axcelersblocks' ) }
			</h3>

			<ImagePreview
				imageId={ imageId }
				imageUrl={ imageUrl }
				label={ __( 'Default image', 'axcelersblocks' ) }
			/>

			<MediaUploadCheck>
				<MediaUpload
					onSelect={ onSelectMedia }
					allowedTypes={ [ 'image', 'image/svg+xml' ] }
					value={ imageId ? parseInt( imageId, 10 ) : undefined }
					render={ ( { open } ) => (
						<Button variant="secondary" onClick={ open }>
							{ imageId
								? __( 'Replace Image', 'axcelersblocks' )
								: __( 'Select Image', 'axcelersblocks' ) }
						</Button>
					) }
				/>
			</MediaUploadCheck>
			{ imageId && (
				<Button
					variant="link"
					isDestructive
					onClick={ clearLibrary }
					style={ { marginLeft: '10px' } }
				>
					{ __( 'Clear', 'axcelersblocks' ) }
				</Button>
			) }

			<ToggleControl
				label={ __( 'Render SVG inline', 'axcelersblocks' ) }
				className="axcelersblocks-render-svg-toggle"
				checked={ !! renderInlineSvg }
				onChange={ ( value ) => setAttributes( { renderInlineSvg: value } ) }
				help={ __(
					'When enabled, uploaded or local SVG files render as inline SVG markup instead of an img tag. Remote SVG URLs continue to use the image tag.',
					'axcelersblocks'
				) }
			/>

			<SelectControl
				label={ __( 'Image Size', 'axcelersblocks' ) }
				value={ attributes.sizeSlug || 'full' }
				onChange={ ( val ) => setAttributes( { sizeSlug: val } ) }
				options={ sizeOptions }
				help={ __( 'WordPress registered image size to serve.', 'axcelersblocks' ) }
			/>

			<hr className="axcelersblocks-divider" />

			{/* External URL + Alt (external-only) */}
			<h3 className="axcelersblocks-settings-title">
				{ __( 'External Image URL', 'axcelersblocks' ) }
			</h3>
			<TextControl
				label={ __( 'Image URL (external only)', 'axcelersblocks' ) }
				value={ imageUrl }
				onChange={ ( val ) => setAttributes( { imageUrl: val } ) }
				placeholder="https://example.com/image.jpg"
				help={ __(
					'Used only when Dynamic is off and no Media Library image is selected.',
					'axcelersblocks'
				) }
			/>
			<TextControl
				label={ __( 'Alt text (for external image only)', 'axcelersblocks' ) }
				value={ alt }
				onChange={ ( val ) => setAttributes( { alt: val } ) }
			/>

			<hr className="axcelersblocks-divider" />

			{/* Responsive overrides — render a <picture> element on the frontend */}
			<h3 className="axcelersblocks-settings-title">
				{ __( 'Responsive images (optional)', 'axcelersblocks' ) }
			</h3>
			<p className="axcelersblocks-settings-help">
				{ sprintf(
					/* translators: 1: tablet breakpoint width, 2: mobile breakpoint width. */
					__(
						'Optionally load a different image on Tablet (≤%1$s) or Mobile (≤%2$s). Leave empty to inherit the default image above. Alt text is shared.',
						'axcelersblocks'
					),
					breakpoints.tablet,
					breakpoints.mobile
				) }
			</p>

			<ResponsiveImageOverride
				label={ __( 'Tablet image', 'axcelersblocks' ) }
				description={ sprintf(
					/* translators: %s: breakpoint width, e.g. "1024px" or "768px". */
					__( 'Shown at %s wide and below.', 'axcelersblocks' ),
					breakpoints.tablet
				) }
				override={ imageSources.tablet }
				onChange={ ( next ) => updateOverride( 'tablet', next ) }
			/>

			<ResponsiveImageOverride
				label={ __( 'Mobile image', 'axcelersblocks' ) }
				description={ sprintf(
					/* translators: %s: breakpoint width, e.g. "1024px" or "768px". */
					__( 'Shown at %s wide and below.', 'axcelersblocks' ),
					breakpoints.mobile
				) }
				override={ imageSources.mobile }
				onChange={ ( next ) => updateOverride( 'mobile', next ) }
			/>
		</div>
	);
}
