<?php
/**
 * Form Builder class file
 *
 * This file contains the FormBuilder class which handles the construction,
 * rendering, and validation of complex HTML forms. It provides a flexible
 * system for defining form structures through schemes, supports tabbed layouts,
 * conditional rendering, and performance-optimized caching mechanisms.
 *
 * @package    UltraguardPro\view
 * @author     Vikas Bhardwaj <support@ultraguard.net>
 * @copyright  2024 UltraguardPro
 * @license    GPL-2.0-or-later
 * @version    1.0.0
 * @link       https://ultraguardpro.com/docs/form-builder
 */

namespace UltraguardPro\view;

defined( 'ABSPATH' ) || exit;
use UltraguardPro\core\ValidationEngine;
/**
 * Form Builder
 *
 * Handles dynamic form construction and management with performance optimizations,
 * tabbed layouts, conditional rendering, and validation integration. This class
 * implements a modular approach to form building where forms are defined through
 * structured schemes and rendered with proper security and accessibility.
 *
 * The FormBuilder supports horizontal and vertical tab layouts, field grouping,
 * section organization, and integrates with validation and conditional rendering
 * engines. It uses lazy loading for dependent services and implements caching
 * for improved performance on complex forms.
 *
 * @package    UltraguardPro\view
 * @author     Vikas Bhardwaj
 * @version    1.0.0
 * @since      1.0.0
 * @see        \UltraguardPro\view\RenderEngine
 * @see        \UltraguardPro\core\ValidationEngine
 * @see        \UltraguardPro\view\ConditionalRenderer
 *
 * @example
 * $scheme = [
 *     'form' => ['method' => 'post', 'action' => ''],
 *     'header' => ['title' => 'My Form'],
 *     'data' => [['type' => 'text', 'name' => 'username', 'title' => 'Username']],
 *     'footer' => ['submit_button' => true]
 * ];
 * $builder = new FormBuilder($scheme);
 * echo $builder->build();
 */
class FormBuilder {

    /**
     * Form scheme
     *
     * Contains the complete form definition including form configuration,
     * header, layout, data fields, tabs, and footer settings. Merged with
     * default values during construction.
     *
     * @var array
     * @access private
     */
    private $scheme;

    /**
     * Form context
     *
     * Contextual data passed to the form builder for conditional rendering
     * and validation. Typically includes current user data, post data, or
     * application state.
     *
     * @var array
     * @access private
     */
    private $context;

    /**
     * Render engine instance
     *
     * Lazy-loaded instance of the RenderEngine used for rendering individual
     * form fields and action elements. Only instantiated when needed.
     *
     * @var \UltraguardPro\view\RenderEngine|null
     * @access private
     */
    private $render_engine;

    /**
     * Validation engine instance
     *
     * Lazy-loaded instance of the ValidationEngine used for validating form
     * submissions against the scheme's validation rules.
     *
     * @var \UltraguardPro\core\ValidationEngine|null
     * @access private
     */
    private $validation_engine;

    /**
     * Conditional renderer instance
     *
     * Lazy-loaded instance of the ConditionalRenderer used for evaluating
     * conditional logic for tab visibility and field rendering.
     *
     * @var \UltraguardPro\view\ConditionalRenderer|null
     * @access private
     */
    private $conditional_renderer;

    /**
     * Cached validation rules
     *
     * Extracted validation rules from the form scheme, cached to avoid
     * repeated processing during multiple validation calls.
     *
     * @var array|null
     * @access private
     */
    private $cached_validation_rules;

    /**
     * Default scheme structure
     *
     * Default structure for form schemes ensuring all required sections
     * exist with empty defaults. Used as fallback when merging user schemes.
     *
     * @var array
     * @access private
     * @static
     */
    private static $default_scheme = array(
        'form'   => array(),
        'header' => array(),
        'layout' => array(),
        'data'   => array(),
        'tabs'   => array(),
        'footer' => array(),
    );

    /**
     * Cache for tab visibility checks
     *
     * Stores visibility evaluation results for tabs to avoid redundant
     * capability and condition checks during rendering.
     *
     * @var array
     * @access private
     */
    private $tab_visibility_cache = array();

    /**
     * FormBuilder constructor
     *
     * Initializes the form builder with a scheme and optional context.
     * Merges the provided scheme with defaults and sets up lazy-loaded
     * service instances for rendering, validation, and conditional logic.
     *
     * @param  array  $scheme   Form definition scheme
     * @param  array  $context  Optional contextual data for rendering and validation
     * @return void
     * @access public
     */
    public function __construct( $scheme, $context = array() ) {
        // Secure scheme with defaults using cached defaults
        $this->scheme = wp_parse_args( $scheme, self::$default_scheme );

        $this->context = wp_parse_args( $context, array() );

        // Lazy load engines only when needed
        $this->render_engine = null;
        $this->validation_engine = null;
        $this->conditional_renderer = null;
        $this->cached_validation_rules = null;
    }

    /**
     * Build complete form from scheme
     *
     * Renders the complete HTML form including wrapper, header, body,
     * and footer sections. Executes before and after hooks if enabled.
     * This is the primary public method for form output.
     *
     * @return string  Rendered form HTML
     * @access public
     *
     * @example
     * $formHtml = $builder->build();
     * echo $formHtml;
     */
    public function build() {
        $hooks_enabled = ! defined( 'ULTRA_GUARD_DISABLE_HOOKS' ) || ! ULTRA_GUARD_DISABLE_HOOKS;

        if ( $hooks_enabled ) {
            do_action( 'ultraguard_before_form_build', $this->scheme, $this->context );
        }

        $form_wrapper = $this->render_form_wrapper();
        $form_header = $this->render_form_header();
        $form_body = $this->render_form_body();
        $form_footer = $this->render_form_footer();


        $output = $form_wrapper . $form_header . $form_body . $form_footer . '</form>';

        if ( $hooks_enabled ) {
            do_action( 'ultraguard_after_form_build', $this->scheme, $this->context, $output );
        }

        return $output;
    }

    /**
     * Render form wrapper
     *
     * Generates the opening <form> tag with configured attributes,
     * nonce field, and hidden fields. Applies filters for custom
     * attribute modification.
     *
     * @return string  Form wrapper HTML including <form> opening tag
     * @access protected
     */
    protected function render_form_wrapper() {
        static $form_id_counter = 0;

        $default_form_config = array(
            'method'         => 'post',
            // For AJAX forms 'action' is a wp_ajax_{action} name, not a URL.
            // Default to admin-ajax.php; callers override with the action name.
            'action'         => '',
            'ajax'           => false,
            // Default nonce to TRUE so every FormBuilder form gets a nonce field
            // unless the caller explicitly passes 'nonce' => false.
            'nonce'          => true,
            'nonce_action'   => 'ultraguard_admin_nonce',
            'class'          => 'ultraguard-form',
            // Counter-based ID — avoids the frozen-uniqid bug where a static
            // cache makes every form share the same id within one PHP request.
            'id'             => 'ultraguard-form-' . ( ++$form_id_counter ),
            'hidden_fields'  => array(),
        );

        $form_config = wp_parse_args( $this->scheme['form'], $default_form_config );

        $method = in_array( strtolower( $form_config['method'] ), array( 'post', 'get' ), true )
            ? $form_config['method']
            : 'post';

        $ajax  = (bool) $form_config['ajax'];
        $class = sanitize_html_class( $form_config['class'] );
        $id    = sanitize_html_class( $form_config['id'] );

        // Separate the AJAX action name from the HTML form action URL — identical
        // to how LayoutRenderer::render_form_start() handles this.
        $ajax_action_name = '';
        if ( $ajax && ! empty( $form_config['action'] ) ) {
            $ajax_action_name = sanitize_key( $form_config['action'] );
        }

        $form_action_url = $ajax_action_name
                ? esc_url( self_admin_url( 'admin-ajax.php' ) )
            : esc_url( $form_config['action'] );

        $attributes = array(
            'method' => $method,
            'action' => $form_action_url,
            'class'  => $class,
            'id'     => $id,
        );

        if ( $ajax ) {
            $attributes['data-ajax'] = 'true';
            // data-ajax-action is what the JS handler reads first — without it
            // the form submission falls back to a wrong consolidated handler.
            if ( $ajax_action_name ) {
                $attributes['data-ajax-action'] = $ajax_action_name;
            }
        }

        // Allow custom form attributes via filter.
        $attributes = apply_filters( 'ultraguard_form_builder_attributes', $attributes, $this->scheme, $this->context );

        // Build attributes string.
        $attributes_parts = array();
        foreach ( $attributes as $key => $value ) {
            $attributes_parts[] = sprintf( '%s="%s"', esc_attr( $key ), esc_attr( $value ) );
        }
        $attributes_string = $attributes_parts ? ' ' . implode( ' ', $attributes_parts ) : '';

        $output = sprintf( '<form%s>', $attributes_string );

        // Hidden action field — secondary lookup path for JS (input[name="action"])
        // and fallback for non-JS traditional form submissions.
        if ( $ajax_action_name ) {
            $output .= sprintf(
                '<input type="hidden" name="action" value="%s">',
                esc_attr( $ajax_action_name )
            );
        }

        // Nonce: emit a single field named `nonce` so the JS handler picks it up
        // without the AjaxManager appending a second global nonce over the top.
        //
        //   'nonce' => true           → generate from nonce_action (default)
        //   'nonce' => 'some_value'   → pre-computed value; use as-is
        //   'nonce' => false          → omit entirely
        $nonce_cfg = $form_config['nonce'];
        if ( $nonce_cfg === true ) {
            $nonce_action = sanitize_key( $form_config['nonce_action'] ?: 'ultraguard_admin_nonce' );
            $output .= sprintf(
                '<input type="hidden" id="_wpnonce" name="nonce" value="%s">',
                esc_attr( wp_create_nonce( $nonce_action ) )
            );
        } elseif ( is_string( $nonce_cfg ) && $nonce_cfg !== '' ) {
            $output .= sprintf(
                '<input type="hidden" id="_wpnonce" name="nonce" value="%s">',
                esc_attr( $nonce_cfg )
            );
        }

        // Additional hidden fields.
        if ( ! empty( $form_config['hidden_fields'] ) && is_array( $form_config['hidden_fields'] ) ) {
            foreach ( $form_config['hidden_fields'] as $name => $value ) {
                $output .= sprintf(
                    '<input type="hidden" name="%s" value="%s">',
                    esc_attr( sanitize_key( $name ) ),
                    esc_attr( $value )
                );
            }
        }

        return $output;
    }

    /**
     * Render form header
     *
     * Generates the form header section with title, subtitle, icon,
     * and action buttons. Returns empty string if all header elements
     * are empty.
     *
     * @return string  Form header HTML or empty string
     * @access protected
     */
    protected function render_form_header() {
        static $default_header_config = null;

        if ( $default_header_config === null ) {
            $default_header_config = array(
                'title'    => '',
                'subtitle' => '',
                'icon'     => '',
                'actions'  => array(),
            );
        }

        $header_config = wp_parse_args( $this->scheme['header'], $default_header_config );

        if ( empty( $header_config['title'] ) &&
             empty( $header_config['subtitle'] ) &&
             empty( $header_config['actions'] ) ) {
            return '';
        }

        $title    = $header_config['title'];
        $subtitle = $header_config['subtitle'];
        $icon     = $header_config['icon'];
        $actions  = $header_config['actions'];

        $output = '<div class="ultraguard-form-header">';

        if ( ! empty( $icon ) ) {
            $output .= sprintf( '<span class="ultraguard-form-icon dashicons %s"></span>', esc_attr( $icon ) );
        }

        $output .= '<div class="ultraguard-form-title">';

        if ( ! empty( $title ) ) {
            $output .= sprintf( '<h2>%s</h2>', esc_html( $title ) );
        }

        if ( ! empty( $subtitle ) ) {
            $output .= sprintf( '<p class="description">%s</p>', esc_html( $subtitle ) );
        }

        $output .= '</div>';

        // Header actions
        if ( ! empty( $actions ) ) {
            $output .= '<div class="ultraguard-form-actions">';
            foreach ( $actions as $action ) {
                $output .= $this->get_render_engine()->render( $action, $this->context );
            }
            $output .= '</div>';
        }

        $output .= '</div>';

        return $output;
    }

    /**
     * Render form body
     *
     * Generates the main form body containing either tabbed layout
     * or standard field groups. Handles empty form fallback.
     *
     * @return string  Form body HTML
     * @access protected
     */
    protected function render_form_body() {
        static $default_layout = null;

        if ( $default_layout === null ) {
            $default_layout = array( 'type' => 'standard' );
        }

        $layout = wp_parse_args( $this->scheme['layout'], $default_layout );
        $data = isset( $this->scheme['data'] ) ? $this->scheme['data'] : array();
        $tabs = isset( $this->scheme['tabs'] ) ? $this->scheme['tabs'] : array();

        $output = '<div class="ultraguard-form-body">';

        // Handle tabbed layout
        if ( ! empty( $tabs ) ) {
            $output .= $this->render_tabbed_layout( $tabs );
        }
        // Handle standard layout
        else if ( ! empty( $data ) ) {
            $output .= $this->render_field_groups( $data );
        } else {
            // Empty form body fallback
            $output .= '<div class="ultraguard-form-empty">' . esc_html__( 'No form fields configured.', 'ultraguard-security-suite') . '</div>';
        }

        $output .= '</div>';

        return $output;
    }

    /**
     * Render tabbed layout
     *
     * Delegates to horizontal or vertical tab rendering based on
     * layout configuration. Defaults to horizontal tabs.
     *
     * @param  array  $tabs  Tabs configuration
     * @return string        Tabbed layout HTML
     * @access protected
     */
    protected function render_tabbed_layout( $tabs ) {
        $layout_type = isset( $this->scheme['layout']['type'] ) ? $this->scheme['layout']['type'] : 'tabs';

        if ( $layout_type === 'vertical_tabs' ) {
            return $this->render_vertical_tabs( $tabs );
        } else {
            return $this->render_horizontal_tabs( $tabs );
        }
    }

    /**
     * Render horizontal tabs
     *
     * Generates a horizontal tab navigation interface with tab content
     * panels. Handles tab visibility checks and empty state.
     *
     * @param  array  $tabs  Tabs configuration
     * @return string        Horizontal tabs HTML
     * @access protected
     */
    protected function render_horizontal_tabs( $tabs ) {
        static $default_tab_config = null;

        if ( $default_tab_config === null ) {
            $default_tab_config = array(
                'title'       => '',
                'icon'        => '',
                'data'        => array(),
                'capability'  => '',
                'condition'   => array(),
            );
        }

        $tabs_nav = '';
        $tabs_content = '';
        $first = true;
        $has_visible_tabs = false;

        foreach ( $tabs as $tab_id => $tab_config ) {
            $tab_config = wp_parse_args( $tab_config, $default_tab_config );

            if ( ! $this->should_render_tab( $tab_id, $tab_config ) ) {
                continue;
            }

            $has_visible_tabs = true;
            $active_class = $first ? ' ultraguard-tab-active' : '';
            $first = false;

            // Tab navigation
            $icon_html = '';
            if ( ! empty( $tab_config['icon'] ) ) {
                $icon_html = sprintf( '<span class="dashicons %s"></span>', esc_attr( $tab_config['icon'] ) );
            }

            $tab_title = ! empty( $tab_config['title'] ) ? $tab_config['title'] : __( 'Untitled Tab', 'ultraguard-security-suite');

            $tabs_nav .= sprintf(
                '<li class="ultraguard-tab-nav-item%s">' .
                '<a href="#%s" class="ultraguard-tab-nav-link" data-tab="%s">%s%s</a>' .
                '</li>',
                esc_attr( $active_class ),
                esc_attr( sanitize_html_class( $tab_id ) ),
                esc_attr( sanitize_html_class( $tab_id ) ),
                $icon_html,
                esc_html( $tab_title )
            );

            // Tab content
            $tab_content = '';
            if ( ! empty( $tab_config['data'] ) ) {
                $tab_content = $this->render_field_groups( $tab_config['data'] );
            }

            $display_class = $active_class ? 'ultraguard-tab-active' : '';

            $tabs_content .= sprintf(
                '<div id="%s" class="ultraguard-tab-pane %s">%s</div>',
                esc_attr( sanitize_html_class( $tab_id ) ),
                esc_attr( $display_class ),
                $tab_content
            );
        }

        if ( ! $has_visible_tabs ) {
            return '<div class="ultraguard-no-tabs">' . esc_html__( 'No tabs available.', 'ultraguard-security-suite') . '</div>';
        }

        return sprintf(
            '<div class="ultraguard-tabs">' .
            '<ul class="ultraguard-tab-nav">%s</ul>' .
            '<div class="ultraguard-tab-content">%s</div>' .
            '</div>',
            $tabs_nav,
            $tabs_content
        );
    }

    /**
     * Render vertical tabs
     *
     * Generates a vertical tab navigation interface with sidebar navigation
     * and content area. Similar to horizontal tabs but with different CSS structure.
     *
     * @param  array  $tabs  Tabs configuration
     * @return string        Vertical tabs HTML
     * @access protected
     */
    protected function render_vertical_tabs( $tabs ) {
        static $default_tab_config = null;

        if ( $default_tab_config === null ) {
            $default_tab_config = array(
                'title'       => '',
                'icon'        => '',
                'data'        => array(),
                'capability'  => '',
                'condition'   => array(),
            );
        }

        $tabs_nav = '';
        $tabs_content = '';
        $first = true;
        $has_visible_tabs = false;

        foreach ( $tabs as $tab_id => $tab_config ) {
            $tab_config = wp_parse_args( $tab_config, $default_tab_config );

            if ( ! $this->should_render_tab( $tab_id, $tab_config ) ) {
                continue;
            }

            $has_visible_tabs = true;
            $active_class = $first ? ' ultraguard-tab-active' : '';
            $first = false;

            // Tab navigation
            $icon_html = '';
            if ( ! empty( $tab_config['icon'] ) ) {
                $icon_html = sprintf( '<span class="dashicons %s"></span>', esc_attr( $tab_config['icon'] ) );
            }

            $tab_title = ! empty( $tab_config['title'] ) ? $tab_config['title'] : __( 'Untitled Tab', 'ultraguard-security-suite');

            $tabs_nav .= sprintf(
                '<li class="ultraguard-tab-nav-item%s">' .
                '<a href="#%s" class="ultraguard-tab-nav-link" data-tab="%s">%s%s</a>' .
                '</li>',
                esc_attr( $active_class ),
                esc_attr( sanitize_html_class( $tab_id ) ),
                esc_attr( sanitize_html_class( $tab_id ) ),
                $icon_html,
                esc_html( $tab_title )
            );

            // Tab content
            $tab_content = '';
            if ( ! empty( $tab_config['data'] ) ) {
                $tab_content = $this->render_field_groups( $tab_config['data'] );
            }

            $display_class = $active_class ? 'ultraguard-tab-active' : '';

            $tabs_content .= sprintf(
                '<div id="%s" class="ultraguard-tab-pane %s">%s</div>',
                esc_attr( sanitize_html_class( $tab_id ) ),
                esc_attr( $display_class ),
                $tab_content
            );
        }

        if ( ! $has_visible_tabs ) {
            return '<div class="ultraguard-no-tabs">' . esc_html__( 'No tabs available.', 'ultraguard-security-suite') . '</div>';
        }

        return sprintf(
            '<div class="ultraguard-tabs ultraguard-tabs-vertical">' .
            '<div class="ultraguard-tabs-sidebar">' .
            '<ul class="ultraguard-tab-nav">%s</ul>' .
            '</div>' .
            '<div class="ultraguard-tabs-content">%s</div>' .
            '</div>',
            $tabs_nav,
            $tabs_content
        );
    }

    /**
     * Render field groups
     *
     * Processes and renders field data arrays, delegating to appropriate
     * renderers for sections, field groups, or individual fields.
     *
     * @param  array  $data  Field data configuration
     * @return string        Field groups HTML
     * @access protected
     */
    protected function render_field_groups( $data ) {
        static $default_item_config = null;

        if ( $default_item_config === null ) {
            $default_item_config = array(
                'type'        => '',
                'name'        => '',
                'title'       => '',
                'description' => '',
                'data'        => array(),
                'fields'      => array(),
                'actions'     => array(),
            );
        }

        if ( empty( $data ) || ! is_array( $data ) ) {
            return '';
        }

        $output = '';

        foreach ( $data as $item ) {
            if ( ! is_array( $item ) ) {
                continue;
            }

            $item = wp_parse_args( $item, $default_item_config );

            if ( $item['type'] === 'section' ) {
                $output .= $this->render_section( $item );
            } else if ( $item['type'] === 'field-group' ) {
                $output .= $this->render_field_group( $item );
            } else {
                $output .= $this->get_render_engine()->render( $item, $this->context );
            }
        }

        return $output;
    }

    /**
     * Render section
     *
     * Generates a form section with optional header (title, description,
     * actions) and content area for nested fields.
     *
     * @param  array  $section  Section configuration
     * @return string           Section HTML
     * @access protected
     */
    protected function render_section( $section ) {
        static $default_section_config = null;

        if ( $default_section_config === null ) {
            $default_section_config = array(
                'title'       => '',
                'description' => '',
                'data'        => array(),
                'actions'     => array(),
                'class'       => '',
            );
        }

        $section = wp_parse_args( $section, $default_section_config );

        $output = '<div class="ultraguard-form-section">';

        // Section header
        if ( ! empty( $section['title'] ) || ! empty( $section['description'] ) || ! empty( $section['actions'] ) ) {
            $output .= '<div class="ultraguard-section-header">';

            if ( ! empty( $section['title'] ) ) {
                $output .= sprintf( '<h3>%s</h3>', esc_html( is_array( $section['title'] ) ? (string)( $section['title']['text'] ?? $section['title']['content'] ?? wp_json_encode( $section['title'] ) ) : (string)( $section['title'] ) ) );
            }

            if ( ! empty( $section['description'] ) ) {
                $output .= sprintf( '<p class="description">%s</p>', esc_html( is_array( $section['description'] ) ? (string)( $section['description']['text'] ?? $section['description']['content'] ?? wp_json_encode( $section['description'] ) ) : (string)( $section['description'] ) ) );
            }

            // Section actions
            if ( ! empty( $section['actions'] ) && is_array( $section['actions'] ) ) {
                $output .= '<div class="ultraguard-section-actions">';
                foreach ( $section['actions'] as $action ) {
                    $output .= $this->get_render_engine()->render( $action, $this->context );
                }
                $output .= '</div>';
            }

            $output .= '</div>';
        }

        // Section content
        if ( ! empty( $section['data'] ) ) {
            $output .= '<div class="ultraguard-section-content">';
            $output .= $this->render_field_groups( $section['data'] );
            $output .= '</div>';
        }

        $output .= '</div>';

        return $output;
    }

    /**
     * Render field group
     *
     * Generates a multi-column field group container for organizing
     * related fields. Supports 1-6 column layouts.
     *
     * @param  array  $group  Field group configuration
     * @return string         Field group HTML
     * @access protected
     */
    protected function render_field_group( $group ) {
        static $default_group_config = null;

        if ( $default_group_config === null ) {
            $default_group_config = array(
                'columns' => 1,
                'fields'  => array(),
                'class'   => '',
            );
        }

        $group = wp_parse_args( $group, $default_group_config );

        $columns = max( 1, min( 6, absint( $group['columns'] ) ) ); // Limit columns between 1-6
        $fields = $group['fields'];

        if ( empty( $fields ) ) {
            return '';
        }

        $output = sprintf( '<div class="ultraguard-field-group ultraguard-field-group-columns-%d">', $columns );

        foreach ( $fields as $field ) {
            if ( is_array( $field ) ) {
                $output .= $this->get_render_engine()->render( $field, $this->context );
            }
        }

        $output .= '</div>';

        return $output;
    }

    /**
     * Render form footer
     *
     * Generates the form footer with submit/reset buttons and additional
     * actions. Returns empty string if no footer elements configured.
     *
     * @return string  Form footer HTML or empty string
     * @access protected
     */
    protected function render_form_footer() {
        static $default_footer_config = null;

        if ( $default_footer_config === null ) {
            $default_footer_config = array(
                'submit_button' => true,
                'submit_text'   => __( 'Save Changes', 'ultraguard-security-suite'),
                'reset_button'  => false,
                'reset_text'    => __( 'Reset', 'ultraguard-security-suite'),
                'actions'       => array(),
            );
        }

        $footer_config = wp_parse_args( $this->scheme['footer'], $default_footer_config );

        $has_submit = $footer_config['submit_button'];
        $has_reset = $footer_config['reset_button'];
        $has_actions = ! empty( $footer_config['actions'] );

        if ( ! $has_submit && ! $has_reset && ! $has_actions ) {
            return '';
        }

        $output = '<div class="ultraguard-form-footer">';

        // Submit button
        if ( $has_submit ) {
            $output .= sprintf(
                '<button type="submit" class="button button-primary ultraguard-submit">%s</button>',
                esc_html( $footer_config['submit_text'] )
            );
        }

        // Reset button
        if ( $has_reset ) {
            $output .= sprintf(
                '<button type="reset" class="button button-secondary ultraguard-reset">%s</button>',
                esc_html( $footer_config['reset_text'] )
            );
        }

        // Additional actions
        if ( $has_actions ) {
            $footer_actions = apply_filters( 'ultraguard_form_footer_actions', $footer_config['actions'], $this->scheme, $this->context );

            foreach ( $footer_actions as $action ) {
                if ( is_array( $action ) ) {
                    $output .= $this->get_render_engine()->render( $action, $this->context );
                }
            }
        }

        $output .= '</div>';

        return $output;
    }

    /**
     * Check if tab should be rendered
     *
     * Evaluates tab visibility based on capability requirements,
     * conditional logic, and custom filters. Results are cached
     * for performance during form rendering.
     *
     * @param  string  $tab_id      Tab identifier
     * @param  array   $tab_config  Tab configuration
     * @return bool                 Whether to render tab
     * @access protected
     */
    protected function should_render_tab( $tab_id, $tab_config ) {
        // Check cache first
        if ( isset( $this->tab_visibility_cache[ $tab_id ] ) ) {
            return $this->tab_visibility_cache[ $tab_id ];
        }

        $visible = true;

        // Check capability
        if ( ! empty( $tab_config['capability'] ) && ! current_user_can( $tab_config['capability'] ) ) {
            $visible = false;
        }

        // Check custom conditions
        if ( $visible && ! empty( $tab_config['condition'] ) ) {
            $conditional_renderer = $this->get_conditional_renderer();
            if ( ! $conditional_renderer->evaluate( $tab_config['condition'], $this->context ) ) {
                $visible = false;
            }
        }

        // Allow custom tab visibility logic
        if ( $visible ) {
            $visible = apply_filters( 'ultraguard_form_tab_visibility', true, $tab_config, $this->context );
        }

        // Cache result
        $this->tab_visibility_cache[ $tab_id ] = $visible;

        return $visible;
    }

    /**
     * Validate form data
     *
     * Validates submitted form data against the scheme's validation rules.
     * Executes before and after hooks if enabled. Returns validation result.
     *
     * @param  array  $data  Form data to validate (typically $_POST)
     * @return bool          Validation result (true if valid, false otherwise)
     * @access public
     *
     * @example
     * $isValid = $builder->validate($_POST);
     * if ($isValid) {
     *     // Process form submission
     * }
     */
    public function validate( $data ) {
        $hooks_enabled = ! defined( 'ULTRA_GUARD_DISABLE_HOOKS' ) || ! ULTRA_GUARD_DISABLE_HOOKS;

        if ( $hooks_enabled ) {
            do_action( 'ultraguard_before_form_validation', $data, $this->scheme, $this->context );
        }

        $validation_rules = $this->extract_validation_rules();
        $result = $this->get_validation_engine()->validate( $data, $validation_rules, $this->context );

        if ( $hooks_enabled ) {
            do_action( 'ultraguard_after_form_validation', $data, $this->scheme, $this->context, $result );
        }

        return $result;
    }

    /**
     * Extract validation rules from form scheme
     *
     * Recursively extracts validation rules from the form scheme,
     * caching results for performance. Returns array of rules keyed by field name.
     *
     * @return array  Validation rules
     * @access protected
     */
    protected function extract_validation_rules() {
        // Return cached rules if available
        if ( $this->cached_validation_rules !== null ) {
            return $this->cached_validation_rules;
        }

        $rules = array();

        $this->extract_rules_from_data( isset( $this->scheme['data'] ) ? $this->scheme['data'] : array(), $rules );

        if ( isset( $this->scheme['tabs'] ) ) {
            foreach ( $this->scheme['tabs'] as $tab ) {
                $tab = wp_parse_args( $tab, array( 'data' => array() ) );
                $this->extract_rules_from_data( $tab['data'], $rules );
            }
        }

        $rules = apply_filters( 'ultraguard_form_validation_rules', $rules, $this->scheme, $this->context );

        // Cache the result
        $this->cached_validation_rules = $rules;

        return $rules;
    }

    /**
     * Extract rules from data recursively
     *
     * Recursively traverses form data structure to extract validation
     * rules from fields. Handles nested sections and field groups.
     *
     * @param  array  $data   Form data structure
     * @param  array  &$rules Rules array (passed by reference for accumulation)
     * @return void
     * @access protected
     */
    protected function extract_rules_from_data( $data, &$rules ) {
        if ( empty( $data ) || ! is_array( $data ) ) {
            return;
        }

        static $default_item_config = null;

        if ( $default_item_config === null ) {
            $default_item_config = array(
                'type'       => '',
                'name'       => '',
                'validation' => array(),
            );
        }

        foreach ( $data as $item ) {
            if ( ! is_array( $item ) ) {
                continue;
            }

            $item = wp_parse_args( $item, $default_item_config );

            if ( ! empty( $item['name'] ) && ! empty( $item['validation'] ) ) {
                $rules[ sanitize_key( $item['name'] ) ] = $item['validation'];
            }

            if ( ! empty( $item['data'] ) && is_array( $item['data'] ) ) {
                $this->extract_rules_from_data( $item['data'], $rules );
            }

            if ( ! empty( $item['fields'] ) && is_array( $item['fields'] ) ) {
                $this->extract_rules_from_data( $item['fields'], $rules );
            }
        }
    }

    /**
     * Get validation errors
     *
     * Returns validation errors from the last validation attempt.
     * Useful for displaying error messages to users.
     *
     * @return array  Validation errors
     * @access public
     */
    public function get_validation_errors() {
        return $this->get_validation_engine()->get_errors();
    }

    /**
     * Get render engine instance (lazy loading)
     *
     * Provides singleton access to the RenderEngine instance,
     * initializing it only when first needed.
     *
     * @return \UltraguardPro\view\RenderEngine
     * @access protected
     */
    protected function get_render_engine() {
        if ( $this->render_engine === null ) {
            $this->render_engine = RenderEngine::get_instance();
        }
        return $this->render_engine;
    }

    /**
     * Get validation engine instance (lazy loading)
     *
     * Provides singleton access to the ValidationEngine instance,
     * initializing it only when first needed.
     *
     * @return \UltraguardPro\core\ValidationEngine
     * @access protected
     */
    protected function get_validation_engine() {
        if ( $this->validation_engine === null ) {
            $this->validation_engine = ValidationEngine::get_instance();
        }
        return $this->validation_engine;
    }

    /**
     * Get conditional renderer instance (lazy loading)
     *
     * Provides singleton access to the ConditionalRenderer instance,
     * initializing it only when first needed.
     *
     * @return \UltraguardPro\view\ConditionalRenderer
     * @access protected
     */
    protected function get_conditional_renderer() {
        if ( $this->conditional_renderer === null ) {
            $this->conditional_renderer = ConditionalRenderer::get_instance();
        }
        return $this->conditional_renderer;
    }

    /**
     * Clear internal caches
     *
     * Clears cached tab visibility and validation rules.
     * Useful when form context changes between renders.
     *
     * @return void
     * @access public
     */
    public function clear_cache() {
        $this->tab_visibility_cache = array();
        $this->cached_validation_rules = null;
    }
}
