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

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

import {
	Modal,
	__experimentalHStack as HStack,
} from '@wordpress/components'

import {
	reset as resetIcon,
} from '@wordpress/icons'

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

import {
	store as noticesStore,
} from '@wordpress/notices'

import {
	Button,
	DiffView,
	type DiffViewProps,
} from '@ska/components'

import {
	parseJson,
} from '@ska/utils'

import {
	usePreset,
	usePresetOptionsEdit,
	PresetActions,
	type PresetSlug,
} from '../..'

import {
	useParse,
} from '../../../../tailwind/inspector-controls'

import {
	managedPresets,
} from '../../../../data'

import type {
	Preset,
} from '../../../../types'

import type {
	tBlockAttributes,
} from '@ska/shared'

import './style.scss'

export interface PresetDiffProps {
	slug: PresetSlug
	onRequestClose: () => void
}

const PresetDiff: React.FC<PresetDiffProps> = ({
	slug,
	onRequestClose,
}) => {

	const {
		createSuccessNotice,
	} = useDispatch(noticesStore)

	const preset = usePreset(slug)
	const [, presetsDispatch] = usePresetOptionsEdit()

	const {
		title,
		attrs,
		cx,
		loading,
	} = preset

	const attributes = parseJson(attrs, `Preset: ${slug}`) as tBlockAttributes

	const updatePresetAttributes = async (attributes: tBlockAttributes, updates: Partial<Omit<Preset, 'attrs' | 'cx' | 'css'>> = {}) => {
		await presetsDispatch.updatePresetAttributes(slug, attributes, updates)
	}

	const setAttributes = (nextAttributes: tBlockAttributes) => {
		updatePresetAttributes({
			...attributes,
			...nextAttributes,
		})
	}

	const [parse, ParseErrors] = useParse({
		attributes,
		setAttributes,
	})

	const {
		cx: originalClasses = '',
		attrs: originalAttrs = '{}',
		loading: defaultLoading,
	} = managedPresets[slug] || {}

	const loadingIsDifferent = defaultLoading && loading !== defaultLoading
	const isDifferent = cx !== originalClasses

	const a = cx.split(' ')
	const b = originalClasses.split(' ')

	const onChange = useCallback(({side, type, lineNumber, content}: Parameters<NonNullable<DiffViewProps['onChange']>>[0]) => {
		if(side === 'old' && type === 'delete') {
			parse(content)
		}
	}, [parse])

	return (
		<Modal
			title={sprintf(__('Compare preset: %s', 'ska-blocks'), title)}
			onRequestClose={onRequestClose}
			size='fill'
			className='ska-blocks__preset-diff'
			headerActions={<>
				<HStack
					className='ska-blocks__preset-diff__actions'
					justify='end'
					spacing={6}
				>
					{isDifferent && (
						<Button
							isDestructive
							variant='secondary'
							size='small'
							icon={resetIcon}
							children={__('Reset preset to default', 'ska-blocks')}
							aria-disabled={!isDifferent}
							disabled={!isDifferent}
							onClick={() => {
								updatePresetAttributes(
									parseJson(originalAttrs, `Original preset: ${slug}`) as tBlockAttributes,
									{
										...loadingIsDifferent && {
											loading: defaultLoading,
										},
										isDefault: true,
									}
								)
								createSuccessNotice(sprintf(__('Preset "%s" has been reset to default.'), title), {type: 'snackbar'})
								onRequestClose()
							}}
						/>
					)}
					<PresetActions slug={slug} />
				</HStack>
			</>}
		>
			{ParseErrors}
			<DiffView
				bTitle={__('Current preset', 'ska-blocks')}
				bValue={a}
				aTitle={__('Original preset', 'ska-blocks')}
				aValue={b}
				onChange={onChange}
			/>
		</Modal>
	)
}

export default PresetDiff
