import * as React from 'react'

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

import {
	__experimentalVStack as VStack,
	__experimentalHStack as HStack,
	__experimentalGrid as Grid,
	__experimentalView as View,
	Button,
} from '@wordpress/components'

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

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

import {
	Pre,
	DiffView,
	ImportExportStringsContext,
} from '@ska/components'

import {
	createUseOptionsEdit,
	type RootKey,
	type Option,
} from '@ska/plugin'

import {
	getSchema,
} from './util'

export interface OptionImporterProps {
	/** Slug on plugin options, `ska_theme`, `ska_blocks`, etc. */
	slug: RootKey
	/** Value to import. */
	valueToImport: any
}

const OptionImporter: React.FC<OptionImporterProps> = ({
	slug,
	valueToImport,
}) => {

	const isTailwind = slug === 'ska_blocks_tailwind4'

	const currentValue = useSelect((select) => {

		const {
			getEditedEntityRecord,
		} = select(coreDataStore)

		// @ts-ignore
		const site: Record<string, any> = getEditedEntityRecord<any>('root', 'site', undefined!) || {}

		const {
			// @ts-ignore
			[slug]: currentValue = {},
		} = site

		return currentValue
	}, [slug])

	const {schema, useOptionsEdit} = useMemo(() => {
		return {
			schema: getSchema(slug),
			useOptionsEdit: createUseOptionsEdit(slug, currentValue),
		}
	}, [slug, currentValue])

	const [, dispatch] = useOptionsEdit()

	const {
		importLabel,
		currentValueLabel,
		importedValueLabel,
		nothingToImportMessage,
	} = useContext(ImportExportStringsContext)

	const [imported, setImported] = useState<string[]>([])

	const importableOptions = schema.flatMap(category => {

		return category.options.map(option => {

			const key = option.id
			if(!Object(valueToImport).hasOwnProperty(key)) {
				return false
			}

			const value = currentValue[key]
			const nextValue = valueToImport[key]

			if(
				value === nextValue
				|| JSON.stringify(value) === JSON.stringify(nextValue)
				|| imported.includes(key)
			) {
				return false
			}

			return option
		}).filter(v => v !== false)
	})

	return (
		<View className='ska__import-export__option-importer'>
			<h2>{slug}</h2>
			<VStack spacing={8}>
				{schema.map(category => {

					const options = category.options.map(option => {

						const key = option.id

						if(!Object(valueToImport).hasOwnProperty(key)) {
							return false
						}

						const value = currentValue[key]
						const nextValue = valueToImport[key]

						if(
							value === nextValue
							|| JSON.stringify(value) === JSON.stringify(nextValue)
							|| imported.includes(key)
						) {
							return false
						}

						return option
					}).filter(v => v !== false)

					if(!options.length) {
						return null
					}

					return (
						<View key={category.id}>
							<Grid
								columns={4}
								align='center'
							>
								<h3>{category.label || category.id}</h3>
								{isTailwind && <div style={{gridColumn: 'span 2 / span 2'}}></div>}
								{!isTailwind && <>
									<h3>{currentValueLabel}</h3>
									<h3>{importedValueLabel}</h3>
								</>}
								<div></div>
							</Grid>
							<VStack>
								{(options as Option[]).map(option => {

									const key = option.id
									const value = currentValue[key]
									const nextValue = valueToImport[key]

									return (
										<Grid
											key={key}
											align='flex-start'
											columns={4}
										>
											<div>{option.label || option.id}</div>
											{isTailwind && <>
												<div style={{gridColumn: 'span 2 / span 2', textAlign: 'center'}}>
													<DiffView.Modal
														aValue={typeof value !== 'string' ? JSON.stringify(value, null, 2) : value}
														aTitle={currentValueLabel}
														bValue={typeof nextValue !== 'string' ? JSON.stringify(nextValue, null, 2) : nextValue}
														bTitle={importedValueLabel}
														buttonProps={{
															variant: 'link',
															size: 'default',
														}}
													/>
												</div>
											</>}
											{!isTailwind && <>
												<Pre value={value} copy={false} />
												<Pre value={nextValue} copy={false} />
											</>}
											<HStack justify='flex-end'>
												{!isTailwind && <>
													<DiffView.Modal
														aValue={typeof value !== 'string' ? JSON.stringify(value, null, 2) : value}
														aTitle={currentValueLabel}
														bValue={typeof nextValue !== 'string' ? JSON.stringify(nextValue, null, 2) : nextValue}
														bTitle={importedValueLabel}
														buttonProps={{
															variant: 'link',
															size: 'default',
														}}
													/>
												</>}
												<Button
													variant='primary'
													size='compact'
													children={importLabel}
													onClick={() => {
														dispatch.updateOption({option: option.id, value: valueToImport[key]})
														setImported([...imported, key])
													}}
												/>
											</HStack>
										</Grid>
									)
								})}
							</VStack>
						</View>
					)
				})}
			</VStack>
			{importableOptions.length < 1 && (
				<View>
					<p>{nothingToImportMessage}</p>
				</View>
			)}
		</View>
	)
}

export default OptionImporter
