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

import {
	useBlockProps,
	useInnerBlocksProps,
	// @ts-expect-error
} from '@wordpress/block-editor'

import {
	createBlock,
	// @ts-expect-error
} from '@wordpress/blocks'

import {
	debugInfo,
	IS_SKA_THEME,
} from '@ska/utils'

// @ts-ignore
import metadata from './block.json'

import {
	useAppenderInnerBlocksOptions,
	useAs,
	useAttributes,
	useBackground,
	type AppenderAttributes,
	type AsAttributes,
	type AttributesAttributes,
	type BackgroundAttributes,
} from '../../supports'

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

import type {
	BlockModule,
	tBlockAttributes,
	tBlockEditProps,
	tBlockSaveProps,
	tBlockTransform,
} from '@ska/shared'

import './style.scss'

export interface ElementBlockAttributes extends AppenderAttributes, AsAttributes, AttributesAttributes, BackgroundAttributes {}

const Edit: React.FC<tBlockEditProps<ElementBlockAttributes>> = (props) => {

	const blockProps = useBlockProps()
	const innerBlocksProps = useInnerBlocksProps(blockProps, useAppenderInnerBlocksOptions(props))
	const [Element, asProps, {isVoidElement}] = useAs(props)
	const attributesProps = useAttributes(props)
	const innerBlocksPropsWithBackground = useBackground(props, innerBlocksProps)

	return (
		<Element
			{...asProps}
			{...attributesProps}
			{...innerBlocksPropsWithBackground}
			{...(isVoidElement && {
				children: undefined,
			})}
		/>
	)
}

const Save: React.FC<tBlockSaveProps<ElementBlockAttributes>> = (props) => {

	const blockProps = useBlockProps.save()
	const innerBlocksProps = useInnerBlocksProps.save(blockProps)
	const [Element, asProps, {isVoidElement}] = useAs.save(props)
	const attributesProps = useAttributes.save(props)
	const innerBlocksPropsWithBackground = useBackground.save(props, innerBlocksProps)

	return (
		<Element
			{...asProps}
			{...attributesProps}
			{...innerBlocksPropsWithBackground}
			{...(isVoidElement && {
				children: undefined,
			})}
		/>
	)
}

const getLayoutClassName = (attributes: tBlockAttributes) => {

	const {
		skaBlocksDisplay = {},
		skaBlocksFlexDirection = {},
	} = attributes

	let layoutClassName = (
		Object.keys(skaBlocksDisplay).length === 1
		&& !!skaBlocksDisplay?.v?.$?.['@']
		&& Object.keys(skaBlocksDisplay.v).length === 1
	) ? `.${skaBlocksDisplay.v.$['@']}` : ''

	if(layoutClassName === '.flex') {

		if(
			Object.keys(skaBlocksFlexDirection).length === 1
			&& !!skaBlocksFlexDirection?.v?.$?.['@']
			&& Object.keys(skaBlocksFlexDirection.v).length === 1
		) {
			layoutClassName = `${layoutClassName}-${skaBlocksFlexDirection.v.$['@']}`
		} else if(Object.keys(skaBlocksFlexDirection).length === 0) {
			layoutClassName = `${layoutClassName}-row`
		}
	}

	return layoutClassName
}

export default (skaBlocks: SkaBlocks): BlockModule => {

	const SKA_THEME_TRANSFORMS = ['ska/conditions', 'ska/condition', 'ska/lightbox', 'ska/hook', 'ska/slider']

	const TRANSFORM_FROM = [
		{
			type: 'block',
			isMultiBlock: true,
			blocks: ['*'],
			transform: () => null,
			__experimentalConvert: (blocks) => {

				debugInfo('__experimentalConvert', blocks)

				if(IS_SKA_THEME && blocks.length === 1) {
					const block = blocks[0]
					if(SKA_THEME_TRANSFORMS.includes(block.name)) {
						return createBlock(
							'ska/element',
							block.attributes,
							block.innerBlocks.map(({name, attributes, innerBlocks}) => createBlock(name, attributes, innerBlocks))
						)
					}
				}

				return createBlock(
					'ska/element',
					{},
					blocks.map(({name, attributes, innerBlocks}) => createBlock(name, attributes, innerBlocks))
				)
			},
		},
	] as tBlockTransform[]

	const SKA_THEME_TRANSFORM_TO = IS_SKA_THEME ? SKA_THEME_TRANSFORMS.map(blockName => ({
		type: 'block',
		blocks: [blockName],
		transform: (attributes, innerBlocks) => createBlock(blockName, attributes, innerBlocks),
	})) as tBlockTransform[] : []

	const TRANSFORM_TO = SKA_THEME_TRANSFORM_TO.concat([
		{
			type: 'block',
			blocks: ['ska/text'],
			transform: (attributes, innerBlocks) => {
				return createBlock('ska/text', {
					...skaBlocks.tailwind.getTailwindAttributes(attributes),
					...(attributes.skaBlocksAs ? {
						skaBlocksAs: attributes.skaBlocksAs,
					} : {
						skaBlocksAs: {
							element: 'div',
						},
					}),
					...(attributes.skaBlocksAttributes && {
						skaBlocksAttributes: attributes.skaBlocksAttributes,
					}),
					...(attributes.anchor && {
						anchor: attributes.anchor,
					}),
					content: innerBlocks.map(block => {
						const {attributes = {}} = block
						const {content = ''} = attributes
						return ((typeof content === 'object' && 'trim' in content) || typeof content === 'string') ? content.trim() : ''
					}).map(v => v).join('<br>'),
				})
			},
		},
		{
			type: 'block',
			blocks: ['*'],
			transform: (attributes, innerBlocks) => innerBlocks,
		},
	] as tBlockTransform[])

	return {
		metadata,
		settings: {
			edit: Edit,
			save: Save,
			transforms: {
				from: TRANSFORM_FROM,
				to: TRANSFORM_TO,
			},
			__experimentalLabel: (attributes: tBlockAttributes, {context}) => {

				const customName = attributes?.metadata?.name
				if(context === 'list-view' && customName) {
					return customName
				}

				const {
					skaBlocksVariation,
					skaBlocksAs = {},
					className,
				} = attributes

				if(skaBlocksVariation) {
					return
				}

				if(context === 'list-view') {

					const {
						element = 'div',
						customElement = 'div',
						isVoid,
					} = skaBlocksAs

					const layoutClassName = getLayoutClassName(attributes)
					const renderClassName = className ? `.${className.split(' ').join('.')}` : ''
					const tagName = `${element === 'custom' ? customElement : element}${layoutClassName}${renderClassName}`

					if(isVoid) {
						return sprintf(_x(`Void: &lt;%s&gt;`, 'Block name in list view - void element', 'ska-blocks'), tagName)
					}

					return sprintf(_x(`&lt;%s&gt;`, 'Block name in list view - HTML element', 'ska-blocks'), tagName)
				}
			},
		},
	}
}
