/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';
import { addFilter } from "@wordpress/hooks";
import { Flex, Tooltip, Icon, Button, SelectControl, TextControl } from "@wordpress/components";
import { help, trash, plusCircle } from '@wordpress/icons';

/**
 * Internal dependencies
 */
import { hasOtherBlockAtts } from './../utils/index';

/**
 * Checks for Profile Fields as part of required PersonalizeWP logic.
 *
 * @param {Object} attributes All original PWP attributes
 * @return {boolean} Return True if the attributes validate for Profile Fields
 */
const checkRequiredProfileFields = ( required, attributes ) => {
	// Ensures a rule with a non-empty field is set
	if ( Object.hasOwn( attributes, 'profileFields' ) && 0 < attributes.profileFields.rules.filter(
		( rule ) => '' !== rule.field
	).length ) {
		return true;
	}
	// Return original
	return required;
}
addFilter(
	'personalizeWP.hasRequiredFields',
	'personalizewp/check-for-profile-fields',
	checkRequiredProfileFields
);

/**
 * Render the Profile Fields inspector controls.
 *
 * @since 2.7.0
 * @param {Object} props All the props passed to this function
 */
export default function ProfileFields( props ) {
	const {
		blockAtts,
		setPersonalizeWPAtts,
		settings
	} = props;

	// Check for custom Profile Fields to use, awaiting loading.
	if ( ! settings?.profile_fields || 0 >= settings.profile_fields.length ) {
		return null;
	}

	// Process the custom fields into options we can use.
	const fieldOptions = [
			{
				value: '',
				label: __( '-- Select a field --', 'personalizewp' ),
			},
		].concat(
			// Get all the custom profile fields, order alphabetically by label, and add to the default option.
			...Array.from(settings.profile_fields).sort( (a,b) => {
				return a.label.localeCompare(b.label);
			} )
		);

	const profileFields = blockAtts?.profileFields?.rules ?? [];

	// This is required to ensure the first SelectControl appears
	if ( 0 === profileFields.length ) {
		profileFields.push(
			// Operator is currently hardcoded
			{ 'field': '', 'operator': 'equal' }
		);
	}

	/**
	 * Adds a new field to the overall rules.
	 */
	const addField = () => {
		setPersonalizeWPAtts( {
			'profileFields' :
			{ 'rules' : [
				...profileFields,
				// Operator is currently hardcoded
				{ 'field': '', 'operator': 'equal' },
			] }
		} );
	};

	/**
	 * Remove a field from the set of rules.
	 * @param {number} index Position to remove
	 */
	const removeField = ( index ) => {
		// Filter out the rule at the given index.
		const updatedRules = profileFields.filter(
			( _value, _index ) => _index !== index
		);
		// Update the control attributes with the new rules.
		setPersonalizeWPAtts( {
			'profileFields' :
			{ 'rules' : [
				...updatedRules
			] }
		} );
	};

	/**
	 * Updates specific part of specific rule
	 * @param {mixed} value Field value to change
	 * @param {string} valueType Field type
	 * @param {string} fieldName Field name to change
	 * @param {number} ruleIndex Position of rule changing in all rules.
	 */
	const handleRuleChange = (
		value,
		valueType,
		fieldName,
		ruleIndex = 0
	) => {
		let newValue;

		// if ( 'select' === valueType ) {
		// 	newValue = value.value;
		// } else
		if ( 'multiSelect' === valueType ) {
			newValue = value.length ? value.map( ( v ) => v.value ) : [];
		} else {
			newValue = value;
		}

		// Clone current rules for modification.
		const updatedRules = [ ...profileFields ];
		const currentRule = { ...updatedRules[ ruleIndex ] };

		// if ( 'field' === fieldName ) {
			updatedRules[ ruleIndex ] = Object.assign(
				currentRule,
				{
					[ fieldName ]: newValue
				}
			);
		// }

		setPersonalizeWPAtts( {
			'profileFields' :
			{ 'rules' : [
				...updatedRules,
			] }
		} );
	};

	/**
	 * Dynamic field label based on 1st rule of set
	 * @param {number} ruleIndex Position of rule in all rules.
	 */
	const defaultFieldLabel = ( ruleIndex ) => {
		return '';
		if ( 0 === ruleIndex ) {
			return __( 'Show the block if:', 'personalizewp' );
		}

		return __( 'And if', 'personalizewp' );
	};

	// These controls can be marked as inert if settings have been made elsewhere.
	const inert = hasOtherBlockAtts( blockAtts, [ 'profileFields' ] );

	return (
		<div className="pwp-panel profile-fields">
			<Flex direction="row" align="flex-start">
				<h3>{ __( 'Custom Profile Fields', 'personalizewp' )}</h3>
				<Tooltip
					delay={200}
					text={ __( 'This will return true if the user has the custom profile field with the contained value.', 'personalizewp' ) }
					className="pwp-tooltip"
					placement="bottom-end">
					<div>
						<Icon icon={ help } size={ 20 } />
					</div>
				</Tooltip>
			</Flex>

			{ profileFields.map( ( rule, ruleIndex ) => {
				const usesValue = 'notEmpty' !== rule.operator && 'empty' !== rule.operator;

				return (
					<div className="profile-field" key={ ruleIndex } inert={ inert ? 'true' : undefined } >
						{ defaultFieldLabel( ruleIndex ) }
						<Flex direction="row">
							<SelectControl
								label={ __( 'Select field', 'personalizewp' ) }
								hideLabelFromVision={true}
								value={ rule.field }
								options={ fieldOptions }
								onChange={ ( v ) => handleRuleChange(
									v,
									'select', // fieldType,
									'field', // fieldName,
									ruleIndex
								) }
								__nextHasNoMarginBottom
								disabled={ inert }
							/>
							{
								// Only show this when there are at least 2 fields
								1 < profileFields.length && (
									<Button
										label={ __( 'Delete field', 'personalizewp' ) }
										icon={ trash }
										onClick={ () => removeField( ruleIndex ) }
									/>
								)
							}
						</Flex>

						{
							// Only show the field value if the operator requires a value
							'' !== rule.field && usesValue && (
								<TextControl
									label={ __( 'Enter value', 'personalizewp' ) }
									hideLabelFromVision={true}
									placeholder={ __( 'Enter value', 'personalizewp' ) }
									value={ rule?.value ?? '' }
									onChange={ ( v ) => handleRuleChange(
										v,
										'text', // fieldType,
										'value', // fieldName,
										ruleIndex
									) }
									autoComplete="off"
									__nextHasNoMarginBottom
									disabled={ inert }
								/>
							)
						}
					</div>
				)
			} ) }

			<div className="rule-set__add-rule">
				<Flex direction="row" justify="flex-end">
					{ '' !== profileFields[profileFields.length - 1].field && (
						<Button
							label={ __( 'Add another', 'personalizewp' ) }
							icon={ plusCircle }
							onClick={ () => addField() }
							disabled={ inert }
						/>
					) }
				</Flex>
			</div>
		</div>
	);
}
