import * as React from 'react'
import {__, _x} from '@wordpress/i18n'

import {
	useState,
} from '@wordpress/element'

import {
	SelectControl,
	__experimentalVStack as VStack,
	__experimentalHStack as HStack,
	BaseControl,
	TextControl,
	ToggleControl,
	Button,
} from '@wordpress/components'

import {
	addQueryArgs,
} from '@wordpress/url'

import {
	useSelect,
	useDispatch,
} from '@wordpress/data'

import {
	store as coreDataStore,
	type Attachment,
} from '@wordpress/core-data'

import apiFetch from '@wordpress/api-fetch'

import {
	useMediaSizeOptions,
} from './hooks'

import {
	RESIZABLE_MIME_TYPES,
} from './constants'

import {
	getAttachmentSizeSlugByUrl,
	type APIResponse,
} from '@ska/shared'

import './style.scss'

export * from './types'
export * from './constants'
export * from './hooks'
export * from './util'

export interface ImageSizeControlProps {
	label?: string
	/** Current image size slug, alternatively derived from `src` when `id` is specified. */
	slug?: string
	/** Media ID. */
	id?: number
	/** Media file source URL. */
	src?: string
	/** Fired when different size is selected. */
	onChange: (nextValue: {slug: string, src?: string, width?: number, height?: number}) => void
	/** Is resizing supported (default: `true`). */
	resizable?: boolean
	/** Supports selecting "custom" size. */
	custom?: boolean
}

const ImageSizeControl: React.FC<ImageSizeControlProps> = ({
	label = __('Source image', 'ska-blocks'),
	slug,
	id,
	src = '',
	onChange,
	resizable = true,
	custom = false,
}) => {

	const media = useSelect(select => select(coreDataStore).getEntityRecord<Attachment>('postType', 'attachment', id), [id])

	const [width, setWidth] = useState<number>(0)
	const [height, setHeight] = useState<number>(0)
	const [crop, setCrop] = useState<boolean>(src ? !src.includes('-no-crop') : true)

	const [isResizing, setIsResizing] = useState(false) // Whether to show UI for resizing
	const [isLoading, setIsLoading] = useState<boolean>(false)

	// @ts-expect-error
	const {invalidateResolution} = useDispatch(coreDataStore)

	const supportsSizes = slug || (media && !src.startsWith('data:image'))
	const supportsResize = media && media?.mime_type && RESIZABLE_MIME_TYPES.includes(media.mime_type)
	const canResize = resizable && supportsResize

	const OPTIONS = useMediaSizeOptions(media, custom)

	const value = slug ? slug : getAttachmentSizeSlugByUrl(media, src)

	if(!supportsSizes) {
		return null
	}

	return (
		<BaseControl
			className='ska-image-size-control'
			__nextHasNoMarginBottom
		>
			<div className='ska-image-size-control__wrapper'>
				<SelectControl
					label={label}
					options={OPTIONS}
					value={value}
					onChange={slug => {

						const {
							width = 0,
							height = 0,
						} = OPTIONS.find(({value}) => value === slug) || {}

						const src = media && slug in (media?.media_details?.sizes || {}) ? media.media_details.sizes[slug].source_url : undefined

						onChange({
							slug,
							src,
							width,
							height,
						})
					}}
					__nextHasNoMarginBottom
					__next40pxDefaultSize
				/>
				{canResize && <>
					<Button
						className='ska-image-size-control__toggle'
						variant='link'
						size='small'
						children={!isResizing ? __('Resize', 'ska-blocks') : __('Close', 'ska-blocks')}
						disabled={isLoading}
						onClick={() => setIsResizing(!isResizing)}
					/>
				</>}
			</div>
			{isResizing && (
				<VStack className='ska-image-size-control__resize'>
					<HStack>
						<TextControl
							type='number'
							label={__('Width', 'ska-blocks')}
							value={width || 0}
							min={0}
							onChange={value => setWidth(Number(value) || 0)}
							__nextHasNoMarginBottom
							__next40pxDefaultSize
						/>
						<TextControl
							type='number'
							label={__('Height', 'ska-blocks')}
							value={height || 0}
							min={0}
							onChange={value => setHeight(Number(value) || 0)}
							__nextHasNoMarginBottom
							__next40pxDefaultSize
						/>
					</HStack>
					<HStack>
						<ToggleControl
							label={__('Crop to fit', 'ska-blocks')}
							checked={crop}
							onChange={() => setCrop(!crop)}
							__nextHasNoMarginBottom
						/>
						<Button
							variant='primary'
							size='small'
							children={__('Resize', 'ska-blocks')}
							isBusy={isLoading}
							disabled={isLoading || (width < 1 && height < 1)}
							onClick={() => {

								setIsLoading(true)

								const sizeSlug = `ska-size-${width}x${height}${crop ? '' : '-no-crop'}`
								const path = addQueryArgs(`/ska-blocks/v1/image/src`, {id, size: sizeSlug})

								apiFetch<APIResponse>({path})
									.then(response => {
										if(response.success && typeof response.value === 'string') {
											onChange({
												slug: sizeSlug,
												src: response.value,
												width,
												height,
											})
											invalidateResolution('getEntityRecord', ['postType', 'attachment', id])
										}
									})
									.finally(() => {
										setIsLoading(false)
										setIsResizing(false)
									})
							}}
						/>
					</HStack>
				</VStack>
			)}
		</BaseControl>
	)
}

export default ImageSizeControl
