<?php

namespace GriffinForms\Admin\Secure;

class Field extends \GriffinForms\Admin\Secure\Format
{
    protected function secureFieldType($value)
    {
        $field_types = $this->config->getFieldTypes();
        if (in_array($value, $field_types)) {
            return $value;
        } else {
            return $field_types[0];
        }
    }    
    
    protected function secureIsRequired($value)
    {
        return $this->secureToggle($value);
    }    
    
    protected function secureIsReadonly($value)
    {
        return $this->secureToggle($value);
    }    
    
    protected function secureIsDisabled($value)
    {
        return $this->secureToggle($value);
    }    
    
    protected function secureIsHidden($value)
    {
        return $this->secureToggle($value);
    }    
    
    protected function secureIsReusable($value)
    {
        return $this->secureToggle($value);
    }    
    
    protected function secureIsGet($value)
    {
        return $this->secureToggle($value);
    }    
    
    protected function secureGetName($value)
    {
        return sanitize_text_field($value);
    }      
    
    protected function secureDefaultValue($value)
    {   
        $value_type_options = $this->choices->getChoices('default_value_type_' . $this->data['field_type'], false);
        $value_variable_options = $this->choices->getChoices('variable_values_' . $this->data['field_type'], false);
                
        $secured_value = array();
        
        if (!is_array($value)) {
            $secured_value['value_type'] = $value_type_options[0];
            return $secured_value;
        }
        
        if (key_exists('value_type', $value) and in_array($value['value_type'], $value_type_options)) {
            $secured_value['value_type'] = $value['value_type'];
        } else {
            $secured_value['value_type'] = $value_type_options[0];
        }
    
        if (key_exists('custom', $value)) {
            $secured_value['custom'] = sanitize_text_field($value['custom']);
        } else {
            $secured_value['custom'] = '';
        }
    
        if (key_exists('variable', $value)) {
            if (in_array($value['variable'], $value_variable_options)) {
                $secured_value['variable'] = $value['variable'];
            } else {
                $secured_value['variable'] = $value_variable_options[0];
            }
        } else {
            $secured_value['variable'] = $value_variable_options[0];
        }
    
        if (key_exists('get_value', $value)) {
            $secured_value['get_value'] = $this->secureToggle($value['get_value']);
        } else {
            $secured_value['get_value'] = 0;
        }
    
        if (key_exists('get_name', $value)) {
            $secured_value['get_name'] = $this->secureName($value['get_name']);
        } else {
            $secured_value['get_name'] = '';
        }
        
        return $secured_value;
    }
    
    protected function secureInputrichtextSettings($value)
    {
        $allowed_toolbar = [
            'bold', 'italic', 'underline', 'strike',
            'heading1', 'heading2', 'heading3',
            'bulletlist', 'orderedlist', 'blockquote',
            'code', 'link', 'horizontalrule', 'clearformatting',
        ];

        $s = is_array($value) ? $value : [];

        $raw_toolbar = is_array($s['toolbar'] ?? null) ? $s['toolbar'] : [];
        $toolbar = array_values(array_filter($raw_toolbar, static function ($item) use ($allowed_toolbar) {
            return in_array($item, $allowed_toolbar, true);
        }));

        $placeholder = sanitize_text_field((string) ($s['placeholder'] ?? 'Write something…'));

        $min_height = absint($s['min_height'] ?? 160);
        if ($min_height < 50) {
            $min_height = 160;
        }

        $max_height = absint($s['max_height'] ?? 0);
        if ($max_height > 0 && $max_height < $min_height) {
            $max_height = 0;
        }

        $max_characters = absint($s['max_characters'] ?? 0);

        return [
            'toolbar'        => $toolbar,
            'placeholder'    => $placeholder,
            'min_height'     => $min_height,
            'max_height'     => $max_height,
            'max_characters' => $max_characters,
        ];
    }

    protected function secureInputlikertSettings($value)
    {
        $s = is_array($value) ? $value : [];
        error_log('Griffin Assist likert secureInputlikertSettings input: ' . wp_json_encode($s, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));

        $raw_rows = is_array($s['rows'] ?? null) ? $s['rows'] : [];
        $rows = [];
        foreach ($raw_rows as $row) {
            if (!is_array($row) || !isset($row['id'], $row['label'])) continue;
            $rows[] = [
                'id'    => sanitize_key((string) $row['id']),
                'label' => sanitize_text_field((string) $row['label']),
            ];
        }
        $rows = array_slice($rows, 0, 20);

        $raw_cols = is_array($s['columns'] ?? null) ? $s['columns'] : [];
        $columns = [];
        foreach ($raw_cols as $col) {
            if (!is_array($col) || !isset($col['id'], $col['label'])) continue;
            $columns[] = [
                'id'    => sanitize_key((string) $col['id']),
                'label' => sanitize_text_field((string) $col['label']),
            ];
        }
        if (count($columns) < 2) {
            $columns = [
                ['id' => 'col_1', 'label' => 'Strongly Disagree'],
                ['id' => 'col_2', 'label' => 'Strongly Agree'],
            ];
        }
        $columns = array_slice($columns, 0, 10);

        $allowed_req_modes    = ['all', 'none'];
        $allowed_col_widths   = ['auto', 'equal'];

        $secured = [
            'rows'          => $rows,
            'columns'       => $columns,
            'allow_na'      => !empty($s['allow_na']),
            'required_mode' => in_array($s['required_mode'] ?? '', $allowed_req_modes, true) ? $s['required_mode'] : 'all',
            'column_width'  => in_array($s['column_width']  ?? '', $allowed_col_widths, true) ? $s['column_width'] : 'auto',
        ];
        error_log('Griffin Assist likert secureInputlikertSettings output: ' . wp_json_encode($secured, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));

        return $secured;
    }

    protected function secureImageselectionSettings($value)
    {
        $s = is_array($value) ? $value : [];

        $raw_options = is_array($s['options'] ?? null) ? $s['options'] : [];
        $options = [];
        $none_option_taken = false;

        foreach ($raw_options as $option) {
            if (!is_array($option)) {
                continue;
            }

            $value_key = sanitize_key((string) ($option['value'] ?? ''));
            if ($value_key === '') {
                continue;
            }

            $is_none_option = !empty($option['is_none_option']) && !$none_option_taken;
            if ($is_none_option) {
                $none_option_taken = true;
            }

            $options[] = [
                'image_id' => absint($option['image_id'] ?? 0),
                'image_url' => esc_url_raw((string) ($option['image_url'] ?? '')),
                'title' => sanitize_text_field((string) ($option['title'] ?? '')),
                'description' => sanitize_text_field((string) ($option['description'] ?? '')),
                'value' => $value_key,
                'is_none_option' => $is_none_option,
            ];
        }

        $allowed_values = array_map(static function ($option) {
            return $option['value'];
        }, $options);

        $aspect_ratio = sanitize_key((string) ($s['aspect_ratio'] ?? '1:1'));
        if (!in_array($aspect_ratio, array('1:1', '4:3', '16:9', '3:2', 'free'), true)) {
            $aspect_ratio = '1:1';
        }

        $default_selected = [];
        if (is_array($s['default_selected'] ?? null)) {
            foreach ($s['default_selected'] as $selected) {
                $selected_key = sanitize_key((string) $selected);
                if ($selected_key !== '' && in_array($selected_key, $allowed_values, true)) {
                    $default_selected[] = $selected_key;
                }
            }
        }

        return [
            'options' => $options,
            'columns_desktop' => max(1, min(6, absint($s['columns_desktop'] ?? 3))),
            'columns_mobile' => max(1, min(3, absint($s['columns_mobile'] ?? 2))),
            'show_title' => !empty($s['show_title']),
            'show_description' => !empty($s['show_description']),
            'aspect_ratio' => $aspect_ratio,
            'randomise' => !empty($s['randomise']),
            'default_selected' => array_values(array_unique($default_selected)),
        ];
    }

    protected function secureSignatureSettings($value)
    {
        $s = is_array($value) ? $value : [];

        $pad_height = absint($s['pad_height'] ?? 0);
        if ($pad_height < 50 || $pad_height > 600) {
            $pad_height = 200;
        }

        $pen_color = sanitize_hex_color((string) ($s['pen_color'] ?? ''));
        if (!$pen_color) {
            $pen_color = '#000000';
        }

        $pen_thickness = absint($s['pen_thickness'] ?? 0);
        if ($pen_thickness < 1 || $pen_thickness > 10) {
            $pen_thickness = 2;
        }

        $bg_color = sanitize_hex_color((string) ($s['bg_color'] ?? ''));
        if (!$bg_color) {
            $bg_color = '#ffffff';
        }

        return [
            'pad_height'            => $pad_height,
            'pen_color'             => $pen_color,
            'pen_thickness'         => $pen_thickness,
            'bg_color'              => $bg_color,
            'signature_placeholder' => sanitize_text_field($s['signature_placeholder'] ?? ''),
        ];
    }

    protected function secureInputratingSettings($value)
    {
        $s = is_array($value) ? $value : [];
        $scale = absint($s['scale'] ?? 5);
        if ($scale < 2 || $scale > 10) {
            $scale = 5;
        }

        $icon_group = sanitize_key((string) ($s['icon_group'] ?? 'star'));
        if (!in_array($icon_group, ['star', 'heart', 'thumb', 'face', 'circle', 'flag', 'bolt', 'diamond', 'custom'], true)) {
            $icon_group = 'star';
        }

        $icon_size = max(16, min(64, absint($s['icon_size'] ?? 32)));
        $icon_spacing = max(0, min(24, absint($s['icon_spacing'] ?? 4)));
        $color_filled = sanitize_hex_color((string) ($s['color_filled'] ?? '')) ?: '#f5a623';
        $color_empty = sanitize_hex_color((string) ($s['color_empty'] ?? '')) ?: '#d1d5db';

        $step_image_ids = [];
        foreach (array_slice((array) ($s['step_image_ids'] ?? []), 0, $scale) as $id) {
            $step_image_ids[] = absint($id);
        }
        while (count($step_image_ids) < $scale) {
            $step_image_ids[] = 0;
        }

        $step_labels = [];
        foreach (array_slice((array) ($s['step_labels'] ?? []), 0, $scale) as $label) {
            $step_labels[] = sanitize_text_field((string) $label);
        }
        while (count($step_labels) < $scale) {
            $step_labels[] = '';
        }

        return [
            'scale' => $scale,
            'icon_group' => $icon_group,
            'icon_size' => $icon_size,
            'icon_spacing' => $icon_spacing,
            'color_filled' => $color_filled,
            'color_empty' => $color_empty,
            'custom_image_id' => absint($s['custom_image_id'] ?? 0),
            'step_image_ids' => $step_image_ids,
            'step_labels' => $step_labels,
            'allow_clear' => !empty($s['allow_clear']) ? 1 : 0,
        ];
    }

    protected function securePlaceholder($value)
    {
        return sanitize_text_field($value);
    }
    
    protected function secureAutocomplete($value)
    {
        return $this->secureToggle($value);
    }
    
    protected function secureIterations($value)
    {
        
    	$secured_value = array();
    
    	if (!is_array($value) or !key_exists('allow', $value)) {
    		return $secured_value['allow'] = 0;
    	} else {
    		$secured_value['allow'] = $this->secureToggle($value['allow']);
    	}
    	    	
    	if ($secured_value['allow'] == 1) {
    	    	
    		if (key_exists('min', $value)) {
    			$secured_value['min'] = absint($value['min']);
    		} else {
    			$secured_value['min'] = 0;
    		}
    		
    		if (key_exists('max', $value)) {
    			$secured_value['max'] = absint($value['max']);
    			
    			if ($secured_value['max'] < $secured_value['min']) {
    				$secured_value['max'] = $secured_value['min'];
    			}
    			
    		} else {
    			$secured_value['max'] = '';
    		}
    		
    		if (key_exists('unique', $value)) {
    			$secured_value['unique'] = $this->secureToggle($value['unique']);
    		} else {
    			$secured_value['unique'] = 0;
    		}
    		
    		if (key_exists('add_button_label', $value)) {
    			$secured_value['add_button_label'] = sanitize_text_field($value['add_button_label']);
    		} else {
    			$secured_value['add_button_label'] = '';
    		}
    	}
    	
    	return $secured_value;
    }
    
    protected function secureValidations($value)
    {
        $validation_type_options = $this->choices->getChoices('validation_types_' . $this->data['field_type']);
        $match_type_options = $this->choices->getChoices('match_type');
        
    	$secured_value = array();
    	
        if (!is_array($validation_type_options) || empty($validation_type_options)) {
            return $secured_value;
        }

    	if (!is_array($value) or !isset($value['type']) or !in_array($value['type'], array_keys($validation_type_options))) {

    		$secured_value['type'] = array_key_first($validation_type_options);
    		return $secured_value;
    		
    	} else {
            
            $secured_value['type'] = $value['type'];
            
        }
    	
        if ($secured_value['type'] === 'min_rating') {
            if (isset($value['validation_value']) && is_numeric($value['validation_value'])) {
                $secured_value['validation_value'] = floatval($value['validation_value']);
            }
        }

        if ($secured_value['type'] === 'min_max_select' && $this->data['field_type'] === 'imageselection') {
            if (key_exists('min_selections', $value) && is_numeric($value['min_selections'])) {
                $secured_value['min_selections'] = absint($value['min_selections']);
            }

            if (key_exists('max_selections', $value) && is_numeric($value['max_selections'])) {
                $secured_value['max_selections'] = absint($value['max_selections']);
            }
        }

    	if ($secured_value['type'] === 'pattern') {
            
    		if (key_exists('pattern', $value)) {
    			$secured_value['pattern'] = sanitize_text_field($value['pattern']);
    		} else {
    			$secured_value['pattern'] = '';
    		}
    	}
    	
    	if ($secured_value['type'] === 'custom-parameters') {
    	
    		if ($this->data['field_type'] === 'textarea') {
                if (key_exists('min_chars', $value) and is_numeric($value['min_chars'])) {
                    $secured_value['min_chars'] = $value['min_chars'];
                }

                if (key_exists('max_chars', $value) and is_numeric($value['max_chars'])) {
                    $secured_value['max_chars'] = $value['max_chars'];
                }
            }

    		if ($this->data['field_type'] === 'inputcheckbox') {
                if (key_exists('min_checks', $value) and is_numeric($value['min_checks'])) {
                    $secured_value['min_checks'] = $value['min_checks'];
                }

                if (key_exists('max_checks', $value) and is_numeric($value['max_checks'])) {
                    $secured_value['max_checks'] = $value['max_checks'];
                }
            }
            
    		if ($this->data['field_type'] === 'inputnumber') {
                if (key_exists('min', $value) and is_numeric($value['min'])) {
                    $secured_value['min'] = $value['min'];
                }

                if (key_exists('max', $value) and is_numeric($value['max'])) {
                    $secured_value['max'] = $value['max'];
                }
            }
            
            if ($this->data['field_type'] === 'inputpassword') {
                $allowed_sets = array('uppercase', 'lowercase', 'numbers', 'symbols', 'spaces');

                if (isset($value['min']) && is_numeric($value['min'])) {
                    $secured_value['min'] = absint($value['min']);
                }

                if (isset($value['max']) && is_numeric($value['max'])) {
                    $secured_value['max'] = absint($value['max']);
                }

                if (isset($value['allowed_sets']) && is_array($value['allowed_sets'])) {
                    $sets = array_values(array_intersect($value['allowed_sets'], $allowed_sets));
                    $secured_value['allowed_sets'] = !empty($sets) ? $sets : array('uppercase', 'lowercase', 'numbers', 'symbols');
                } else {
                    $secured_value['allowed_sets'] = array('uppercase', 'lowercase', 'numbers', 'symbols');
                }

                if (isset($value['required_sets']) && is_array($value['required_sets'])) {
                    $required = array_values(array_intersect($value['required_sets'], $allowed_sets));
                    $secured_value['required_sets'] = array_values(array_intersect($required, $secured_value['allowed_sets']));
                } else {
                    $secured_value['required_sets'] = array();
                }

                $secured_value['disallowed_chars'] = isset($value['disallowed_chars']) ? sanitize_text_field($value['disallowed_chars']) : '';

                if (isset($value['min_strength']) && in_array($value['min_strength'], array('weak', 'medium', 'strong', 'very_strong'), true)) {
                    $secured_value['min_strength'] = sanitize_text_field($value['min_strength']);
                } else {
                    $secured_value['min_strength'] = 'weak';
                }

                if (isset($value['messages']) && is_array($value['messages'])) {
                    $secured_value['messages'] = array();
                    foreach ($value['messages'] as $message_key => $message_value) {
                        $secured_value['messages'][$message_key] = sanitize_text_field($message_value);
                    }
                }
            }

            if ($this->data['field_type'] === 'inputpassword') {
                $allowed_sets = array('uppercase', 'lowercase', 'numbers', 'symbols', 'spaces');

                if (isset($value['min']) && is_numeric($value['min'])) {
                    $secured_value['min'] = absint($value['min']);
                }

                if (isset($value['max']) && is_numeric($value['max'])) {
                    $secured_value['max'] = absint($value['max']);
                }

                if (isset($value['allowed_sets']) && is_array($value['allowed_sets'])) {
                    $sets = array_values(array_intersect($value['allowed_sets'], $allowed_sets));
                    $secured_value['allowed_sets'] = !empty($sets) ? $sets : array('uppercase', 'lowercase', 'numbers', 'symbols');
                } else {
                    $secured_value['allowed_sets'] = array('uppercase', 'lowercase', 'numbers', 'symbols');
                }

                if (isset($value['required_sets']) && is_array($value['required_sets'])) {
                    $required = array_values(array_intersect($value['required_sets'], $allowed_sets));
                    $secured_value['required_sets'] = array_values(array_intersect($required, $secured_value['allowed_sets']));
                } else {
                    $secured_value['required_sets'] = array();
                }

                $secured_value['disallowed_chars'] = isset($value['disallowed_chars']) ? sanitize_text_field($value['disallowed_chars']) : '';

                $strength_options = array('weak', 'medium', 'strong', 'very_strong');
                $strength = isset($value['min_strength']) ? sanitize_text_field($value['min_strength']) : 'weak';
                $secured_value['min_strength'] = in_array($strength, $strength_options, true) ? $strength : 'weak';

                if (isset($value['messages']) && is_array($value['messages'])) {
                    $secured_value['messages'] = array();
                    foreach ($value['messages'] as $message_key => $message_value) {
                        $secured_value['messages'][$message_key] = sanitize_text_field($message_value);
                    }
                }
            }

            if ($this->data['field_type'] === 'inputtext') {
                if (key_exists('min', $value)) {
                    $secured_value['min'] = absint($value['min']);
                }

                if (key_exists('max', $value)) {
                    $secured_value['max'] = absint($value['max']);
                }
            }
            
            if ($this->data['field_type'] === 'inputtime') {
                if (key_exists('min', $value) && is_numeric($value['min'])) {
                    $secured_value['min'] = absint($value['min']);
                }

                if (key_exists('max', $value) && is_numeric($value['max'])) {
                    $secured_value['max'] = absint($value['max']);
                }
            }

    		if ($this->data['field_type'] === 'inputdate') {

                $secured_value['date_type'] = sanitize_text_field($value['date_type']);

                if ($secured_value['date_type'] === 'fixed_date') {

                    if (key_exists('min', $value)) {
                        $secured_value['min'] = sanitize_text_field($value['min']);
                    }

                    if (key_exists('max', $value)) {
                        $secured_value['max'] = sanitize_text_field($value['max']);
                    }

                } else if ($secured_value['date_type'] === 'relative_date') {
                    
                    // Validate and sanitize relative minimum date parameters (days, weeks, months, years)
                    // Only numeric values are accepted; others are skipped.
                    if (key_exists('relative_min', $value)) {
                        foreach (['days', 'weeks', 'months', 'years'] as $unit) {
                            if (isset($value['relative_min'][$unit]) && is_numeric($value['relative_min'][$unit])) {
                                $secured_value['relative_min'][$unit] = absint($value['relative_min'][$unit]);
                            }
                        }
                        $secured_value['relative_min']['date_logic'] = sanitize_text_field($value['relative_min']['date_logic'] ?? '');
                        $secured_value['relative_min']['date_variable'] = sanitize_text_field($value['relative_min']['date_variable'] ?? '');
                    }

                    // Validate and sanitize relative maximum date parameters (days, weeks, months, years)
                    // Only numeric values are accepted; others are skipped.
                    if (key_exists('relative_max', $value)) {
                        foreach (['days', 'weeks', 'months', 'years'] as $unit) {
                            if (isset($value['relative_max'][$unit]) && is_numeric($value['relative_max'][$unit])) {
                                $secured_value['relative_max'][$unit] = absint($value['relative_max'][$unit]);
                            }
                        }
                        $secured_value['relative_max']['date_logic'] = sanitize_text_field($value['relative_max']['date_logic'] ?? '');
                        $secured_value['relative_max']['date_variable'] = sanitize_text_field($value['relative_max']['date_variable'] ?? '');
                    }
                    
                }
                
                $secured_value['day_type'] = sanitize_text_field($value['day_type']);
                
            }

            if ($this->data['field_type'] === 'inputphone') {
                if (key_exists('min_digits', $value) && is_numeric($value['min_digits'])) {
                    $secured_value['min_digits'] = absint($value['min_digits']);
                }

                if (key_exists('max_digits', $value) && is_numeric($value['max_digits'])) {
                    $secured_value['max_digits'] = absint($value['max_digits']);
                }

                $format_options = $this->choices->getChoices('phone_format_type_' . $this->data['field_type']);
                $format_keys = array_keys($format_options);
                if (!empty($format_keys)) {
                    if (key_exists('format_type', $value) && in_array($value['format_type'], $format_keys, true)) {
                        $secured_value['format_type'] = sanitize_text_field($value['format_type']);
                    } else {
                        $secured_value['format_type'] = $format_keys[0];
                    }
                }

                $secured_value['allow_extension'] = key_exists('allow_extension', $value)
                    ? $this->secureToggle($value['allow_extension'])
                    : 0;

                if (key_exists('allowed_country_codes', $value) && is_array($value['allowed_country_codes'])) {
                    $codes = array();
                    foreach ($value['allowed_country_codes'] as $code) {
                        $code = ltrim((string) $code, '+');
                        $code = preg_replace('/\D/', '', $code);
                        if ($code !== '') {
                            $codes[] = $code;
                        }
                    }

                    if (!empty($codes)) {
                        $secured_value['allowed_country_codes'] = array_values(array_unique($codes));
                    }
                }
            }

            if ($this->data['field_type'] === 'inputaddress') {
                $mode_options = $this->choices->getChoices('country_filter_mode_inputaddress');
                $mode_keys = array_keys($mode_options);
                if (!empty($mode_keys)) {
                    if (key_exists('country_filter_mode', $value) && in_array($value['country_filter_mode'], $mode_keys, true)) {
                        $secured_value['country_filter_mode'] = sanitize_text_field($value['country_filter_mode']);
                    } else {
                        $secured_value['country_filter_mode'] = $mode_keys[0];
                    }
                } else {
                    $secured_value['country_filter_mode'] = 'all_countries';
                }

                $secured_value['allowed_countries'] = array();
                $secured_value['excluded_countries'] = array();

                if ($secured_value['country_filter_mode'] === 'limit_to_countries' && key_exists('allowed_countries', $value) && is_array($value['allowed_countries'])) {
                    $secured_value['allowed_countries'] = $this->sanitizeCountryCodes($value['allowed_countries']);
                }

                if ($secured_value['country_filter_mode'] === 'exclude_countries' && key_exists('excluded_countries', $value) && is_array($value['excluded_countries'])) {
                    $secured_value['excluded_countries'] = $this->sanitizeCountryCodes($value['excluded_countries']);
                }
            }
    		
    		if ($this->data['field_type'] === 'inputpassword') {
                $allowed_sets = array('uppercase', 'lowercase', 'numbers', 'symbols', 'spaces');

                if (isset($value['min']) && $value['min'] !== '' && is_numeric($value['min'])) {
                    $secured_value['min'] = absint($value['min']);
                }

                if (isset($value['max']) && $value['max'] !== '' && is_numeric($value['max'])) {
                    $secured_value['max'] = absint($value['max']);
                }

                if (isset($value['allowed_sets']) && is_array($value['allowed_sets'])) {
                    $sets = array_values(array_intersect($value['allowed_sets'], $allowed_sets));
                    $secured_value['allowed_sets'] = !empty($sets) ? $sets : array('uppercase', 'lowercase', 'numbers', 'symbols');
                } else {
                    $secured_value['allowed_sets'] = array('uppercase', 'lowercase', 'numbers', 'symbols');
                }

                if (isset($value['required_sets']) && is_array($value['required_sets'])) {
                    $secured_value['required_sets'] = array_values(array_intersect($value['required_sets'], $allowed_sets));
                } else {
                    $secured_value['required_sets'] = array();
                }

                if (!empty($secured_value['required_sets'])) {
                    $secured_value['required_sets'] = array_values(array_intersect($secured_value['required_sets'], $secured_value['allowed_sets']));
                }

                $secured_value['disallowed_chars'] = isset($value['disallowed_chars'])
                    ? sanitize_text_field($value['disallowed_chars'])
                    : '';

                $strength_options = array('weak', 'medium', 'strong', 'very_strong');
                $min_strength = isset($value['min_strength']) ? sanitize_text_field($value['min_strength']) : 'weak';
                $secured_value['min_strength'] = in_array($min_strength, $strength_options, true) ? $min_strength : 'weak';

                $secured_value['messages'] = array();
                if (isset($value['messages']) && is_array($value['messages'])) {
                    foreach ($value['messages'] as $message_key => $message_value) {
                        $secured_value['messages'][$message_key] = sanitize_text_field($message_value);
                    }
                }
            }

    		if (key_exists('allow_numbers', $value)) {
    			$secured_value['allow_numbers'] = $this->secureToggle($value['allow_numbers']);
    		}
    		
    		if (key_exists('allow_spaces', $value)) {
    			$secured_value['allow_spaces'] = $this->secureToggle($value['allow_spaces']);
    		}
    		
    		if (key_exists('allow_splchars', $value)) {
    			$secured_value['allow_splchars'] = $this->secureToggle($value['allow_splchars']);
    		}
    		
    		if (key_exists('exclude', $value)) {
    			$secured_value['exclude'] = sanitize_textarea_field($value['exclude']);    		
    		}
    		
    		if (key_exists('number_type', $value)) {
    			$secured_value['number_type'] = sanitize_text_field($value['number_type']);    		
    		}
    		
    		if (key_exists('allow_decimal', $value)) {
    			$secured_value['allow_decimal'] = $this->secureToggle($value['allow_decimal']);    		
    		}
    		
    		if (key_exists('is_restricted_domains', $value)) {
    			$secured_value['is_restricted_domains'] = $this->secureToggle($value['is_restricted_domains']);   
    		}
    		
    		if (key_exists('restricted_domains', $value)) {
                $secured_value['restricted_domains'] = array();
    			if (is_array($value['restricted_domains'])) {
                    foreach ($value['restricted_domains'] as $domain) {
                        $domain = trim($domain);
                        $secured_value['restricted_domains'][] = sanitize_text_field($domain);
                    }
                }
    		}
    		
    		if (key_exists('excluded_domains', $value)) {
                $secured_value['excluded_domains'] = array();
    			if (is_array($value['excluded_domains'])) {
                    foreach ($value['excluded_domains'] as $domain) {
                        $domain = trim($domain);
                        $secured_value['excluded_domains'][] = sanitize_text_field($domain);
                    }
                }
    		}
            
            if (key_exists('protocols', $value) and is_array($value['protocols'])) {
    			$secured_value['protocols'] = array_map('sanitize_text_field', $value['protocols']);
    		}
            
            
    		
    		if (key_exists('restricted_tld', $value)) {
                $secured_value['restricted_tld'] = array();
    			if (is_array($value['restricted_tld'])) {
                    foreach ($value['restricted_tld'] as $tld) {
                        $tld = trim($tld);
                        $secured_value['restricted_tld'][] = sanitize_text_field($tld);
                    }
                }
    		}
    		
    		if (key_exists('excluded_tld', $value)) {
                $secured_value['excluded_tld'] = array();
    			if (is_array($value['excluded_tld'])) {
                    foreach ($value['excluded_tld'] as $tld) {
                        $tld = trim($tld);
                        $secured_value['excluded_tld'][] = sanitize_text_field($tld);
                    }
                }
    		}
    	}
        
        if ($secured_value['type'] === 'multiples_of') {
            if (key_exists('multiples', $value) and is_array($value['multiples'])) {
                foreach ($value['multiples'] as $multiple) {
                    $multiple = trim($multiple);
                    if (is_numeric($multiple)) {
                        $secured_value['multiples'][] = $multiple;
                    }
                }
            } else {
                $secured_value['multiple'] = null;
            }
        }
    	
    	if ($secured_value['type'] === 'db-validate') {
    		
    		if (key_exists('table', $value)) {
    			$secured_value['table'] = sanitize_text_field($value['table']);    		
    		} else {
				$secured_value['table'] = '';
    		}
    		
    		if (key_exists('column', $value)) {
    			$secured_value['column'] = sanitize_text_field($value['column']);    		
    		} else {
				$secured_value['column'] = '';
    		}
    		
    		if (key_exists('match_type', $value) and in_array($value['match_type'], array_keys($match_type_options))) {
                
    			$secured_value['match_type'] = sanitize_text_field($value['match_type']); 
                
    		} else {
                
				$secured_value['match_type'] = array_key_first($match_type_options);
    		}    	
    	}
        
        return $secured_value;
    }
    
    protected function secureRelativeDate($value)
    {
        return $value;
    }

    private function sanitizeCountryCodes($codes)
    {
        $allowed_list = $this->choices->getChoices('address_countries', false);
        $allowed_codes = array();

        if (is_array($allowed_list)) {
            $allowed_codes = array_map('strtoupper', array_keys($allowed_list));
        }

        $sanitized = array();
        if (is_array($codes)) {
            foreach ($codes as $code) {
                $code = strtoupper(trim((string) $code));
                if (strlen($code) !== 2) {
                    continue;
                }
                if (!empty($allowed_codes) && !in_array($code, $allowed_codes, true)) {
                    continue;
                }
                $sanitized[] = $code;
            }
        }

        return array_values(array_unique($sanitized));
    }
    
    protected function secureFieldOptions($value)
    {
        if ($this->data['field_type'] === 'payment') {
            return $this->securePaymentFieldOptions($value);
        }

        $secured_value = array();
        
        if (is_array($value) and !empty($value)) {

            foreach ($value as $group => $pair) {

                $sanitized_group = sanitize_text_field($group);
                $secured_value[$sanitized_group] = array();

                // pair is either a legacy {label: value} object or an ordered [[label, value], ...] array
                $pairs = (isset($pair[0]) && is_array($pair[0]))
                    ? $pair
                    : array_map(null, array_keys($pair), array_values($pair));

                foreach ($pairs as $entry) {

                    $text  = isset($entry[0]) ? $entry[0] : '';
                    $val   = isset($entry[1]) ? $entry[1] : '';

                    $secured_option_text = sanitize_text_field($text);

                    if (empty($secured_option_text)) {
                        // Do not want empty options;
                        continue;
                    }

                    $secured_option_value = sanitize_text_field($val);

                    if (empty($secured_option_value)) {
                        // if option value is empty, it is auto-set from option text.
                        $secured_option_value = sanitize_text_field(str_replace(' ', '', strtolower($text)));
                    }

                    $secured_value[$sanitized_group][$secured_option_text] = $secured_option_value;
                }
            }
        }
        
        return $secured_value;
    }

    protected function securePaymentFieldOptions($value)
    {
        $secured = array();

        if (!is_array($value)) {
            return $secured;
        }

        foreach ($value as $product) {
            if (!is_array($product)) {
                continue;
            }

            $name = sanitize_text_field($product['name'] ?? '');
            if ($name === '') {
                continue;
            }

            $sku = sanitize_text_field($product['sku'] ?? '');
            $product_id = $sku !== '' ? $sku : 'prod_' . wp_generate_password(6, false, false);

            $min_qty = max(1, absint($product['min_qty'] ?? 1));
            $max_candidate = absint($product['max_qty'] ?? $min_qty);
            $max_qty = $max_candidate >= $min_qty ? $max_candidate : $min_qty;
            $default_qty = max(1, absint($product['default_qty'] ?? 1));
            if ($default_qty < $min_qty) {
                $default_qty = $min_qty;
            }
            if ($default_qty > $max_qty) {
                $default_qty = $max_qty;
            }

            $secured[] = array(
                'id'             => $product_id,
                'name'           => $name,
                'price'          => isset($product['price']) ? floatval($product['price']) : 0,
                'description'    => sanitize_textarea_field($product['description'] ?? ''),
                'image'          => esc_url_raw($product['image'] ?? ''),
                'link'           => esc_url_raw($product['link'] ?? ''),
                'default_qty'    => $default_qty,
                'min_qty'        => $min_qty,
                'max_qty'        => $max_qty,
                'allow_quantity' => !empty($product['allow_quantity']) ? 1 : 0,
                'featured'       => !empty($product['featured']) ? 1 : 0,
            );
        }

        return $secured;
    }

    protected function secureFieldSettings($value)
    {
        $method = 'secure' . $this->data['field_type'] . 'Settings';

        if (method_exists($this, $method)) {
            return $this->$method($value);
        }
    }

    protected function securePaymentSettings($value)
    {
        $secured = array();
        $allowed_layouts = array('cards', 'list', 'minimal');
        $layout = isset($value['layout']) ? sanitize_text_field($value['layout']) : 'cards';
        $secured['layout'] = in_array($layout, $allowed_layouts, true) ? $layout : 'cards';
        $secured['allow_quantity_controls'] = isset($value['allow_quantity_controls']) ? $this->secureToggle($value['allow_quantity_controls']) : 1;
        $secured['show_images'] = isset($value['show_images']) ? $this->secureToggle($value['show_images']) : 1;
        $secured['show_descriptions'] = isset($value['show_descriptions']) ? $this->secureToggle($value['show_descriptions']) : 1;
        $secured['show_prices'] = isset($value['show_prices']) ? $this->secureToggle($value['show_prices']) : 1;
        $min_select = isset($value['min_select']) ? absint($value['min_select']) : 0;
        $max_select = isset($value['max_select']) ? absint($value['max_select']) : 0;
        if ($max_select > 0 && $max_select < $min_select) {
            $max_select = $min_select;
        }
        $secured['min_select'] = $min_select;
        $secured['max_select'] = $max_select;

        $allowed_modes = array('inherit', 'custom');
        $mode = isset($value['tax_mode']) ? sanitize_text_field($value['tax_mode']) : 'inherit';
        $mode = in_array($mode, $allowed_modes, true) ? $mode : 'inherit';
        $secured['tax_mode'] = $mode;

        if ($mode === 'custom') {
            $allowed_types = array('percentage', 'fixed');
            $type = isset($value['tax_rate_type']) ? sanitize_text_field($value['tax_rate_type']) : 'percentage';
            $type = in_array($type, $allowed_types, true) ? $type : 'percentage';
            $rate_value = isset($value['tax_rate_value']) ? (float) $value['tax_rate_value'] : 0;
            if ($rate_value < 0) {
                $rate_value = 0;
            }
            $label = isset($value['tax_display_label']) ? sanitize_text_field($value['tax_display_label']) : '';
            if ($label === '') {
                $label = __('Tax', 'griffinforms-form-builder');
            }
            $registration_label = isset($value['tax_registration_label']) ? sanitize_text_field($value['tax_registration_label']) : '';
            $registration_number = isset($value['tax_registration_number']) ? sanitize_text_field($value['tax_registration_number']) : '';

            $secured['tax_rate_type'] = $type;
            $secured['tax_rate_value'] = $rate_value;
            $secured['tax_display_label'] = $label;
            $secured['tax_registration_label'] = $registration_label;
            $secured['tax_registration_number'] = $registration_number;
        } else {
            $secured['tax_rate_type'] = '';
            $secured['tax_rate_value'] = '';
            $secured['tax_display_label'] = '';
            $secured['tax_registration_label'] = '';
            $secured['tax_registration_number'] = '';
        }

        return $secured;
    }

    protected function secureInputDateSettings($value)
    {
        $secured_value = array();

        $date_format_options = $this->choices->getChoices('date_format');
        $date_format = isset($value['date_format']) ? $value['date_format'] : '';

        if (empty($date_format) or !in_array($date_format, $date_format_options)) {
            $secured_value['date_format'] = array_key_first($date_format_options);
        } else {
            $secured_value['date_format'] = sanitize_text_field($value['date_format']);
        }

        return $secured_value;

    }

    protected function secureInputPhoneSettings($value)
    {
        $secured_value = array();
        $options = $this->choices->getChoices('phone_display_mode_inputphone');
        $allowed = is_array($options) ? array_keys($options) : array('flag_code', 'code_only', 'flag_code_name');
        $mode = isset($value['phone_display_mode']) ? sanitize_text_field($value['phone_display_mode']) : 'flag_code';
        $secured_value['phone_display_mode'] = in_array($mode, $allowed, true) ? $mode : 'flag_code';
        return $secured_value;
    }

    protected function secureInputTimeSettings($value)
    {
        // No field settings for InputTime - HTML5 time input uses browser locale
        return array();
    }

    protected function secureInputPasswordSettings($value)
    {
        $secured_value = array();

        $secured_value['display_strength_meter'] = isset($value['display_strength_meter'])
            ? $this->secureToggle($value['display_strength_meter'])
            : 1;

        $secured_value['show_password_toggle'] = isset($value['show_password_toggle'])
            ? $this->secureToggle($value['show_password_toggle'])
            : 1;

        $allowed_modes = array('new-password', 'current-password', 'on', 'off');
        $mode = isset($value['autocomplete_mode']) ? sanitize_text_field($value['autocomplete_mode']) : 'new-password';
        $secured_value['autocomplete_mode'] = in_array($mode, $allowed_modes, true) ? $mode : 'new-password';

        $secured_value['require_confirmation'] = isset($value['require_confirmation'])
            ? $this->secureToggle($value['require_confirmation'])
            : 0;

        $default_label = $this->lang->getText('confirmation_label_default');
        $default_message = $this->lang->getText('confirmation_message_default');

        $label = isset($value['confirmation_label']) ? sanitize_text_field($value['confirmation_label']) : $default_label;
        $message = isset($value['confirmation_message']) ? sanitize_text_field($value['confirmation_message']) : $default_message;

        $secured_value['confirmation_label'] = $label !== '' ? $label : $default_label;
        $secured_value['confirmation_message'] = $message !== '' ? $message : $default_message;

        $secured_value['encrypt_passwords'] = isset($value['encrypt_passwords'])
            ? $this->secureToggle($value['encrypt_passwords'])
            : 0;

        $encryption_key = isset($value['encryption_key']) ? sanitize_text_field($value['encryption_key']) : '';
        if ($secured_value['encrypt_passwords'] && $encryption_key !== '') {
            $secured_value['encryption_key'] = $encryption_key;
        } else {
            $secured_value['encryption_key'] = '';
        }

        return $secured_value;
    }

    protected function secureInputAddressSettings($value)
    {
        $defaults = array(
            'line1'   => $this->lang->getText('address_line1_default_label'),
            'line2'   => $this->lang->getText('address_line2_default_label'),
            'city'    => $this->lang->getText('address_city_default_label'),
            'state'   => $this->lang->getText('address_state_default_label'),
            'postal'  => $this->lang->getText('address_postal_default_label'),
            'country' => $this->lang->getText('address_country_default_label')
        );

        $labels = array();
        if (isset($value['labels']) && is_array($value['labels'])) {
            foreach ($defaults as $key => $fallback) {
                if (array_key_exists($key, $value['labels'])) {
                    $label = sanitize_text_field((string) $value['labels'][$key]);
                    $labels[$key] = $label !== '' ? $label : $fallback;
                } else {
                    $labels[$key] = $fallback;
                }
            }
        } else {
            $labels = $defaults;
        }

        $secured_value = array(
            'labels' => $labels,
            'enable_line2' => isset($value['enable_line2']) ? $this->secureToggle($value['enable_line2']) : 1
        );

        return $secured_value;
    }

    protected function secureTermsconditionsSettings($value)
    {
        $defaults = array(
            'checkbox_label' => $this->lang->getText('terms_checkbox_label', 'default'),
            'anchor_text'    => $this->lang->getText('terms_anchor_text', 'default'),
            'subtext'        => $this->lang->getText('terms_subtext', 'default'),
            'link_type'      => 'page',
            'page_id'        => 0,
            'post_id'        => 0,
            'open_in_modal'  => 0,
            'accept_label'   => $this->lang->getText('terms_accept_label', 'default'),
            'decline_label'  => $this->lang->getText('terms_decline_label', 'default'),
        );

        if (!is_array($value)) {
            return $defaults;
        }

        $sanitized = array();

        $sanitized['checkbox_label'] = isset($value['checkbox_label'])
            ? sanitize_text_field((string) $value['checkbox_label'])
            : $defaults['checkbox_label'];

        if ($sanitized['checkbox_label'] === '') {
            $sanitized['checkbox_label'] = $defaults['checkbox_label'];
        }

        $sanitized['anchor_text'] = isset($value['anchor_text'])
            ? sanitize_text_field((string) $value['anchor_text'])
            : $defaults['anchor_text'];

        if ($sanitized['anchor_text'] === '') {
            $sanitized['anchor_text'] = $defaults['anchor_text'];
        }

        $sanitized['subtext'] = isset($value['subtext'])
            ? sanitize_textarea_field((string) $value['subtext'])
            : $defaults['subtext'];

        $link_type = isset($value['link_type']) ? sanitize_key((string) $value['link_type']) : 'page';
        $sanitized['link_type'] = in_array($link_type, array('page', 'post'), true) ? $link_type : 'page';

        $sanitized['page_id'] = isset($value['page_id']) ? absint($value['page_id']) : 0;
        $sanitized['post_id'] = isset($value['post_id']) ? absint($value['post_id']) : 0;

        if ($sanitized['link_type'] === 'post') {
            $sanitized['page_id'] = 0;
        } else {
            $sanitized['post_id'] = 0;
        }

        $target_id = $sanitized['link_type'] === 'post' ? $sanitized['post_id'] : $sanitized['page_id'];
        if ($target_id > 0) {
            $post = get_post($target_id);
            if (!$post || $post->post_status !== 'publish') {
                $this->log->add(
                    'error',
                    'field',
                    0,
                    get_current_user_id(),
                    'Terms and Conditions field received an invalid target ID: ' . absint($target_id),
                    'validation'
                );
                $sanitized['page_id'] = 0;
                $sanitized['post_id'] = 0;
            }
        } else {
            $this->log->add(
                'warning',
                'field',
                0,
                get_current_user_id(),
                'Terms and Conditions field was saved without a target page or post.',
                'validation'
            );
        }

        $sanitized['open_in_modal'] = isset($value['open_in_modal'])
            ? $this->secureToggle($value['open_in_modal'])
            : 0;

        $sanitized['accept_label'] = isset($value['accept_label']) && $value['accept_label'] !== ''
            ? sanitize_text_field((string) $value['accept_label'])
            : $defaults['accept_label'];

        $sanitized['decline_label'] = isset($value['decline_label']) && $value['decline_label'] !== ''
            ? sanitize_text_field((string) $value['decline_label'])
            : $defaults['decline_label'];

        return $sanitized;
    }

    protected function secureFileUploadSettings($value)
    {
        return $value;
    }
}
