// select2-control.js
const { createElement, useRef, useEffect } = window.wp.element;
const { __ } = window.wp.i18n;

export const Select2Control = ({ attributes, setAttributes, clientId, options, id, valueKey = 'selected' }) => {
	const containerRef = useRef(null);

	useEffect(() => {
		const container = containerRef.current;
		if (!container) return;

		let select = container.querySelector('select');
		if (!select) {
			select = document.createElement('select');
			select.name = 'eac-select2-multi';
			select.multiple = true;
			select.style.minWidth = '100%';
			if (id) select.id = id;
			container.appendChild(select);
		}

		// Synchronise les options du <select> avec `options`
		const existingOptionsMap = Array.from(select.options).reduce((map, optionEl) => {
			map[String(optionEl.value)] = optionEl;
			return map;
		}, {});
		(options || []).forEach(option => {
			const valueStr = String(option.value);
			if (existingOptionsMap[valueStr]) {
				if (existingOptionsMap[valueStr].textContent !== option.text) existingOptionsMap[valueStr].textContent = option.text;
			} else {
				const optionEl = document.createElement('option');
				optionEl.value = option.value;
				optionEl.textContent = option.text;
				select.appendChild(optionEl);
			}
		});
		Array.from(select.options).forEach(optionEl => {
			if (!(options || []).some(opt => String(opt.value) === String(optionEl.value))) select.removeChild(optionEl);
		});

		const normalize = value => Array.isArray(value) ? value.map(String) : (value == null ? [] : [String(value)]);
		const currentAttrValue = attributes && Object.prototype.hasOwnProperty.call(attributes, valueKey) ? attributes[valueKey] : undefined;
		let selected = normalize(currentAttrValue);

		// Appliquer la sélection initiale
		Array.from(select.options).forEach(optionEl => {
			optionEl.selected = selected.indexOf(String(optionEl.value)) !== -1;
		});

		// Helper pour mettre à jour l'attribut en forçant une nouvelle instance d'Array
		const updateAttribute = (vals) => {
			const payload = {};
			payload[valueKey] = Array.isArray(vals) ? vals.slice() : vals;
			if (typeof setAttributes === 'function') {
				setAttributes(payload);
			} else {
				wp.data.dispatch('core/block-editor').updateBlockAttributes(clientId, payload);
			}
		};

		if (window.jQuery && jQuery(select).select2) {
			if (jQuery(select).hasClass('select2-hidden-accessible')) {
				jQuery(select).val(selected).trigger('change.select2');
			} else {
				jQuery(select).select2({
					width: '100%',
					placeholder: __('-- CHOOSE --', 'eac-components'),
					allowClear: true,
					tags: false,
					closeOnSelect: false,
					templateSelection: data => (data && data.text) ? data.text : data.id
				});
				jQuery(select).val(selected).trigger('change.select2');
			}

			jQuery(select).off('change.select2.eac').on('change.select2.eac', function () {
				// `this` est l'élément select
				const vals = jQuery(this).val() || [];
				const normalized = Array.isArray(vals) ? vals.map(String) : [String(vals)];
				const current = normalize(currentAttrValue);
				const equal = normalized.length === current.length && normalized.every(value => current.indexOf(value) !== -1);
				if (!equal) {
					updateAttribute(normalized);
				}
			});
		} else {
			// Branch fallback natif (sans jQuery/select2)
			// On attache l'écouteur directement — on n'effectue pas de replaceWith pour ne pas casser les listeners.
			const changeHandler = () => {
				const vals = Array.from(select.selectedOptions).map(optionEl => String(optionEl.value)).filter(v => v !== '');
				updateAttribute(vals);
			};
			// S'assurer qu'il n'y a pas d'ancien listener du même nom
			select.removeEventListener('change', select._eacChangeHandler || (() => { }));
			select._eacChangeHandler = changeHandler;
			select.addEventListener('change', changeHandler);
		}

		return () => {
			if (window.jQuery && jQuery(select).hasClass('select2-hidden-accessible')) {
				jQuery(select).off('change.select2.eac');
				try { jQuery(select).select2('destroy'); } catch (e) { /* ignore */ }
			} else {
				// Retirer listener proprement
				if (select && select._eacChangeHandler) {
					select.removeEventListener('change', select._eacChangeHandler);
					delete select._eacChangeHandler;
				}
			}
		};
		// Dépendances : options et valeur actuelle de l'attribut (stringifiée pour forcer re-run si contenu change)
	}, [options, JSON.stringify(attributes && attributes[valueKey] || [])]);

	return createElement('div', { ref: containerRef, className: 'eac-select2-multi-container' });
};
