import * as React from 'react'

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

import {
	__experimentalHStack as HStack,
	__experimentalVStack as VStack,
	__experimentalView as View,
	Modal,
	Placeholder,
	Spinner,
	CheckboxControl,
} from '@wordpress/components'

import {
	download,
} from '@wordpress/icons'

import {
	Button,
	Label,
	JsonView,
	ImportExportStringsContext,
} from '@ska/components'

import {
	useExportSelect,
	useSiteExportValues,
	useOnExport,
} from './hooks'

import {
	EXPORTABLES,
	EXPORTABLE_POST_TYPES,
	SLUG,
} from './util'

import {
	usePostTypeLabels,
} from './PostTypeLabel'

const EXPORTABLE_OPTIONS = EXPORTABLES.filter(({type}) => {
	return ['option', 'record'].includes(type)
})

export interface ExportModalProps {
	onRequestClose: () => void
}

const ExportModal: React.FC<ExportModalProps> = ({
	onRequestClose,
}) => {

	const {
		exportLabel,
		importExportLoadingLabel,
		downloadLabel,
		noTitleLabel,
		exportInstructions,
		labelDefault,
		labelModified,
		labelCustom,
		labelFrontPage,
		labelBlogPage,
	} = useContext(ImportExportStringsContext)

	const postTypeLabels = usePostTypeLabels(EXPORTABLE_POST_TYPES)

	const {
		site,
		stylesheet,
		postTypes,
		loading,
	} = useExportSelect()

	const {
		page_for_posts = -1,
		page_on_front = -1,
		show_on_front,
	} = site

	/** Site options to include. */
	const [include, setInclude] = useState(EXPORTABLE_OPTIONS.filter(({defaultChecked = false}) => defaultChecked).map(({value}) => value))

	/** Site data for exporting. */
	const exportables = useSiteExportValues(site, include, {enabled: !loading})

	/** Entities to include. */
	const [selectedForExport, setSelectedForExport] = useState<Record<string, any[]>>({})

	const contentToExport = Object.keys(selectedForExport).reduce((acc, cur) => {

		const postType = cur
		const ids = selectedForExport[postType]
		if(!ids.length) {
			return acc
		}

		const {
			records = [],
		} = postTypes.find(({postType: pt}) => pt === postType) || {}

		acc[postType] = ids.map(id => {

			const entity = records.find(({id: recordId}) => recordId === id)
			const meta = entity?.meta || {}
			const onlyHasFootnotesMeta = Object.keys(meta).length === 1 && Object(meta).hasOwnProperty('footnotes') && meta.footnotes === ''
			const hasMeta = Object.keys(meta).length > 0 && !onlyHasFootnotesMeta

			const data = {
				title: entity?.title?.raw || '',
				...(entity?.excerpt?.raw && {
					excerpt: entity.excerpt.raw || '',
				}),
				content: entity?.content?.raw || '',
				...(hasMeta && {
					meta,
				}),
				...(['post', 'page'].includes(postType) && {
					template: entity?.template || '',
				}),
			}

			return {
				id,
				...data,
			}
		})
		return acc
	}, {} as Record<string, any[]>)

	const valueToExport = {
		__file: SLUG,
		site: {
			title: site?.title || '',
			show_on_front: site?.show_on_front || '',
			page_for_posts: site?.page_for_posts || 0,
			page_on_front: site?.page_on_front || 0,
			posts_per_page: site?.posts_per_page || 7,
		},
		stylesheet,
		...(include.reduce((acc, slug) => {
			if(slug in exportables) {
				acc[slug] = exportables[slug]
			}
			return acc
		}, {} as any)),
		content: contentToExport,
	}

	const onExport = useOnExport(valueToExport)

	return (
		<Modal
			className='ska__import-export__export-modal'
			title={exportLabel}
			onRequestClose={onRequestClose}
		>
			{loading && (
				<Placeholder
					label={importExportLoadingLabel}
					className='ska__import-export__export-modal__loader'
				>
					<Spinner />
				</Placeholder>
			)}
			{!loading && (
				<View>
					<VStack spacing={8}>
						<p>{exportInstructions}</p>
						<VStack>
							{EXPORTABLE_OPTIONS.map(({label, value}) => {
								const checked = include.includes(value)
								return (
									<CheckboxControl
										key={value}
										label={label}
										checked={checked}
										onChange={() => {
											setInclude(checked ? [...include.filter(v => v !== value)] : [...include, value])
										}}
										__nextHasNoMarginBottom
									/>
								)
							})}
						</VStack>
						<VStack spacing={8}>
							{postTypes.map(({postType, records}) => {

								const ids = records.map(({id}) => id)
								if(!ids.length) {
									return null
								}

								const current = selectedForExport[postType] || []
								const allChecked = ids.length === current.length

								return (
									<fieldset key={postType}>
										<legend>
											<h2>
												<CheckboxControl
													label={postTypeLabels[postType]}
													checked={allChecked}
													indeterminate={current.length > 0 && current.length < ids.length}
													onChange={() => {
														setSelectedForExport({
															...selectedForExport,
															[postType]: allChecked ? [] : ids,
														})
													}}
													__nextHasNoMarginBottom
												/>
											</h2>
										</legend>
										{records.map((record: any) => {

											const {
												id,
												title,
												type,
												original_source,
												source,
											} = record

											const {raw: postTitle = noTitleLabel} = title
											const checked = current.includes(id)

											return (
												<CheckboxControl
													key={id}
													className='ska__import-export__export-modal__checkbox'
													label={postTitle}
													help={(
														<span className='ska__import-export__export-modal__checkbox__help'>
															<span className='slug'>{id}</span>
															{type.indexOf('wp_template') === 0 && <>
																{original_source === 'theme' && <>
																	{source === 'theme' && <Label color='primary'>{labelDefault}</Label>}
																	{source === 'custom' && <Label color='orange'>{labelModified}</Label>}
																</>}
																{original_source === 'user' && <Label color='yellow'>{labelCustom}</Label>}
															</>}
															{type === 'page' && <>
																{id === page_on_front && <Label color='primary'>{labelFrontPage}</Label>}
																{id === page_for_posts && <Label color='primary'>{labelBlogPage}</Label>}
															</>}
														</span>
													)}
													checked={checked}
													onChange={() => {
														setSelectedForExport({
															...selectedForExport,
															[postType]: [
																...(checked ? current.filter(v => v !== id) : []),
																...(!checked ? current.concat(id) : []),
															],
														})
													}}
													__nextHasNoMarginBottom
												/>
											)
										})}
									</fieldset>
								)
							})}
						</VStack>
						<HStack>
							<Button
								variant='primary'
								icon={download}
								children={downloadLabel}
								onClick={() => {
									onExport()
									onRequestClose()
								}}
							/>
							<JsonView value={valueToExport} />
						</HStack>
					</VStack>
				</View>
			)}
		</Modal>
	)
}

export default ExportModal
