<?php

/**
 * JCOGS Image Pro - Advanced Settings Route
 * ==========================================
 * Advanced image processing configuration with native EE7 validation
 * 
 * @category   ExpressionEngine Add-on
 * @package    JCOGS Image Pro
 * @author     JCOGS Design <contact@jcogs.net>
 * @copyright  Copyright (c) 2021 - 2025 JCOGS Design
 * @license    https://jcogs.net/add-ons/license/jcogs_img_pro
 * @version    2.0.6
 * @link       https://JCOGS.net/
 * @since      2.0.0
 */

namespace JCOGSDesign\JCOGSImagePro\ControlPanel\Routes;

use Exception;

class AdvancedSettings extends ImageAbstractRoute
{
    /**
     * @var string
     */
    protected $route_path = 'advanced_settings';

    /**
     * @var string
     */
    protected $cp_page_title = 'jcogs_img_pro_cp_advanced_settings';

    /**
     * Advanced configuration settings page
     * 
     * @param false $id
     * @return ImageAbstractRoute
     */
    public function process($id = false)
    {
        // Load language files
        $this->loadLanguage();
        $this->loadLanguage('jcogs_img_pro_parameters');
        
        // Check for error notifications and display them (Issue #89)
        $this->displayErrorNotifications();
        
        // Set page title using language key
        $this->cp_page_title = lang('jcogs_img_pro_cp_advanced_settings');
        
        // Add breadcrumb
        $this->addBreadcrumb('advanced_settings', lang('jcogs_img_pro_cp_advanced_settings'));

        // Get current settings using shared service
        $current_settings = $this->getCurrentSettings();
        
        // Build the sidebar using shared method
        $this->build_sidebar($current_settings);

        // Handle form submission
        if (ee()->input->post('submit')) {
            $this->_handleAdvancedSettings();
        }

        // Build form data using EE7 CP/Form
        $form = $this->_buildAdvancedSettingsForm($current_settings);

        // Pass form data to template
        $variables = [
            'cp_page_title' => $this->cp_page_title,
            'form' => $form
        ];
        $this->setBody('advanced_settings', $variables);

        return $this;
    }

    /**
     * Build advanced settings form using EE7 CP/Form service
     */
    private function _buildAdvancedSettingsForm($current_settings)
    {
        // Create EE7 CP/Form
        $form = ee('CP/Form');
        $form->asFileUpload()
            ->setBaseUrl(ee('CP/URL')->make('addons/settings/jcogs_img_pro/advanced_settings'));

        // Advanced Options Toggle Section (like legacy)
        $advanced_toggle_group = $form->getGroup(lang('jcogs_img_pro_advanced_settings'));
        
        // View Advanced Options toggle
        $toggle_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_view_advanced_options'));
        $toggle_fieldset->setDesc(lang('jcogs_img_pro_cp_view_advanced_options_desc'));
        $toggle_field = $toggle_fieldset->getField('img_cp_advanced_options', 'yes_no');
        $toggle_field->setValue('n');
        
        // Set up group toggle functionality like AddConnection - proper EE CP/Form approach
        $toggle_field->set('group_toggle', [
            'y' => 'advanced_options'
        ]);

        // Enable Browser Capability Detection
        $browser_check_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_enable_browser_check'));
        $browser_check_fieldset->setDesc(lang('jcogs_img_pro_cp_enable_browser_check_desc'));
        $browser_check_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $browser_check_fieldset->getField('img_cp_enable_browser_check', 'yes_no')
            ->setValue($current_settings['img_cp_enable_browser_check'] ?? 'y');

        // Enable Class Consolidation
        $class_consolidation_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_class_consolidation_default'));
        $class_consolidation_fieldset->setDesc(lang('jcogs_img_pro_cp_class_consolidation_default_desc'));
        $class_consolidation_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $class_consolidation_fieldset->getField('img_cp_class_consolidation_default', 'yes_no')
            ->setValue($current_settings['img_cp_class_consolidation_default'] ?? 'y');

        // Enable Attribute Variable Expansion
        $attribute_expansion_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_attribute_variable_expansion_default'));
        $attribute_expansion_fieldset->setDesc(lang('jcogs_img_pro_cp_attribute_variable_expansion_default_desc'));
        $attribute_expansion_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $attribute_expansion_fieldset->getField('img_cp_attribute_variable_expansion_default', 'yes_no')
            ->setValue($current_settings['img_cp_attribute_variable_expansion_default'] ?? 'y');

        // Face Detection Crop Focus (Pro Feature)
        $face_detect_crop_focus_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_face_detect_crop_focus'));
        $face_detect_crop_focus_fieldset->setDesc(lang('jcogs_img_pro_cp_face_detect_crop_focus_desc'));
        $face_detect_crop_focus_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $face_detect_crop_focus_field = $face_detect_crop_focus_fieldset->getField('img_cp_default_face_detect_crop_focus', 'select');
        $face_detect_crop_focus_field->setValue($current_settings['img_cp_default_face_detect_crop_focus'] ?? 'first_face')
            ->setChoices([
                'first_face' => lang('jcogs_img_pro_cp_face_detect_crop_focus_first_face'),
                'all' => lang('jcogs_img_pro_cp_face_detect_crop_focus_all')
            ]);

        // Cache Filename Separator
        $separator_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_default_filename_separator'));
        $separator_fieldset->setDesc(lang('jcogs_img_pro_cp_default_filename_separator_desc'));
        $separator_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $separator_fieldset->getField('img_cp_default_filename_separator', 'text')
            ->setValue($current_settings['img_cp_default_filename_separator'] ?? '_-_')
            ->setRequired(true);

        // Special Character Replacement in Filenames
        $char_replacement_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_filename_special_char_replacement'));
        $char_replacement_fieldset->setDesc(lang('jcogs_img_pro_cp_filename_special_char_replacement_desc'));
        $char_replacement_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $char_replacement_field = $char_replacement_fieldset->getField('img_cp_filename_special_char_replacement', 'select');
        $char_replacement_field->setValue($current_settings['img_cp_filename_special_char_replacement'] ?? '_')
            ->setChoices([
                '_' => lang('jcogs_img_pro_cp_filename_replacement_underscore'),
                '-' => lang('jcogs_img_pro_cp_filename_replacement_hyphen'),
                '' => lang('jcogs_img_pro_cp_filename_replacement_remove')
            ])
            ->setRequired(true);

        // Maximum Source Filename Length
        $filename_length_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_default_max_source_filename_length'));
        $filename_length_fieldset->setDesc(lang('jcogs_img_pro_cp_default_max_source_filename_length_desc'));
        $filename_length_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $filename_length_fieldset->getField('img_cp_default_max_source_filename_length', 'text')
            ->setValue($current_settings['img_cp_default_max_source_filename_length'] ?? '175')
            ->setRequired(true);

        // Include Source in Filename Hash
        $include_source_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_include_source_in_filename_hash'));
        $include_source_fieldset->setDesc(lang('jcogs_img_pro_cp_include_source_in_filename_hash_desc'));
        $include_source_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $include_source_fieldset->getField('img_cp_include_source_in_filename_hash', 'yes_no')
            ->setValue($current_settings['img_cp_include_source_in_filename_hash'] ?? 'n');

        // Append Path to Action Links
        $append_path_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_append_path_to_action_links'));
        $append_path_fieldset->setDesc(lang('jcogs_img_pro_cp_append_path_to_action_links_desc'));
        $append_path_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $append_path_fieldset->getField('img_cp_append_path_to_action_links', 'yes_no')
            ->setValue($current_settings['img_cp_append_path_to_action_links'] ?? 'n');

        // CE Image Remote Directory
        $ce_remote_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_ce_image_remote_dir'));
        $ce_remote_fieldset->setDesc(lang('jcogs_img_pro_cp_ce_image_remote_dir_desc'));
        $ce_remote_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $ce_remote_fieldset->getField('img_cp_ce_image_remote_dir', 'text')
            ->setValue($current_settings['img_cp_ce_image_remote_dir'] ?? 'images/remote');

        // PHP Memory Limit
        $php_ram_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_default_min_php_ram'));
        $php_ram_fieldset->setDesc(lang('jcogs_img_pro_cp_default_min_php_ram_desc'));
        $php_ram_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $php_ram_fieldset->getField('img_cp_default_min_php_ram', 'text')
            ->setValue($current_settings['img_cp_default_min_php_ram'] ?? '128')
            ->setRequired(true);

        // PHP Execution Time - ENHANCED with natural language support
        $php_time_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_default_min_php_process_time'));
        $php_time_fieldset->setDesc(lang('jcogs_img_pro_cp_default_min_php_process_time_desc'));
        $php_time_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        
        // Use enhanced duration field with natural language support for timeout context
        try {
            $duration_parser = new \JCOGSDesign\JCOGSImagePro\Service\DurationParser();
            $duration_form_field = new \JCOGSDesign\JCOGSImagePro\Service\DurationFormField($duration_parser);
            
            $current_process_time = $current_settings['img_cp_default_min_php_process_time'] ?? '60';
            $process_time_field = $duration_form_field->createField(
                $php_time_fieldset, 
                'img_cp_default_min_php_process_time', 
                $current_process_time, 
                'timeout'
            );
            
            // Add help text for better UX
            $help_text = $duration_form_field->getHelpText('timeout');
            $php_time_fieldset->setDesc(lang('jcogs_img_pro_cp_default_min_php_process_time_desc') . '<br><small style="color: #64748b;">' . $help_text . '</small>');
            
        } catch (Exception $e) {
            // Fallback to basic field if duration services fail
            $php_time_fieldset->getField('img_cp_default_min_php_process_time', 'text')
                ->setValue($current_settings['img_cp_default_min_php_process_time'] ?? '60')
                ->setRequired(true);
        }

        // PHP Remote Connection Time - ENHANCED with natural language support
        $remote_time_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_default_php_remote_connect_time'));
        $remote_time_fieldset->setDesc(lang('jcogs_img_pro_cp_default_php_remote_connect_time_desc'));
        $remote_time_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        
        // Use enhanced duration field with natural language support for timeout context
        try {
            $duration_parser = new \JCOGSDesign\JCOGSImagePro\Service\DurationParser();
            $duration_form_field = new \JCOGSDesign\JCOGSImagePro\Service\DurationFormField($duration_parser);
            
            $current_remote_time = $current_settings['img_cp_default_php_remote_connect_time'] ?? '3';
            $remote_time_field = $duration_form_field->createField(
                $remote_time_fieldset, 
                'img_cp_default_php_remote_connect_time', 
                $current_remote_time, 
                'timeout'
            );
            
            // Add help text for better UX
            $help_text = $duration_form_field->getHelpText('timeout');
            $remote_time_fieldset->setDesc(lang('jcogs_img_pro_cp_default_php_remote_connect_time_desc') . '<br><small style="color: #64748b;">' . $help_text . '</small>');
            
        } catch (Exception $e) {
            // Fallback to basic field if duration services fail
            $remote_time_fieldset->getField('img_cp_default_php_remote_connect_time', 'text')
                ->setValue($current_settings['img_cp_default_php_remote_connect_time'] ?? '3')
                ->setRequired(true);
        }

        // User Agent String
        $user_agent_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_default_user_agent_string'));
        $user_agent_fieldset->setDesc(lang('jcogs_img_pro_cp_default_user_agent_string_desc'));
        $user_agent_fieldset->set('group', 'advanced_options'); // Set group on fieldset
        $user_agent_fieldset->getField('img_cp_default_user_agent_string', 'text')
            ->setValue($current_settings['img_cp_default_user_agent_string'] ?? 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.5; rv:127.0) Gecko/20100101 Firefox/127.0')
            ->setRequired(true);

        // Enable Cache Audit
        $audit_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_enable_cache_audit'));
        $audit_fieldset->setDesc(lang('jcogs_img_pro_cp_enable_cache_audit_desc'));
        $audit_fieldset->set('group', 'advanced_options');
        $audit_field = $audit_fieldset->getField('img_cp_enable_cache_audit', 'yes_no')
            ->setValue($current_settings['img_cp_enable_cache_audit'] ?? 'y');
        $audit_field->set('group_toggle', [
            'n' => null,
            'y' => 'cache_audit_options'
        ]);

        // Cache Audit Interval - ENHANCED with natural language support
        $audit_interval_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_default_cache_audit_after'));
        $audit_interval_fieldset->setDesc(lang('jcogs_img_pro_cp_default_cache_audit_after_desc'));
        $audit_interval_fieldset->set('group', 'advanced_options');
        
        // Use enhanced duration field with natural language support
        try {
            $duration_parser = new \JCOGSDesign\JCOGSImagePro\Service\DurationParser();
            $duration_form_field = new \JCOGSDesign\JCOGSImagePro\Service\DurationFormField($duration_parser);
            
            $current_audit_interval = $current_settings['img_cp_default_cache_audit_after'] ?? '604800';
            $audit_field = $duration_form_field->createField(
                $audit_interval_fieldset, 
                'img_cp_default_cache_audit_after', 
                $current_audit_interval, 
                'audit'
            );
            
            // Add help text for better UX
            $help_text = $duration_form_field->getHelpText('audit');
            $audit_interval_fieldset->setDesc(lang('jcogs_img_pro_cp_default_cache_audit_after_desc') . '<br><small style="color: #64748b;">' . $help_text . '</small>');
            
        } catch (Exception $e) {
            // Fallback to basic field if duration services fail
            $audit_interval_fieldset->getField('img_cp_default_cache_audit_after', 'text')
                ->setValue($current_settings['img_cp_default_cache_audit_after'] ?? '604800')
                ->setRequired(true);
        }

        // JCOGS License Server Domain
        $license_server_fieldset = $advanced_toggle_group->getFieldSet(lang('jcogs_img_pro_cp_license_server_domain'));
        $license_server_fieldset->setDesc(lang('jcogs_img_pro_cp_license_server_domain_desc'));
        $license_server_fieldset->set('group', 'advanced_options');
        $license_server_fieldset->getField('jcogs_license_server_domain', 'text')
            ->setValue($current_settings['jcogs_license_server_domain'] ?? 'mule.jcogs.net')
            ->setRequired(true);

        // Add submit button
        $submit_button = $form->getButton('submit');
        $submit_button->setType('submit')
            ->setText(lang('jcogs_img_pro_cp_save_advanced_settings'))
            ->setValue('advanced_settings')
            ->setWorking(lang('jcogs_img_pro_cp_saving'));

        return $form;
    }

    /**
     * Get system information for advanced settings
     */

    /**
     * Handle advanced settings form submission
     */
    private function _handleAdvancedSettings()
    {
        if (!$this->ensureMutationAllowed('save_advanced_settings', 'advanced_settings')) {
            return;
        }

        $posted_data = $_POST;
        
        // Basic validation for advanced settings
        $errors = [];
        
        // Validate filename separator
        if (isset($posted_data['img_cp_default_filename_separator'])) {
            $separator = trim((string) $posted_data['img_cp_default_filename_separator']);
            $posted_data['img_cp_default_filename_separator'] = $separator;
            if (empty($separator) || 
                strpbrk($separator, " \t\n\r\0\x0B") !== false || 
                strpbrk($separator, '\\/<>:"|?*') !== false) {
                $errors[] = lang('jcogs_img_pro_cp_invalid_separator_string');
            }
        }
        
        // Validate max source filename length
        if (isset($posted_data['img_cp_default_max_source_filename_length'])) {
            $length_raw = trim((string) $posted_data['img_cp_default_max_source_filename_length']);

            if ($length_raw === '' || !ctype_digit($length_raw)) {
                $errors[] = lang('jcogs_img_pro_cp_invalid_filename_length');
            } else {
                $length = (int) $length_raw;

                // Self-heal legacy over-limit values so they do not block all
                // Advanced Settings saves on older installations.
                if ($length > 175) {
                    $length = 175;
                }

                if ($length <= 0) {
                    $errors[] = lang('jcogs_img_pro_cp_invalid_filename_length');
                } else {
                    $posted_data['img_cp_default_max_source_filename_length'] = (string) $length;
                }
            }
        }
        
        // Validate PHP RAM value
        if (isset($posted_data['img_cp_default_min_php_ram'])) {
            $ram_value = trim((string) $posted_data['img_cp_default_min_php_ram']);
            $posted_data['img_cp_default_min_php_ram'] = $ram_value;
            if (empty($ram_value) || !$this->_isValidMemoryValue($ram_value)) {
                $errors[] = lang('jcogs_img_pro_cp_invalid_php_ram_value');
            }
        }
        
        // DurationParser instance
        $duration_parser = new \JCOGSDesign\JCOGSImagePro\Service\DurationParser();

        // Parse and validate duration fields
        $duration_fields = [
            'img_cp_default_min_php_process_time' => 'timeout',
            'img_cp_default_php_remote_connect_time' => 'timeout',
            'img_cp_default_cache_audit_after' => 'audit'
        ];
        foreach ($duration_fields as $field => $context) {
            if (isset($posted_data[$field])) {
                $parsed = $duration_parser->parseToSeconds($posted_data[$field]);
                if ($parsed['error']) {
                    $errors[] = $parsed['error'];
                } else {
                    $validation = $duration_parser->validateForContext($parsed['value'], $context);
                    if (!$validation['valid']) {
                        $errors[] = $validation['error'];
                    }
                    $posted_data[$field] = $parsed['value'];
                }
            }
        }
        
        // Validate remote connection time
        if (isset($posted_data['img_cp_default_php_remote_connect_time'])) {
            $connect_time = (int)$posted_data['img_cp_default_php_remote_connect_time'];
            if ($connect_time <= 0) {
                $errors[] = lang('jcogs_img_pro_cp_invalid_connection_time');
            }
        }
        
        // Validate user agent string
        if (isset($posted_data['img_cp_default_user_agent_string'])) {
            $user_agent = trim($posted_data['img_cp_default_user_agent_string']);
            if (empty($user_agent)) {
                $errors[] = lang('jcogs_img_pro_cp_invalid_user_agent');
            }
        }
        
        // Validate cache audit interval
        if (isset($posted_data['img_cp_default_cache_audit_after'])) {
            $interval = (int)$posted_data['img_cp_default_cache_audit_after'];
            if ($interval <= 0) {
                $errors[] = lang('jcogs_img_pro_cp_invalid_audit_interval');
            }
        }
        
        // Validate license server domain
        if (isset($posted_data['jcogs_license_server_domain'])) {
            $domain = trim($posted_data['jcogs_license_server_domain']);
            if (empty($domain) || !$this->_isValidDomain($domain)) {
                $errors[] = lang('jcogs_img_pro_cp_invalid_license_domain');
            }
        }
        
        // Validate CE Image remote directory
        if (isset($posted_data['img_cp_ce_image_remote_dir'])) {
            $remote_dir = trim($posted_data['img_cp_ce_image_remote_dir']);
            if (!empty($remote_dir) && !$this->_isValidPath($remote_dir)) {
                $errors[] = lang('jcogs_img_pro_cp_invalid_remote_directory');
            }
        }
        
        // Validate face detection crop focus
        if (isset($posted_data['img_cp_default_face_detect_crop_focus'])) {
            $crop_focus = $posted_data['img_cp_default_face_detect_crop_focus'];
            if (!in_array($crop_focus, ['first_face', 'all'])) {
                $errors[] = lang('jcogs_img_pro_cp_invalid_face_detect_crop_focus');
            }
        }
        
        if (empty($errors)) {
            // Save settings using shared service method
            if ($this->saveSettings($posted_data)) {
                $this->set_success_message('jcogs_img_pro_cp_advanced_settings_saved');
            } else {
                $this->utilities_service->debug_log('message_failure', lang('jcogs_img_pro_cp_settings_save_failed'));

                $error_body = lang('jcogs_img_pro_cp_settings_save_failed');
                $save_error_detail = trim($this->getLastSettingsSaveError());
                if ($save_error_detail !== '') {
                    $error_body .= '<br><small>' . htmlspecialchars($save_error_detail, ENT_QUOTES, 'UTF-8') . '</small>';
                }

                ee('CP/Alert')->makeInline('jcogs-img-pro-advanced-save-failed')
                    ->asIssue()
                    ->withTitle(lang('error') ?: 'Error')
                    ->addToBody($error_body)
                    ->defer();
            }
        } else {
            foreach ($errors as $error) {
                $this->utilities_service->debug_log('message_failure', $error);
            }

            ee('CP/Alert')->makeInline('jcogs-img-pro-advanced-validation-failed')
                ->asIssue()
                ->withTitle(lang('error') ?: 'Error')
                ->addToBody(implode('<br>', $errors))
                ->defer();
        }
        
        $this->redirectToRoute('advanced_settings');
    }

    /**
     * Validate domain format
     */
    private function _isValidDomain($domain): bool
    {
        return filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME);
    }

    /**
     * Validate memory value format
     */
    private function _isValidMemoryValue($value): bool
    {
        $value = strtoupper(trim((string) $value));

        if ($value === '') {
            return false;
        }

        // Remove internal whitespace so values like "256 M" are tolerated.
        $value = str_replace(" ", '', $value);

        // Optional trailing B (e.g. MB, GB)
        if (str_ends_with($value, 'B')) {
            $value = substr($value, 0, -1);
        }

        // Optional unit suffix K/M/G/T/P
        $last = substr($value, -1);
        if (in_array($last, ['K', 'M', 'G', 'T', 'P'], true)) {
            $value = substr($value, 0, -1);
        }

        if ($value === '') {
            return false;
        }

        // Accept integer or decimal numeric core only.
        if (substr_count($value, '.') > 1 || str_starts_with($value, '.') || str_ends_with($value, '.')) {
            return false;
        }

        $numeric = str_replace('.', '', $value);
        return $numeric !== '' && ctype_digit($numeric);
    }

    /**
     * Validate path format
     */
    private function _isValidPath($path): bool
    {
        $path = trim((string) $path);

        // Basic path validation - no absolute paths, no traversal, no dangerous characters.
        if ($path === '' || str_starts_with($path, '/') || str_contains($path, '..')) {
            return false;
        }

        return strpbrk($path, '<>:"|?*') === false;
    }

}
