<?php

/**
 * Blocks Manager Class
 *
 * @package Giraforms
 */
// Exit if accessed directly.
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
/**
 * Class GiraForms_Blocks_Manager
 */
class GiraForms_Blocks_Manager {
    /**
     * Instance of this class.
     *
     * @var GiraForms_Blocks_Manager
     */
    private static $instance = null;

    /**
     * Get instance.
     *
     * @return GiraForms_Blocks_Manager
     */
    public static function instance() {
        if ( is_null( self::$instance ) ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Constructor.
     */
    private function __construct() {
        add_action( 'init', array($this, 'register_blocks') );
        add_action( 'enqueue_block_editor_assets', array($this, 'enqueue_editor_assets') );
        add_action( 'enqueue_block_assets', array($this, 'enqueue_editor_shared_assets') );
        add_action( 'wp_enqueue_scripts', array($this, 'enqueue_frontend_assets') );
        // Captcha block render
        add_filter(
            'render_block',
            array($this, 'render_captcha_block'),
            10,
            2
        );
    }

    /**
     * Register all blocks.
     */
    public function register_blocks() {
        // Form container (must be registered first)
        $this->register_block( 'form-container' );
        // Free blocks
        $free_blocks = array(
            'text-field',
            'number-field',
            'textarea-field',
            'email-field',
            'phone-field',
            'url-field',
            'hidden-field',
            'date-field',
            'time-field',
            'password-field',
            'checkbox-field',
            'radio-field',
            'select-field',
            'color-picker-field',
            'range-slider-field',
            'consent-field',
            'captcha-field',
            'submit-button'
        );
        foreach ( $free_blocks as $block ) {
            $this->register_block( $block );
        }
        // Register block category
        add_filter(
            'block_categories_all',
            array($this, 'register_block_category'),
            10,
            2
        );
    }

    /**
     * Register a single block.
     *
     * @param string $block_name Block name.
     * @param bool   $is_premium Whether it's a premium block.
     */
    private function register_block( $block_name, $is_premium = false ) {
        // Premium blocks use __premium_only suffix for Freemius auto-stripping
        $folder_name = ( $is_premium ? $block_name . '__premium_only' : $block_name );
        $block_path = GIRAFORMS_PLUGIN_DIR . 'blocks/' . $folder_name;
        if ( file_exists( $block_path . '/block.json' ) ) {
            $args = array();
            if ( 'form-container' === $block_name ) {
                $args['render_callback'] = array($this, 'render_form_container');
            }
            register_block_type( $block_path, $args );
            $script_handle = str_replace( '/', '-', 'giraforms/' . $block_name ) . '-editor-script';
            wp_set_script_translations( $script_handle, 'giraforms', GIRAFORMS_PLUGIN_DIR . 'languages' );
        }
    }

    /**
     * Register block category.
     *
     * @param array                   $categories Current categories.
     * @param WP_Block_Editor_Context $editor_context Editor context.
     * @return array
     */
    public function register_block_category( $categories, $editor_context ) {
        return array_merge( array(array(
            'slug'  => 'giraforms',
            'title' => __( 'GiraForms', 'giraforms' ),
        )), $categories );
    }

    /**
     * Enqueue editor assets.
     */
    public function enqueue_editor_assets() {
        wp_enqueue_style(
            'giraforms-editor',
            GIRAFORMS_PLUGIN_URL . 'assets/css/editor.css',
            array('wp-edit-blocks', 'dashicons'),
            GIRAFORMS_VERSION
        );
        $editor_dependencies = array(
            'wp-blocks',
            'wp-element',
            'wp-editor',
            'wp-components',
            'wp-i18n'
        );
        wp_enqueue_script(
            'giraforms-editor',
            GIRAFORMS_PLUGIN_URL . 'assets/js/editor.js',
            $editor_dependencies,
            GIRAFORMS_VERSION,
            false
        );
        // Get email templates for premium users
        $email_templates = array();
        // Check if we need to auto-insert form container
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is a simple URL parameter check for UI state, no data is being processed.
        $auto_insert_form = isset( $_GET['giraforms_add_form'] ) && '1' === sanitize_text_field( wp_unslash( $_GET['giraforms_add_form'] ) );
        wp_localize_script( 'giraforms-editor', 'giraFormsData', array(
            'isPremium'      => giraforms__fs()->can_use_premium_code(),
            'ajaxUrl'        => admin_url( 'admin-ajax.php' ),
            'locale'         => str_replace( '_', '-', get_locale() ),
            'emailTemplates' => $email_templates,
            'autoInsertForm' => $auto_insert_form,
            'roles'          => wp_roles()->get_names(),
        ) );
    }

    /**
     * Enqueue shared editor assets used in the block editor iframe.
     */
    public function enqueue_editor_shared_assets() {
        if ( is_admin() ) {
            wp_enqueue_style( 'dashicons' );
        }
    }

    /**
     * Enqueue frontend assets.
     */
    public function enqueue_frontend_assets() {
        if ( !has_block( 'giraforms/form-container' ) ) {
            return;
        }
        wp_enqueue_style(
            'giraforms-frontend',
            GIRAFORMS_PLUGIN_URL . 'assets/css/frontend.css',
            array(),
            GIRAFORMS_VERSION
        );
        wp_enqueue_script(
            'giraforms-frontend',
            GIRAFORMS_PLUGIN_URL . 'assets/js/frontend.js',
            array('jquery'),
            GIRAFORMS_VERSION,
            true
        );
        // Enqueue captcha provider scripts based on page content.
        if ( has_block( 'giraforms/captcha-field' ) ) {
            global $post;
            $content = ( isset( $post->post_content ) ? $post->post_content : '' );
            if ( false !== strpos( $content, 'cf-turnstile' ) ) {
                wp_enqueue_script(
                    'cloudflare-turnstile',
                    'https://challenges.cloudflare.com/turnstile/v0/api.js',
                    array(),
                    null,
                    true
                );
            }
            if ( false !== strpos( $content, 'g-recaptcha' ) ) {
                wp_enqueue_script(
                    'google-recaptcha',
                    'https://www.google.com/recaptcha/api.js',
                    array(),
                    null,
                    true
                );
            }
            if ( false !== strpos( $content, 'giraforms-recaptcha-v3' ) ) {
                $settings = get_option( 'giraforms_settings', array() );
                $recaptcha_v3_key = ( isset( $settings['recaptcha_v3_site_key'] ) ? $settings['recaptcha_v3_site_key'] : '' );
                if ( !empty( $recaptcha_v3_key ) ) {
                    wp_enqueue_script(
                        'google-recaptcha-v3',
                        'https://www.google.com/recaptcha/api.js?render=' . rawurlencode( $recaptcha_v3_key ),
                        array(),
                        null,
                        true
                    );
                }
            }
            if ( false !== strpos( $content, 'h-captcha' ) ) {
                wp_enqueue_script(
                    'hcaptcha',
                    'https://js.hcaptcha.com/1/api.js',
                    array(),
                    null,
                    true
                );
            }
        }
        // Check for form submission messages (non-AJAX)
        $form_messages = $this->get_form_submission_messages();
        $giraforms_js_data = array(
            'ajaxUrl'      => admin_url( 'admin-ajax.php' ),
            'nonce'        => wp_create_nonce( 'giraForms_submit' ),
            'postId'       => get_the_ID(),
            'locale'       => str_replace( '_', '-', get_locale() ),
            'startOfWeek'  => (int) get_option( 'start_of_week', 0 ),
            'formMessages' => $form_messages,
            'strings'      => $this->get_localized_strings(),
        );
        wp_localize_script( 'giraforms-frontend', 'giraForms', $giraforms_js_data );
    }

    /**
     * Get localized strings for frontend scripts.
     *
     * @return array Localized strings.
     */
    private function get_localized_strings() {
        $strings = array(
            'submitting'    => __( 'Submitting...', 'giraforms' ),
            'success'       => __( 'Form submitted successfully!', 'giraforms' ),
            'error'         => __( 'An error occurred. Please try again.', 'giraforms' ),
            'requiredField' => __( 'This field is required.', 'giraforms' ),
            'invalidEmail'  => __( 'Invalid email address.', 'giraforms' ),
            'invalidPhone'  => __( 'Invalid phone number.', 'giraforms' ),
        );
        return $strings;
    }

    /**
     * Get form submission messages from transients (for non-AJAX submissions).
     *
     * @return array Array of form messages.
     */
    private function get_form_submission_messages() {
        global $post;
        $messages = array();
        if ( !$post || !has_block( 'giraforms/form-container', $post ) ) {
            return $messages;
        }
        // Parse blocks to find form IDs
        $blocks = parse_blocks( $post->post_content );
        $form_ids = $this->extract_form_ids_from_blocks( $blocks );
        // Check for success/error transients for each form
        foreach ( $form_ids as $form_id ) {
            $success = get_transient( 'giraforms_success_' . $form_id );
            if ( $success ) {
                $messages[$form_id] = array(
                    'type'    => 'success',
                    'message' => $success,
                );
                delete_transient( 'giraforms_success_' . $form_id );
            }
            $error = get_transient( 'giraforms_error_' . $form_id );
            if ( $error && is_wp_error( $error ) ) {
                $messages[$form_id] = array(
                    'type'    => 'error',
                    'message' => $error->get_error_message(),
                );
                delete_transient( 'giraforms_error_' . $form_id );
            }
        }
        return $messages;
    }

    /**
     * Extract form IDs from blocks recursively.
     *
     * @param array $blocks Blocks array.
     * @return array Form IDs.
     */
    private function extract_form_ids_from_blocks( $blocks ) {
        $form_ids = array();
        foreach ( $blocks as $block ) {
            if ( 'giraforms/form-container' === $block['blockName'] ) {
                if ( !empty( $block['attrs']['formId'] ) ) {
                    $form_ids[] = $block['attrs']['formId'];
                }
            }
            if ( !empty( $block['innerBlocks'] ) ) {
                $form_ids = array_merge( $form_ids, $this->extract_form_ids_from_blocks( $block['innerBlocks'] ) );
            }
        }
        return $form_ids;
    }

    /**
     * Render captcha block with sitekey.
     *
     * @param string $block_content Block content.
     * @param array  $block         Block data.
     * @return string
     */
    public function render_captcha_block( $block_content, $block ) {
        if ( 'giraforms/captcha-field' !== $block['blockName'] ) {
            return $block_content;
        }
        $settings = get_option( 'giraforms_settings', array() );
        // Detect provider from saved block markup.
        if ( false !== strpos( $block_content, 'giraforms-recaptcha-v3' ) ) {
            $sitekey = ( isset( $settings['recaptcha_v3_site_key'] ) ? $settings['recaptcha_v3_site_key'] : '' );
            $provider_label = 'reCAPTCHA v3';
        } elseif ( false !== strpos( $block_content, 'g-recaptcha' ) ) {
            $sitekey = ( isset( $settings['recaptcha_v2_site_key'] ) ? $settings['recaptcha_v2_site_key'] : '' );
            $provider_label = 'reCAPTCHA v2';
        } elseif ( false !== strpos( $block_content, 'h-captcha' ) ) {
            $sitekey = ( isset( $settings['hcaptcha_site_key'] ) ? $settings['hcaptcha_site_key'] : '' );
            $provider_label = 'hCaptcha';
        } else {
            $sitekey = ( isset( $settings['turnstile_site_key'] ) ? $settings['turnstile_site_key'] : '' );
            $provider_label = 'Turnstile';
        }
        if ( empty( $sitekey ) ) {
            return '<div class="giraforms-captcha-error" style="padding: 10px; background: #fee; border: 1px solid #c00; color: #c00; border-radius: 4px;">' . sprintf( 
                /* translators: %s: captcha provider name */
                esc_html__( 'Error: %s key not configured. Go to Forms > Integrations.', 'giraforms' ),
                esc_html( $provider_label )
             ) . '</div>';
        }
        // Inject the sitekey into the data-sitekey attribute.
        $block_content = str_replace( 'data-sitekey=""', 'data-sitekey="' . esc_attr( $sitekey ) . '"', $block_content );
        return $block_content;
    }

    /**
     * Render form container.
     *
     * @param array  $attributes Block attributes.
     * @param string $content    Block content.
     * @param object $block      Block instance.
     * @return string
     */
    public function render_form_container( $attributes, $content, $block ) {
        return $this->build_form_container_markup( $attributes, $content );
    }

    /**
     * Build dynamic form container markup from attributes and rendered inner blocks.
     *
     * @param array  $attributes Block attributes.
     * @param string $content    Rendered inner blocks content.
     * @return string
     */
    private function build_form_container_markup( $attributes, $content ) {
        $form_id = ( isset( $attributes['formId'] ) ? $attributes['formId'] : '' );
        $form_name = ( isset( $attributes['formName'] ) ? $attributes['formName'] : 'My Form' );
        $success_message = ( isset( $attributes['successMessage'] ) ? $attributes['successMessage'] : __( 'Thank you! Your form has been submitted successfully.', 'giraforms' ) );
        $redirect_url = ( isset( $attributes['redirectUrl'] ) ? $attributes['redirectUrl'] : '' );
        $enable_ajax = !isset( $attributes['enableAjax'] ) || (bool) $attributes['enableAjax'];
        $enable_email_notifications = !isset( $attributes['enableEmailNotifications'] ) || (bool) $attributes['enableEmailNotifications'];
        $email_template_id = ( isset( $attributes['emailTemplateId'] ) ? $attributes['emailTemplateId'] : '' );
        $label_position = ( isset( $attributes['labelPosition'] ) ? $attributes['labelPosition'] : 'above' );
        $custom_style_vars = array();
        $style_attributes = array(
            'accentColor'          => '--giraforms-accent-color',
            'textColor'            => '--giraforms-text-color',
            'borderColor'          => '--giraforms-border-color',
            'borderRadius'         => '--giraforms-border-radius',
            'inputBackgroundColor' => '--giraforms-input-bg-color',
            'requiredColor'        => '--giraforms-required-color',
            'labelFontWeight'      => '--giraforms-label-font-weight',
            'labelSpacing'         => '--giraforms-label-spacing',
        );
        foreach ( $style_attributes as $attr_key => $css_var ) {
            if ( !empty( $attributes[$attr_key] ) ) {
                $custom_style_vars[] = $css_var . ':' . $attributes[$attr_key];
            }
        }
        $wrapper_attributes = array(
            'class' => 'giraforms-form-container giraforms-form',
        );
        if ( !empty( $custom_style_vars ) ) {
            $wrapper_attributes['style'] = implode( ';', $custom_style_vars ) . ';';
        }
        $form_wrapper_attributes = get_block_wrapper_attributes( $wrapper_attributes );
        ob_start();
        ?>
		<form <?php 
        echo wp_kses_data( $form_wrapper_attributes );
        ?>
			method="post"
			action=""
			data-form-id="<?php 
        echo esc_attr( $form_id );
        ?>"
			data-form-name="<?php 
        echo esc_attr( $form_name );
        ?>"
			data-ajax="<?php 
        echo esc_attr( ( $enable_ajax ? 'true' : 'false' ) );
        ?>"
			data-email-notifications="<?php 
        echo esc_attr( ( $enable_email_notifications ? 'true' : 'false' ) );
        ?>"
			data-success-message="<?php 
        echo esc_attr( $success_message );
        ?>"
			data-redirect-url="<?php 
        echo esc_attr( $redirect_url );
        ?>"
			data-label-position="<?php 
        echo esc_attr( $label_position );
        ?>"
			data-conditional-rules=""
		>
			<input type="hidden" name="giraForms_id" value="<?php 
        echo esc_attr( $form_id );
        ?>">
			<input type="hidden" name="giraForms_submit" value="1">
			<input type="hidden" name="giraforms_name" value="<?php 
        echo esc_attr( $form_name );
        ?>">
			<input type="hidden" name="giraForms_post_id" value="" class="giraforms-post-id-field">
			<input type="hidden" name="giraforms_timestamp" value="">
			<input type="hidden" name="giraForms_nonce" value="" class="giraforms-nonce-field">
			<input type="hidden" name="action" value="giraForms_submit">
			<input type="hidden" name="giraforms_email_notifications" value="<?php 
        echo esc_attr( ( $enable_email_notifications ? 'true' : 'false' ) );
        ?>">
			<input type="hidden" name="giraforms_email_template_id" value="<?php 
        echo esc_attr( $email_template_id );
        ?>">
			<input type="hidden" name="giraForms_success_message" value="<?php 
        echo esc_attr( $success_message );
        ?>">
			<input type="hidden" name="giraForms_redirect_url" value="<?php 
        echo esc_attr( $redirect_url );
        ?>">
			<!-- giraforms-premium-hidden-fields -->
			<?php 
        $honeypot_id = 'giraforms-hp-' . $form_id;
        ?>
			<div class="giraforms-hp" aria-hidden="true">
				<label for="<?php 
        echo esc_attr( $honeypot_id );
        ?>">
					<?php 
        esc_html_e( 'Leave this field empty', 'giraforms' );
        ?>
				</label>
				<input
					type="text"
					id="<?php 
        echo esc_attr( $honeypot_id );
        ?>"
					name="giraforms_hp"
					tabindex="-1"
					autocomplete="off"
				>
			</div>
			<div class="giraforms-message" style="display: none"></div>
			<?php 
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Inner blocks are already rendered and escaped by WordPress.
        echo $content;
        ?>
		</form>
		<?php 
        return (string) ob_get_clean();
    }

}
