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 {
	DiffView,
	JsonView,
	ImportExportStringsContext,
} from '@ska/components'

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

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

const getCompareValue = (value: any, key: string) => {

	let compareValue = {}

	switch(key) {

		case 'variations': {

			const {
				ref,
				t,
				v,
				__migrated,
				__id,
				__option,
				...keep
			} = value

			compareValue = {
				...keep,
				variation: parseJson(value?.variation),
			}

			break
		}

		case 'presets': {

			const {
				ref,
				t,
				v,
				css,
				__migrated,
				__id,
				__option,
				description,
				...keep
			} = value

			compareValue = {
				...keep,
				attrs: parseJson(value?.attrs),
			}

			break
		}
	}

	return JSON.stringify(compareValue, null, 2)
}

export interface RecordImporterProps {
	/** Slug on plugin options, `ska_blocks_presets`, `ska_blocks_variations`, etc. */
	slug: RootKey
	/** Option key that contains the record. */
	recordKey: string
	/** Value to import. */
	valueToImport: any
}

/** Imports a record in an option, such as `{presets: {[slug]: preset}}`. Currently tailored for just Variations and Presets. */
const RecordImporter: React.FC<RecordImporterProps> = ({
	slug,
	recordKey,
	valueToImport: recordToImport,
}) => {

	const isPreset = slug === 'ska_blocks_presets'

	const valueToImport = recordKey in recordToImport ? recordToImport[recordKey] : {}

	const currentValue = useSelect((select) => {

		const {
			getEditedEntityRecord,
		} = select(coreDataStore)

		// @ts-ignore
		const site = getEditedEntityRecord('root', 'site', undefined!)

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

		return recordKey in currentValue ? currentValue[recordKey] : {}
	}, [slug, recordKey])

	const useOptionsEdit = useMemo(() => createUseOptionsEdit(slug, currentValue), [slug, currentValue])
	const [select, dispatch] = useOptionsEdit()

	const {
		currentValueLabel,
		importedValueLabel,
		createLabel,
		overwriteLabel,
		createCopyLabel,
		isSameText,
	} = useContext(ImportExportStringsContext)

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

	const allKeys = Object.keys(currentValue).concat(Object.keys(valueToImport)).filter(ARRAY_UNIQUE) as string[]

	return (
		<View className='ska__import-export__option-importer'>
			<h2>{slug}</h2>
			<VStack spacing={8}>
				{Object.keys(valueToImport).map(slug => {

					const currentEntry = slug in currentValue ? currentValue[slug] : false
					const importedEntry = slug in valueToImport ? valueToImport[slug] : false
					const exists = currentEntry !== false
					const title = exists ? currentEntry.title : importedEntry.title
					let i = 1
					while(allKeys.includes(`${slug}-${i}`)) {
						i++
					}
					const copySlug = `${slug}-${i}`

					const isImported = imported.includes(slug)
					const copyIsCreated = imported.includes(`${slug}-copy`)

					const value = getCompareValue(currentEntry, recordKey) || ''
					const nextValue = getCompareValue(importedEntry, recordKey) || ''
					const isSame = JSON.stringify(value) === JSON.stringify(nextValue)

					if(isSame) {
						return null
					}

					// Diff for presets classes
					let classesAreSame = true
					let oClasses = ''
					let iClasses = ''
					if(isPreset) {
						oClasses = currentEntry?.cx || ''
						iClasses = importedEntry?.cx || ''
						if(oClasses !== iClasses) {
							classesAreSame = false
						}
					}

					return (
						<View key={slug}>
							<Grid align='center' columns={3}>
								<VStack alignment='start'>
									<strong>{title}</strong>
									<code>{slug}</code>
								</VStack>
								<HStack justify='flex-start'>
									<JsonView value={() => nextValue} />
									{!isSame && (
										<DiffView.Modal
											aValue={value}
											aTitle={currentValueLabel}
											bValue={nextValue}
											bTitle={importedValueLabel}
											buttonProps={{
												variant: 'link',
												size: 'default',
											}}
										/>
									)}
									{isPreset && !classesAreSame && (
										<DiffView.Modal
											aValue={oClasses.split(' ').join('\n')}
											aTitle={currentValueLabel}
											bValue={iClasses.split(' ').join('\n')}
											bTitle={importedValueLabel}
											buttonProps={{
												variant: 'link',
												size: 'default',
												children: 'Classes diff',
											}}
										/>
									)}
									{exists && isSame && <p>{isSameText}</p>}
								</HStack>
								<HStack justify='flex-end'>
									<Button
										variant='primary'
										size='compact'
										children={exists ? overwriteLabel : createLabel}
										disabled={isImported || isSame}
										onClick={() => {
											dispatch.updateOption({
												option: recordKey,
												value: {
													...currentValue,
													[slug]: importedEntry,
												},
											})
											setImported([...imported, slug])
										}}
									/>
									{exists && (
										<Button
											variant='secondary'
											size='compact'
											disabled={copyIsCreated}
											children={createCopyLabel}
											onClick={() => {
												dispatch.updateOption({
													option: recordKey,
													value: {
														...currentValue,
														[copySlug]: importedEntry,
													},
												})
												setImported([...imported, `${slug}-copy`])
											}}
										/>
									)}
								</HStack>
							</Grid>
						</View>
					)
				})}
			</VStack>
		</View>
	)
}

export default RecordImporter
