<?php

/**
 * Confirm Field - Based on Example Custom Field For WP FluentForms.
 * Set a target field name and this field will work as Confirmation field.
 *
 * Original:
 *
 * @source https://github.com/nkb-bd/wp-fluentform-custom-field
 * @source https://fluentforms.com/docs/how-to-create-your-own-custom-field-with-fluent-forms/
 * @author Lukman Nakib, Amimul Ihsan
 * @package FormEnhancer\FluentForm\Fields
 */

namespace FormEnhancer\FluentForm\Fields;

use FluentForm\App\Modules\Form\FormFieldsParser;
use FluentForm\Framework\Helpers\ArrayHelper;
use FluentForm\App\Services\FormBuilder\Components\Text;
use FluentForm\App\Services\FormBuilder\BaseFieldManager;

/**
 * Class Confirm
 *
 * Handles confirmation field functionality by matching input with a target field.
 */
class Confirm extends BaseFieldManager
{
	/**
	 * Constructor.
	 *
	 * Sets up the field type and registers necessary hooks.
	 */
	public function __construct()
	{
		parent::__construct(
			'formenhancer_confirm_field',
			'Confirm Input - Form Enhancer',
			['confirm', 'check', 'formenhancer'],
			'general'
		);

		\add_filter("fluentform/validate_input_item_{$this->key}", [$this, 'validate'], 10, 5);

		$this->hideFieldFormEntries();
	}

	/**
	 * Get the field component configuration.
	 *
	 * @return array Field component settings and attributes.
	 */
	public function getComponent()
	{
		return [
			'index'          => 16,
			'element'        => $this->key,
			'attributes'     => [
				'name'        => $this->key,
				'class'       => '',
				'value'       => '',
				'type'        => 'text',
				'placeholder' => ''
			],
			'settings'       => [
				'container_class'     => '',
				'placeholder'         => \__('Re-enter your entry', 'formenhancer'),
				'auto_select_country' => 'no',
				'label'               => \__('Confirm Input', 'formenhancer'),
				'label_placement'     => '',
				'help_message'        => '',
				'validate_on_change'  => false,
				'target_input'        => '',
				'error_message'       => \__('Confirm value does not match', 'formenhancer'),
				'validation_rules'    => [
					'required' => [
						'value'   => false,
						'message' => \__('This field is required', 'formenhancer'),
					]
				],
				'conditional_logics'  => []
			],
			'editor_options' => [
				'title'      => $this->title . ' Field',
				'icon_class' => 'ff-edit-text',
				'template'   => 'inputText'
			],
		];
	}

	/**
	 * Get general editor elements.
	 *
	 * @return array List of editor elements.
	 */
	public function getGeneralEditorElements()
	{
		return [
			'label',
			'placeholder',
			'value',
			'label_placement',
			'validation_rules',
		];
	}

	/**
	 * Get general editor element settings.
	 *
	 * @return array Editor element settings.
	 */
	public function generalEditorElement()
	{
		return [
			'target_input'       => [
				'template'  => 'inputText',
				'label'     => 'Target Field Name',
				'help_text' => 'The input value will be matched with target input and show error if not matched',
			],
			'error_message'      => [
				'template' => 'inputText',
				'label'    => 'Error Message',
			],
			'validate_on_change' => [
				'template' => 'inputCheckbox',
				'label'    => 'Validate on Change',
				'options'  => [
					[
						'value' => true,
						'label' => \__('Yes', 'formenhancer'),
					],
				]
			],
		];
	}

	/**
	 * Validate the confirmation field value.
	 *
	 * @param mixed  $errorMessage Error message.
	 * @param array  $field Field data.
	 * @param array  $formData Form data.
	 * @param array  $fields All form fields.
	 * @param object $form Form object.
	 * @return mixed Error message if validation fails.
	 */
	public function validate($errorMessage, $field, $formData, $fields, $form)
	{
		$ConfirmInputName = ArrayHelper::get($field, 'raw.attributes.name');
		$targetInputName = ArrayHelper::get($field, 'raw.settings.target_input');
		$message = ArrayHelper::get($field, 'raw.settings.error_message');

		if (ArrayHelper::get($formData, $ConfirmInputName) != ArrayHelper::get($formData, $targetInputName)) {
			$errorMessage = [$message];
		}

		return $errorMessage;
	}

	/**
	 * Render the confirmation field.
	 *
	 * @param array  $data Field data.
	 * @param object $form Form object.
	 * @return string Rendered field HTML.
	 */
	public function render($data, $form)
	{
		$data['attributes']['id'] = $this->makeElementId($data, $form);
		$this->pushScripts($data, $form);
		return (new Text())->compile($data, $form);
	}

	/**
	 * Add validation scripts to the footer.
	 *
	 * @param array  $data Field data.
	 * @param object $form Form object.
	 */
	private function pushScripts($data, $form)
	{
		\add_action('wp_footer', function () use ($data, $form) {
			if (!ArrayHelper::isTrue($data, 'settings.validate_on_change')) {
				return;
			}
			?>
			<script type="text/javascript">
				jQuery(document).ready(function ($) {
					function confirmValidate() {

						let confirmInput = jQuery('.<?php echo \esc_attr($form->instance_css_class); // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps ?>').find("#<?php echo \esc_attr($data['attributes']['id']); ?>"); 
						let targetName = '<?php echo \esc_js(ArrayHelper::get($data, 'settings.target_input')); ?>';
						let message = '<?php echo \esc_js(ArrayHelper::get($data, 'settings.error_message')); ?>';
						let targetInput = jQuery("input[name='" + targetName + "']")
						let timeout = null;
						confirmInput.on("keyup", function () {
							clearTimeout(timeout); // this will clear the recursive unneccessary calls
							timeout = setTimeout(() => {
								validate()
							}, 1500);
						});

						function validate() {
							if (confirmInput.val() !== targetInput.val()) {
								let div = $('<div/>', {class: 'error text-danger'});
								confirmInput.closest('.ff-el-group').addClass('ff-el-is-error');
								confirmInput.closest('.ff-el-input--content').find('div.error').remove();
								confirmInput.closest('.ff-el-input--content').append(div.text(message));
							} else {
								confirmInput.closest('.ff-el-group').removeClass('ff-el-is-error');
								confirmInput.closest('.ff-el-input--content').find('div.error').remove();
							}
						}
					}

					confirmValidate();
				});
			</script>
			<?php
		}, 9999);
	}

	/**
	 * Hide confirmation fields from form entries.
	 */
	private function hideFieldFormEntries()
	{
		\add_filter('fluentform/all_entry_labels', function ($formLabels, $form_id) {
			$form = \wpFluent()->table('fluentform_forms')->find($form_id);
			$confirmField = FormFieldsParser::getInputsByElementTypes($form, ['confirm_field']);
			if (\is_array($confirmField) && !empty($confirmField)) {
				ArrayHelper::forget($formLabels, \array_keys($confirmField));
			}
			return $formLabels;
		}, 10, 2);

		\add_filter('fluentform/all_entry_labels_with_payment', function ($formLabels, $test, $form) {
			$confirmField = FormFieldsParser::getInputsByElementTypes($form, ['confirm_field']);
			if (\is_array($confirmField) && !empty($confirmField)) {
				ArrayHelper::forget($formLabels, \array_keys($confirmField));
			}
			return $formLabels;
		}, 10, 3);
	}
}