<?php
// Exit if accessed directly.
if (!defined('ABSPATH')) {
    exit; // Prevent direct access to the file.
}

// Check if the class already exists to avoid redeclaration.
if (!class_exists('IAFWZDESK_Form_Fields')) {
    class IAFWZDESK_Form_Fields
    {
        // Constructor for loading required dependencies, if any
        public function __construct()
        {
            // Add any necessary initialization here
        }

        /**
         * Retrieves fields for a specific Contact Form 7 form by form ID.
         *
         * @param int $form_id The ID of the Contact Form 7 form.
         * @return array Array of form fields, each containing the field name and type.
         */
        public function getContactForm7Fields($form_id)
        {
            $form_fields = [];

            // Load the Contact Form 7 form object using its ID
            $contact_form = WPCF7_ContactForm::get_instance($form_id);
            if ($contact_form) {
                // Get form tags (fields) using scan_form_tags method
                $form_tags = $contact_form->scan_form_tags();

                foreach ($form_tags as $tag) {

                    $key = $tag->name;
                    $label = $tag->name;
                    $type = $tag->type;

                    // Check if both name and type are not empty
                    if (!empty($key) && !empty($type)) {
                        // Map Contact Form 7 field types to HTML input types
                        $field_type = $this->mapCF7TypeToInputType($type);
                        $form_fields[] = [
                            'key' => $key, // Field slug
                            'label' => $label, // Field slug
                            'type' => $field_type,
                            'source' => 'form'
                        ];
                    }
                }
            }

            return $form_fields;
        }


        /**
         * Retrieves fields for a specific WPForms form by form ID.
         *
         * @param int $form_id The ID of the WPForms form.
         * @return array Array of form fields, each containing the field name and type.
         */
        public function getWPFormsFields($form_id)
        {
            $form_fields = [];

            // Fetch the form using WPForms API
            $form = wpforms()->form->get($form_id);

            // Check if the form exists and retrieve its content
            if ($form && isset($form->post_content)) {
                // Decode the JSON content in post_content
                $content = json_decode($form->post_content, true);
                // Check if 'fields' exists in the decoded content and is an array
                if (isset($content['fields']) && is_array($content['fields'])) {

                    foreach ($content['fields'] as $field) {
                        $key = $field['id'];
                        $label = $field['label'];
                        $type = $field['type'];

                        // Check if the field is an address field
                        /*if ($type === 'address') {
                           foreach ($field as $sub_key => $sub_value) {
                               // Check if the sub_key contains "_placeholder"
                               if (strpos($sub_key, "_placeholder") !== false) {
                                   // Extract the field name before "_placeholder"
                                   $address_field_name = str_replace("_placeholder", "", $sub_key);

                                   // Add the field details to the form_fields array
                                   $form_fields[] = [
                                       'key' => $key . "_" . $address_field_name,
                                       'label' => ucfirst($address_field_name), // Capitalize the first letter
                                       'type' => $type,
                                       'source' => 'form'
                                   ];
                               }
                           }
                       } else {*/
                        // For other fields, add them directly
                        $form_fields[] = [
                            'key' => $key,
                            'label' => $label,
                            'type' => $type,
                            'source' => 'form'
                        ];
                        // }
                    }
                }
            }
            return $form_fields;
        }

        /**
         * Retrieves fields for a specific Gravity Form by form ID.
         *
         * @param int $form_id The ID of the Gravity Form.
         * @return array Array of form fields, each containing the field name and type.
         */
        public function getGravityFormFields($form_id)
        {
            $form_fields = [];

            // Check if Gravity Forms is active and accessible
            if (class_exists('GFAPI')) {
                // Fetch the form using Gravity Forms API
                $form = GFAPI::get_form($form_id);

                // Check if the form exists and has fields
                if ($form && isset($form['fields']) && is_array($form['fields'])) {

                    foreach ($form['fields'] as $field) {
                        $type = $field->type;
                        // Skip processing for sections
                        if ($type !== "section") {
                            // Check if $field->inputs is valid and iterable
                            if (!empty($field->inputs) && is_array($field->inputs)) {
                                foreach ($field->inputs as $input) {
                                    $key = $input['id'];
                                    $label = $input['label'];
                                    if ((!isset($input['isHidden']) || $input['isHidden'] != 1) && strpos($input['autocompleteAttribute'], 'honorific') === false) {
                                        $form_fields[] = [
                                            'key' => $key,
                                            'label' => $label,
                                            'type' => $type,
                                            'source' => 'form',
                                        ];
                                    }
                                }
                            } else {
                                // Default case when $field->inputs is not valid
                                $key = $field->id; // Field label used as key
                                $label = $field->label;

                                $form_fields[] = [
                                    'key' => $key,
                                    'label' => $label,
                                    'type' => $type,
                                    'source' => 'form'
                                ];
                            }
                        }
                    }
                }
            }
            return $form_fields;
        }

        /**
         * Retrieves fields for a specific Ninja Form by form ID.
         *
         * @param int $form_id The ID of the Ninja Form.
         * @return array Array of form fields, each containing the field name and type.
         */
        public function getNinjaFormFields($form_id)
        {
            $form_fields = [];

            // Check if Ninja Forms is active and accessible
            if (class_exists('Ninja_Forms')) {
                // Fetch the form model using Ninja Forms API
                $form = Ninja_Forms()->form()->get($form_id);

                // Check if the form exists
                if ($form) {
                    // Retrieve the fields associated with the form
                    $fields = Ninja_Forms()->form($form_id)->get_fields();

                    // Iterate over each field
                    foreach ($fields as $field) {
                        // Get the field label and type
                        $key = $field->get_setting('key');
                        $label = $field->get_setting('label');
                        $type = $field->get_setting('type');
                        if ($key && $key !== "submit") {
                            // Append the field details to the form_fields array
                            $form_fields[] = [
                                'key' => $key, // Field slug
                                'label' => $label, // Field slug
                                'type' => $type,
                                'source' => 'form'
                            ];
                        }
                    }
                }
            }
            return $form_fields;
        }


        /**
         * Retrieves fields for a specific Formidable Form by form ID.
         *
         * @param int $form_id The ID of the Formidable Form.
         * @return array Array of form fields, each containing the field name and type.
         */
        public function getFormidableFormFields($form_id)
        {
            $form_fields = [];

            // Check if Formidable Forms is active and accessible
            if (class_exists('FrmForm') && class_exists('FrmField')) {
                // Fetch the form fields using Formidable Forms API
                $fields = FrmField::get_all_for_form($form_id);

                // Check if fields were retrieved
                if (!empty($fields) && is_array($fields)) {
                    foreach ($fields as $field) {
                        // Get the field name (label) and type
                        $key = $field->id;
                        $label = $field->name;
                        $type = $field->type;
                        if ($type != "submit") {
                            if ($type === "address" || $type === "name") {
                                foreach ($field->default_value as $addresskey => $addressvalue) {
                                    $label = isset($field->field_options[$addresskey . '_desc']) && !empty($field->field_options[$addresskey . '_desc'])
                                        ? $field->field_options[$addresskey . '_desc']
                                        : $addresskey;

                                    $form_fields[] = [
                                        'key' => $field->id . "_" . $addresskey, // Field slug
                                        'label' => $label, // Use description if available and not empty, fallback to key
                                        'type' => $type,
                                        'source' => 'form'
                                    ];
                                }
                            } else {
                                $form_fields[] = [
                                    'key' => $key, // Field slug
                                    'label' => $label, // Field slug
                                    'type' => $type,
                                    'source' => 'form'
                                ];
                            }
                        }
                    }
                }
            }
            return $form_fields;
        }
        /**
         * Retrieves fields for a specific Everest Form by form ID.
         *
         * @param int $form_id The ID of the Everest Form.
         * @return array Array of form fields, each containing the field name and type.
         */
        /**
         * Retrieves fields for a specific Everest Form by form ID.
         *
         * @param int $form_id The ID of the Everest Form.
         * @return array Array of form fields, each containing the field name and type.
         */
        public function getEverestFormFields($form_id)
        {
            $form_fields = [];
            // Check if Everest Forms is active and accessible
            // Retrieve the form post object directly
            $form_post = get_post($form_id);
            // Check if the form post exists and has content
            if ($form_post && isset($form_post->post_content)) {
                // Decode the JSON content in post_content
                $content = json_decode($form_post->post_content, true);

                // Check if 'form_fields' exists in the decoded content and is an array
                if (isset($content['form_fields']) && is_array($content['form_fields'])) {

                    foreach ($content['form_fields'] as $field_id => $field) {

                        $key = $field['id'];
                        $label = $field['label'];
                        $type = $field['type'];

                        $form_fields[] = [
                            'key' => $key, // Field slug
                            'label' => $label, // Field slug
                            'type' => $type,
                            'source' => 'form'
                        ];
                    }
                } else {
                }
            }


            return $form_fields;
        }


        /**
         * Retrieves fields for a specific Elementor Form by form ID.
         *
         * @param string $form_id The ID of the Elementor Form.
         * @return array Array of form fields, each containing the field ID, label, and type.
         */
        public function getElementorFormFields($combined_id)
        {
            $empty = [];

            // Require Elementor Core + Pro
            if (! did_action('elementor/loaded') || ! defined('ELEMENTOR_PRO_VERSION')) {
                return $empty;
            }

            try {
                // Expect "{post_id}_{form_widget_id}" (widget id may contain underscores → limit=2)
                $parts = explode('_', (string) $combined_id, 2);
                if (count($parts) < 2) return $empty;

                $post_id        = (int) $parts[0];
                $form_widget_id = trim((string) $parts[1]);
                if ($post_id <= 0 || $form_widget_id === '') return $empty;

                // Prefer _elementor_data; fallback to post_content
                $raw = get_post_meta($post_id, '_elementor_data', true);
                if (! is_string($raw) || $raw === '') {
                    $raw = (string) get_post_field('post_content', $post_id);
                    if ($raw === '') return $empty;
                }

                // Tolerant decode (no pre-unslash)
                $data = $this->decode_elementor_json($raw);
                if (! is_array($data)) return $empty;

                // Walk the structure to find the exact form widget
                $fields_out   = [];
                $iterator = new RecursiveIteratorIterator(
                    new RecursiveArrayIterator($data),
                    RecursiveIteratorIterator::SELF_FIRST
                );

                foreach ($iterator as $node) {
                    if (
                        is_array($node)
                        && ($node['elType'] ?? null) === 'widget'
                        && ($node['widgetType'] ?? null) === 'form'
                        && ($node['id'] ?? null) === $form_widget_id
                    ) {
                        $form_fields = $node['settings']['form_fields'] ?? [];
                        if (! is_array($form_fields)) break;

                        foreach ($form_fields as $field) {
                            if (! is_array($field)) continue;

                            $type = (string) ($field['field_type'] ?? 'text');

                            // Skip internal/non-mappable types
                            if (in_array($type, ['step', 'html', 'recaptcha', 'recaptcha_v3', 'honeypot'], true)) {
                                continue;
                            }

                            $key = isset($field['_id']) ? (string) $field['_id'] : '';
                            if ($key === '') continue;

                            $label = (string) ($field['field_label'] ?? '');
                            if ($label === '') $label = ucfirst($type);

                            $fields_out[] = [
                                'key'    => $key,
                                'type'   => $type,
                                'label'  => $label,
                                'source' => 'form',
                            ];
                        }
                        break; // matched widget found; stop scanning
                    }
                }

                return $fields_out;
            } catch (Throwable $e) {
                return $empty; // fail safe
            }
        }
        private function decode_elementor_json($raw)
        {
            $data = json_decode($raw, true);
            if (is_array($data)) return $data;

            if (function_exists('wp_unslash')) {
                $data = json_decode(wp_unslash($raw), true);
                if (is_array($data)) return $data;
            }

            if (function_exists('mb_convert_encoding')) {
                $fixed = mb_convert_encoding($raw, 'UTF-8', 'UTF-8');
                $data  = json_decode($fixed, true);
                if (is_array($data)) return $data;
            }

            return null;
        }
        /**
         * Maps Contact Form 7 field types to HTML input types.
         *
         * @param string $cf7_type The Contact Form 7 field type.
         * @return string HTML input type.
         */
        private function mapCF7TypeToInputType($cf7_type)
        {
            $mapping = [
                'text' => 'text',
                'email' => 'email',
                'tel' => 'tel',
                'textarea' => 'textarea',
                'radio' => 'radio',
                'checkbox' => 'checkbox',
                'select' => 'select',
                'date' => 'date',
                'number' => 'number',
            ];
            return $mapping[$cf7_type] ?? 'text';
        }

        /**
         * Retrieves form fields by form ID, depending on the form type.
         *
         * @param string $form_type The type of form ('cf7' or 'wpforms').
         * @param int $form_id The ID of the form.
         * @return array Array of form fields, each containing the field name and type.
         */
        public function getFormFields($form_type, $form_id)
        {
            // Initialize an array to hold form fields based on form type
            $form_fields = [];

            // Retrieve fields based on form type
            if ($form_type === 1) {
                $form_fields = $this->getContactForm7Fields($form_id);
            } elseif ($form_type === 2) {
                $form_fields = $this->getWPFormsFields($form_id);
            } elseif ($form_type === 3) {
                $form_fields = $this->getGravityFormFields($form_id);
            } elseif ($form_type === 5) {
                $form_fields = $this->getFormidableFormFields($form_id);
            } elseif ($form_type === 7) {
                // Uncomment if Elementor form fields function is added
                $form_fields = $this->getElementorFormFields($form_id);
            }

            // Define common UTM fields with default type as 'text'
            $utm_fields = [
                [
                    'key' => 'iafwzdesk_custom_value',
                    'label' => 'Custom value',
                    'type' => 'text',
                    'source' => 'custom'
                ],
                // [
                //     'key' => 'iafwzdesk_integration_name',
                //     'label' => 'Integration name',
                //     'type' => 'tracking_text',
                //     'source' => 'custom'
                // ],
                // [
                //     'key' => 'iafwzdesk_form_name',
                //     'label' => 'Form name',
                //     'type' => 'tracking_text',
                //     'source' => 'custom'
                // ],
                [
                    'key' => 'iafwzdesk_entry_added_time',
                    'label' => 'Entry added time',
                    'type' => 'tracking_text',
                    'source' => 'custom'
                ],
                [
                    'key' => 'iafwzdesk_city',
                    'label' => 'City',
                    'type' => 'tracking_text',
                    'source' => 'custom'
                ],
                [
                    'key' => 'iafwzdesk_state',
                    'label' => 'State',
                    'type' => 'tracking_text',
                    'source' => 'custom'
                ],
                [
                    'key' => 'iafwzdesk_country',
                    'label' => 'Country',
                    'type' => 'tracking_text',
                    'source' => 'custom'
                ],
                [
                    'key' => 'iafwzdesk_page_url',
                    'label' => 'Page URL',
                    'type' => 'tracking_text',
                    'source' => 'custom'
                ],
                [
                    'key' => 'iafwzdesk_utm_source',
                    'label' => 'utm_source',
                    'type' => 'tracking_text',
                    'source' => 'custom'
                ],
                [
                    'key' => 'iafwzdesk_utm_medium',
                    'label' => 'utm_medium',
                    'type' => 'tracking_text',
                    'source' => 'custom'
                ],
                [
                    'key' => 'iafwzdesk_utm_campaign',
                    'label' => 'utm_campaign',
                    'type' => 'tracking_text',
                    'source' => 'custom'
                ],
                [
                    'key' => 'iafwzdesk_utm_term',
                    'label' => 'utm_term',
                    'type' => 'tracking_text',
                    'source' => 'custom'
                ],
                [
                    'key' => 'iafwzdesk_utm_content',
                    'label' => 'utm_content',
                    'type' => 'tracking_text',
                    'source' => 'custom'
                ]
            ];


            // Append UTM fields to the form fields array
            $form_fields = array_merge($form_fields, $utm_fields);

            return $form_fields;
        }
    }
    $IAFWZDESK_Form_FieldsInstance = new IAFWZDESK_Form_Fields();
}
