import {
	useState,
	useEffect
} from '@wordpress/element';
import {
	Flex,
	FlexItem,
	Modal,
	TextControl,
	Button,
	ComboboxControl,
	FormTokenField,
} from '@wordpress/components';

import Accordion from './Accordion';

import GoogleVariableFontSettings from './GoogleVariableFontSettings';
import { __, sprintf } from '@wordpress/i18n';



type FontOption = {
	label: string;
	value: string;
};


type ExtendedComboboxControlProps = React.ComponentProps<typeof ComboboxControl> & {
	placeholder?: string;
};

const ExtendedComboboxControl = (props: ExtendedComboboxControlProps) => (
	<ComboboxControl {...props} />
);

type Props = {
	values:GoogleFontItem[];
	defaults: { [key: string]: string };
	fonts: FontOption[];
	fontVariants: GoogleFontConfig[];
	title: string;
	description?: string;
	onChange: (newValues:GoogleFontItem[]) => void
}




export default function GoogleFontSettings({ values, defaults, fonts, fontVariants,title, description, onChange }: Props) {

	// console.log(values);
	const [items, setItems] = useState<GoogleFontItem[]>(values || [{type: 'static', name: '', category: '', variants:[], italic: '', optical_size: ''}]);
	const [searchFonts, setSearchFonts] = useState<FontOption[]>(fonts);
	const [isDeleteMsgOpen, setDeleteMsgOpen] = useState<number>(-1);

	// console.log(fonts);

	// Sync `values` changes to local state
	useEffect(() => {
		// 選択可能なフォント.
		const availableFonts = fonts.filter(({ label }) =>
			items.every((item) => item.name !== label)
		);
		setSearchFonts(availableFonts);

		// フォント名が無い場合は無視.
		onChange(items.filter(item => item?.name));
	}, [items]);


	// console.log(searchFonts);

	// フォントのVariantsをデータから取得.
	const getAllVariantsForFont = (fontName: string|null|undefined): string[] => {
		if (!fontName) return [];
		return fontVariants.find((data) => data.name === fontName)?.variants || [];
	}

	const getFontType = (fontName: string|null|undefined): string => {
		if (!fontName) return '';
		return fontVariants.find((data) => data.name === fontName)?.type || '';
	}

	// アイテム追加.
	const addItem = () => {
		// フォント名を指定していない場合は追加できないようにする.
		if (items.some((item) => item.name === '')) {
			alert(__('Please select a font', 'apura'));
			return;
		}
		setItems([
			...items,
			{
				type: 'static',
				name: '',
				category: '',
				variants: [],
				italic: '',
				optical_size: '',
				width: '',
			}
		]
		);
	};


	// アイテム削除.
	const removeItem = (index: number) => {
		setItems(items.filter((_, i) => i !== index));
		setDeleteMsgOpen(-1);
	};


	const updateFont = (fontName: string | null | undefined, index: number) => {
		setItems((prev) =>
			prev.map((item, i) => {
				return i === index ? {
					type: getFontType(fontName),
					name: fontName || '',
					category: fontVariants.find((data) => data.name === fontName)?.category || '',
					variants: getAllVariantsForFont(fontName),
					italic: fontVariants.find((data) => data.name === fontName)?.italic || '',
					optical_size: fontVariants.find((data) => data.name === fontName)?.optical_size || '',
					width: fontVariants.find((data) => data.name === fontName)?.width?.default || '',
				} : item
			})
		);
	};

	// Variants選択.
	const updateStaticFontVariants = (tokens: string[], fontName: string, index: number) => {
		setItems((prev) =>
			prev.map((item, i) => {
				if (i === index) {
					const variants = tokens.filter((t) => getAllVariantsForFont(fontName).includes(t));
					return { ...item, variants };
				}
				return item;
			})
		);
	};

	const updateVariableFontVariants = (data: GoogleFontItem, index: number) => {
		setItems((prev) =>
			prev.map((item, i) => {
				if (i === index) {
					return { ...item, ...data };
				}
				return item;
			})
		);
	};

	const openDeleteModal = (index: number) => setDeleteMsgOpen(index);
	// 削除時のダイアログメッセージ閉じる
	const closeDeleteModal = () => setDeleteMsgOpen(-1);


	return (
		<div className='apura-google-font-settings-controls'>
			<div className="customize-control-title">{title}</div>
			{description &&
				<p className='description customize-control-description'>{description}</p>
			}
			<Flex direction={'column'} gap={2}>
				{items?.length > 0 && items.map((item, index) => (
					<FlexItem key={index}>
						<Accordion title={item.name || __('Select Font', 'apura')} key={index} isOpened={!item.name}>
							<Flex direction={'column'} gap={4}>
								<FlexItem>
									<ExtendedComboboxControl
										__next40pxDefaultSize
										__nextHasNoMarginBottom
										onChange={(value) => updateFont(value, index)}
										options={searchFonts}
										allowReset={false}
										placeholder={__('Search for...', 'apura' )}
									/>
								</FlexItem>
								<FlexItem>
									<TextControl
										__next40pxDefaultSize
										__nextHasNoMarginBottom
										label={__('Font Name', 'apura')}
										readOnly
										value={item?.name}
										onChange={() => {}}
									/>
								</FlexItem>
								<FlexItem>
									{item.type === 'static' ? (
										<FormTokenField
											__experimentalAutoSelectFirstMatch
											__experimentalExpandOnFocus
											__nextHasNoMarginBottom
											label="Variants"
											onChange={(tokens) => updateStaticFontVariants(tokens as string[], item.name, index)}
											suggestions={getAllVariantsForFont(item?.name)}
											value={item?.variants}
										/>
									) : (
											<GoogleVariableFontSettings
												fontItem={item}
												range={getAllVariantsForFont(item?.name)[0]}
												isWeightOneValue={!item.variants[0].includes('..')}
												// widthData={getFontWidthForFont(item?.name)}
												// isWidthOneValue={item?.width && !item.width.includes('..')}
												onChange={(newValues) => {
													// console.log(newValues);
													updateVariableFontVariants(newValues, index);
												}}
											/>
									)}

								</FlexItem>
								<FlexItem>
									<Button
										style={{border: '1px solid'}}
										isDestructive
										onClick={() => openDeleteModal(index)}
									>{__('Remove')}</Button>
								</FlexItem>
							</Flex>

							{isDeleteMsgOpen === index && (
								<Modal
									title={__('Are you sure you want to remove this font?', 'apura')}
									onRequestClose={closeDeleteModal}
								>
									<p>{__('If this font is used anywhere on the site, it will be unset.', 'apura')}</p>
									<Flex justify='flex-end'>
										<FlexItem>
											<Button variant='primary' onClick={() => removeItem(index)}>{__('Remove')}</Button>
										</FlexItem>
										<FlexItem>
											<Button variant='secondary' onClick={closeDeleteModal}>{__('Cancel')}</Button>
										</FlexItem>
									</Flex>
								</Modal>
							)}
						</Accordion>
					</FlexItem>
				))}
				<FlexItem>
					<Button
						style={{ justifyContent: 'center', width: '100%' }}
						variant='secondary'
						disabled={searchFonts.length === 0}
						icon={<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 24 24"><path fill="currentColor" d="M11.5 12.5H6v-1h5.5V6h1v5.5H18v1h-5.5V18h-1v-5.5Z" /></svg>}
						iconPosition='right'
						onClick={addItem}
						/* translators: %s is the name of the item to add */
					>
						{searchFonts.length === 0
							? __('No items found', 'apura')
							: sprintf(__('Add %s', 'apura'), 'Google Font')
						}
					</Button>
				</FlexItem>
			</Flex>

		</div>
	);

}
