<?php

/**
 * Integration class for FluentForm.
 *
 * This class handles integration of various FluentForm enhancements and new fields.
 *
 * @package FormEnhancer\FluentForm
 */
namespace FormEnhancer\FluentForm;

use FormEnhancer\FluentForm\Fields\Confirm;
use FormEnhancer\Settings;
use FormEnhancer\FluentForm\Fields\CzIco;
use FormEnhancer\FluentForm\Fields\SkIco;
use FormEnhancer\FluentForm\Fields\CzSkIco;
use FormEnhancerPro\FluentForm\Fields\EmailEnhanced;
use FormEnhancer\FluentForm\Fields\EuVat;
use FormEnhancerPro\FluentForm\Fields\InputCheckboxWithOther;
use FormEnhancerPro\FluentForm\Fields\InputRadioWithOther;
use FormEnhancer\FluentForm\Integrations\AdminApprovalEnhanced;
use FormEnhancerPro\FluentForm\Integrations\TelegramFailureNotification\Bootstrap;
use FormEnhancerPro\FluentForm\Integrations\Ecomail\EcomailIntegration;
use FormEnhancer\Integrations\AcfFluentFormField\Bootstrap as AcfFluentFormFieldBootstrap;
use FormEnhancerPro\FluentForm\BulkActions\DuplicateEntry;
use FormEnhancerPro\FluentForm\BulkActions\DuplicateEntryService;
/**
 * Main integration class that sets up all FluentForm enhancements.
 */
class Integration {
    /**
     * Set up hooks and filters.
     *
     * @return void
     */
    public function setup() {
        /*
         * Load new fields
         */
        \add_action( 'fluentform/loaded', [$this, 'loadFieldsAndIntegrations'] );
        /*
         * Explicitly register conditional support for custom fields
         * This ensures fields appear in conditional logic for backend integrations (email notifications, etc.)
         */
        \add_filter( 'fluentform/supported_conditional_fields', [$this, 'registerConditionalFields'], 10 );
        /*
         * Also register as form input types
         */
        \add_filter( 'fluentform/form_input_types', [$this, 'registerConditionalFields'], 10 );
        /*
         * Inject JavaScript to extend the form editor's conditional field types.
         * The form editor has a hardcoded list in JavaScript that needs to be extended client-side.
         */
        \add_action( 'fluentform/editor_script_loaded', [$this, 'injectConditionalFieldTypesScript'], 10 );
        /*
         * Pass custom conditional field types to the editor via editor_vars filter.
         */
        \add_filter( 'fluentform/editor_vars', [$this, 'addConditionalFieldTypesToEditorVars'], 10 );
    }

    /**
     * Load fields and integrations
     *
     * @return void
     */
    public function loadFieldsAndIntegrations() : void {
        if ( \formenhancer()->get_settings( Settings::FF_FIELD_VAT ) ) {
            new EuVat();
        }
        if ( \formenhancer()->get_settings( Settings::FF_FIELD_CZ_ICO ) ) {
            new CzIco();
        }
        if ( \formenhancer()->get_settings( Settings::FF_FIELD_SK_ICO ) ) {
            new SkIco();
        }
        if ( \formenhancer()->get_settings( Settings::FF_FIELD_CZ_SK_ICO ) ) {
            new CzSkIco();
        }
        if ( \formenhancer()->get_settings( Settings::FF_FIELD_CONFIRM ) ) {
            new Confirm();
        }
        // ACF Integration - automatically loads when ACF is available.
        $acfBootstrap = new AcfFluentFormFieldBootstrap();
        $acfBootstrap->init();
        if ( \formenhancer()->get_settings( Settings::FF_INTEGRATION_ADMIN_APPROVAL_ENHANCED ) && \defined( 'FLUENTFORMPRO' ) ) {
            new AdminApprovalEnhanced();
        }
        if ( \formenhancer()->get_settings( Settings::FF_ONLY_ONE_IP_ADDRESS_PER_FORM ) ) {
            \add_filter(
                'fluentform/filter_insert_data',
                function ( $response ) {
                    if ( isset( $response['ip'] ) ) {
                        $response['ip'] = \explode( ',', $response['ip'] )[0];
                        // Keep only first IP address (remove all others).
                    }
                    return $response;
                },
                10,
                1
            );
        }
        if ( \formenhancer()->get_settings( Settings::FF_DISABLE_CAPTCHAS_FOR_LOGGED_IN_USERS ) ) {
            \add_filter(
                'fluentform/has_hcaptcha',
                [$this, 'disable_captcha_for_logged_in_users'],
                15,
                1
            );
            // Load after default filter.
            \add_filter(
                'fluentform/has_recaptcha',
                [$this, 'disable_captcha_for_logged_in_users'],
                15,
                1
            );
            // Load after default filter.
            \add_filter(
                'fluentform/has_turnstile',
                [$this, 'disable_captcha_for_logged_in_users'],
                15,
                1
            );
            // Load after default filter.
        }
        if ( \formenhancer()->get_settings( Settings::FF_SUBMIT_BUTTON_AS_BLOCK_BUTTON ) ) {
            \add_filter(
                'fluentform/rendering_field_html_button',
                function ( $html ) {
                    $replacements = [
                        '/<button(.*?)>(.*?)<\\/button>/' => '<div class="wp-block-button"><button$1>$2</button></div>',
                        '/ff-btn-submit/'                 => 'ff-btn-submit wp-block-button__link',
                        '/ff_submit_btn_wrapper/'         => 'ff_submit_btn_wrapper wp-block-buttons',
                        '/ff_btn_style/'                  => 'ff_btn_no_style',
                    ];
                    return \preg_replace( \array_keys( $replacements ), \array_values( $replacements ), $html );
                },
                10,
                1
            );
        }
    }

    /**
     * Register custom fields for conditional logic support.
     *
     * Uses getEnabledCustomFieldTypes() to get the list of custom fields.
     * When adding new fields, only update getEnabledCustomFieldTypes().
     *
     * @param array $conditionalFields Existing conditional fields.
     * @return array Modified conditional fields list.
     */
    public function registerConditionalFields( $conditionalFields ) {
        return \array_merge( $conditionalFields, $this->getEnabledCustomFieldTypes() );
    }

    /**
     * Disable CAPTCHA for logged in users.
     *
     * @param bool $status Current CAPTCHA status.
     * @return bool Modified CAPTCHA status.
     */
    public function disable_captcha_for_logged_in_users( $status ) {
        if ( \is_user_logged_in() ) {
            return false;
            // Disable reCAPTCHA.
        }
        return $status;
        // Keep default behavior.
    }

    /**
     * Add custom conditional field types to editor vars.
     *
     * @param array $data The editor vars data.
     * @return array Modified editor vars data.
     */
    public function addConditionalFieldTypesToEditorVars( $data ) {
        $customFields = $this->getEnabledCustomFieldTypes();
        if ( !empty( $customFields ) ) {
            $data['formenhancer_conditional_types'] = $customFields;
        }
        return $data;
    }

    /**
     * Inject JavaScript to extend the form editor's conditional field types.
     *
     * The Fluent Forms editor has a hardcoded list of supported conditional field types in JavaScript
     * (conditionalSupportedFields array inside a Vue component's data). This method injects a script
     * that patches Vue component instances and overrides Array.includes for our custom fields.
     *
     * @param object $form The form object.
     * @return void
     */
    public function injectConditionalFieldTypesScript( $form ) {
        $customFields = $this->getEnabledCustomFieldTypes();
        if ( empty( $customFields ) ) {
            return;
        }
        $customFieldsJson = \wp_json_encode( $customFields );
        ?>
		<script type="text/javascript">
		(function() {
			var customFields = <?php 
        echo $customFieldsJson;
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON encoded array
        ?>;

			if (!customFields || !customFields.length) return;

			/**
			 * Extend an array with custom field types.
			 */
			function extendArray(arr) {
				if (!Array.isArray(arr)) return false;
				var extended = false;
				customFields.forEach(function(field) {
					if (arr.indexOf(field) === -1) {
						arr.push(field);
						extended = true;
					}
				});
				return extended;
			}

			/**
			 * Find and patch Vue component instances with conditionalSupportedFields.
			 */
			function patchVueInstances() {
				var patched = false;

				// Find all Vue instances in the DOM
				var elements = document.querySelectorAll('[data-v-app], [data-v], #ff_form_editor_app, .ff_form_editor_wrapper');
				elements.forEach(function(el) {
					if (el.__vue__ && el.__vue__.conditionalSupportedFields) {
						if (extendArray(el.__vue__.conditionalSupportedFields)) {
							patched = true;
						}
					}
					// Vue 3 uses __vue_app__
					if (el.__vue_app__ && el.__vue_app__._instance) {
						var instance = el.__vue_app__._instance;
						if (instance.data && instance.data.conditionalSupportedFields) {
							if (extendArray(instance.data.conditionalSupportedFields)) {
								patched = true;
							}
						}
					}
				});

				// Also try the main app element
				var appEl = document.getElementById('ff_form_editor_app');
				if (appEl && appEl.__vue__) {
					// Search child components
					function searchVueTree(vm, depth) {
						if (!vm || depth > 10) return false;
						if (vm.conditionalSupportedFields && extendArray(vm.conditionalSupportedFields)) {
							return true;
						}
						if (vm.$children) {
							for (var i = 0; i < vm.$children.length; i++) {
								if (searchVueTree(vm.$children[i], depth + 1)) {
									return true;
								}
							}
						}
						return false;
					}
					if (searchVueTree(appEl.__vue__, 0)) {
						patched = true;
					}
				}

				return patched;
			}

			/**
			 * Override Array.includes to allow custom fields in various Fluent Forms checks.
			 * This intercepts the includes() call for:
			 * 1. conditionalSupportedFields array - to allow custom fields in conditional logic
			 * 2. Options display array - to show options dropdown for radio/checkbox fields
			 */
			var originalIncludes = Array.prototype.includes;

			// Fields that extend radio/checkbox and should show options dropdown
			var optionBasedFields = [
				'formenhancer_input_radio_other',
				'formenhancer_input_checkbox_other'
			];

			Array.prototype.includes = function(searchElement, fromIndex) {
				if (typeof searchElement !== 'string' || searchElement.indexOf('formenhancer_') !== 0) {
					return originalIncludes.call(this, searchElement, fromIndex);
				}

				// Check 1: conditionalSupportedFields array (contains input_text AND input_radio)
				if (this.indexOf('input_text') !== -1 && this.indexOf('input_radio') !== -1) {
					return true;
				}

				// Check 2: Options display array ["input_radio","select","input_checkbox","dynamic_field"]
				// Only return true for fields that should show options (radio/checkbox based)
				if (this.indexOf('input_radio') !== -1 &&
					this.indexOf('input_checkbox') !== -1 &&
					this.indexOf('select') !== -1 &&
					this.indexOf('dynamic_field') !== -1 &&
					this.length === 4) {
					// This is the options display check
					if (optionBasedFields.indexOf(searchElement) !== -1) {
						return true;
					}
				}

				return originalIncludes.call(this, searchElement, fromIndex);
			};

			// Also try to patch Vue instances when DOM is ready
			function attemptPatch() {
				patchVueInstances();
			}

			// Run on various lifecycle events
			if (document.readyState === 'loading') {
				document.addEventListener('DOMContentLoaded', attemptPatch);
			} else {
				attemptPatch();
			}

			// Poll to catch late-loading Vue components
			var attempts = 0;
			var interval = setInterval(function() {
				patchVueInstances();
				if (++attempts > 30) {
					clearInterval(interval);
				}
			}, 200);

		})();
		</script>
		<?php 
    }

    /**
     * Get enabled custom field types.
     *
     * IMPORTANT: This is the single source of truth for custom field types that support
     * conditional logic. When adding a new field, add it here and it will automatically
     * be registered for both PHP filters and JavaScript conditional logic support.
     *
     * @see registerConditionalFields() - Uses this method for PHP filter registration
     * @see injectConditionalFieldTypesScript() - Uses this method for JavaScript injection
     *
     * @return array Array of enabled custom field type keys.
     */
    private function getEnabledCustomFieldTypes() {
        $customFields = [];
        if ( \formenhancer()->get_settings( Settings::FF_FIELD_CZ_ICO ) ) {
            $customFields[] = 'formenhancer_cz_ico';
        }
        if ( \formenhancer()->get_settings( Settings::FF_FIELD_SK_ICO ) ) {
            $customFields[] = 'formenhancer_sk_ico';
        }
        if ( \formenhancer()->get_settings( Settings::FF_FIELD_CZ_SK_ICO ) ) {
            $customFields[] = 'formenhancer_cz_sk_ico';
        }
        if ( \formenhancer()->get_settings( Settings::FF_FIELD_VAT ) ) {
            $customFields[] = 'formenhancer_eu_vat';
        }
        if ( \formenhancer()->get_settings( Settings::FF_FIELD_CONFIRM ) ) {
            $customFields[] = 'formenhancer_confirm_field';
        }
        return $customFields;
    }

}
