<?php

namespace CleantalkSP\SpbctWP\Settings;

use CleantalkSP\SpbctWP\DTO\ReactDataDTO;
use CleantalkSP\SpbctWP\Helpers\IP;

class SettingsGeneralReact
{
    public static function getReactData()
    {
        global $spbc;

        $user  = wp_get_current_user();
        $email = (isset($user->ID) && $user->ID > 0) ? $user->user_email : spbc_get_admin_email();
        $current_ip = IP::get();
        $current_ip = is_string($current_ip) ? $current_ip : __('Unknown IP', 'security-malware-firewall');

        $storage_settings = (isset($spbc->storage['settings']) && is_array($spbc->storage['settings'])) ?
            $spbc->storage['settings'] :
            (array) $spbc->settings;

        $auth_login_url = wp_login_url();
        if (
            ! empty($storage_settings['login_page_rename__enabled']) &&
            ! empty($storage_settings['login_page_rename__name'])
        ) {
            $auth_login_url = get_site_url() . '/' . $storage_settings['login_page_rename__name'];
        }

        $company_name = $spbc->default_data['wl_company_name'];
        if ($spbc->data["wl_mode_enabled"]) {
            $company_name = $spbc->data["wl_company_name"];
        }

        $data['strings'] = [
            'settingsSlug' => SPBC_SETTINGS,
            'nonce' => wp_create_nonce(SPBC_SETTINGS . '-options'),
            'two_fa_verification_email_recipient' => $email,
            'auth_login_page_url' => $auth_login_url,
            'tech_support_url_field_prefix' => get_home_url() . '/' . (get_option('permalink_structure', false) ? '' : '?'),
            'login_rename_notify_admin_email' => spbc_get_admin_email(),
            'visitorCurrentIp' => $current_ip,
            'nextScheduledScanDescription' => spbc_get_next_scan_launch_time_text(),
            'scannerAutoStartManualTimezone' => (string) get_option('gmt_offset', '0'),
            'wlCompanyName' => $company_name,
        ];
        $data['flags'] = [
            'keyIsOk' => (bool) $spbc->key_is_ok,
            'canActivatePlugins' => (bool) current_user_can('activate_plugins'),
            'shuffleSaltsUnlocked' => ! empty($spbc->settings['there_was_signature_treatment']),
        ];
        $data['objects'] = [
            'settings' => self::groupSettings(array_merge((array)$spbc->network_settings, (array)$spbc->settings)),
            'wp_user_roles_options' => self::getWpUserRolesOptionsForReact(),
            'visitorIpSources' => spbc_settings_field__secfw__get_ip__get_labels(),
            'scannerExclusionsDir' => self::getExclusionsStat('dir'),
            'scannerExclusionsURL' => self::getExclusionsStat('url'),
        ];

        $dto = new ReactDataDTO($data);

        return $dto->getArray();
    }

    private static function groupSettings($settings)
    {
        global $spbc;

        $key_to_group = self::buildKeyToGroupMap();
        $grouped_settings = [];

        foreach ($settings as $key => $value) {
            if ($key === 'spbc_key') {
                if (
                    ! (
                        is_main_site() ||
                        $spbc->ms__work_mode == 3 ||
                        ($spbc->ms__work_mode == 1 && is_super_admin())
                    )
                ) {
                    $value = 'Provided by admin';
                }
                $grouped_settings['apikey'][$key] = $value;
                continue;
            }

            if (
                is_multisite() && is_main_site() &&
                in_array($key, ['ms__work_mode', 'ms__hoster_api_key', 'ms__service_utilization'], true)
            ) {
                $grouped_settings['apikey'][$key] = $value;
                continue;
            }

            if (isset($key_to_group[$key])) {
                $grouped_settings[$key_to_group[$key]][$key] = $value;
            }
        }

        return self::orderGroupElements($grouped_settings);
    }

    /**
     * Builds a reverse map: setting_key => group_name from the ordering ruleset.
     *
     * @return array<string, string>
     */
    private static function buildKeyToGroupMap()
    {
        $map = [];
        foreach (self::getOrderingRuleset() as $group_name => $keys) {
            foreach ($keys as $key) {
                $map[$key] = $group_name;
            }
        }
        return $map;
    }

    /**
     * Single source of truth for settings groups ordering.
     *
     * @return array<string, string[]>
     */
    private static function getOrderingRuleset()
    {
        return [
            'auth_and_logging_in' => [
                'bfp__enabled',
                'bfp__delay__1_fails',
                'bfp__delay__5_fails',
                'bfp__allowed_wrong_auths',
                'bfp__count_interval',
                'bfp__block_period__5_fails',
                'check_pass__enable',
                'check_pass__roles',
                '2fa__enable',
                '2fa__roles',
                'edit_tech_support_url__enabled',
                'edit_tech_support_url__link',
                'edit_tech_support_url__remove',
                'login_page_rename__enabled',
                'login_page_rename__name',
                'login_page_rename__redirect',
                'login_page_rename__send_email_notification',

            ],
            'firewall' => [
                'fw__custom_message',
                'secfw__enabled',
                'waf__enabled',
                'waf__xss_check',
                'waf__sql_check',
                'waf__exploit_check',
                'waf_blocker__enabled',
                'upload_checker__file_check',
                'upload_checker__do_check_wordpress_modules',
                'traffic_control__enabled',
                'traffic_control__autoblock_timeframe',
                'traffic_control__autoblock_amount',
                'traffic_control__autoblock_period',
                'traffic_control__exclude_authorised_users',
                'secfw__get_ip',
                'secfw__get_ip__enable_cdn_auto_self_check'
            ],
            'scanner_settings' => [
                'scanner__auto_start',
                'scanner__auto_start__set_period',
                'scanner__auto_start_manual',
                'scanner__auto_start_manual_time',
                'scanner__auto_start_manual_tz',
                'scanner__outbound_links',
                'scanner__outbound_links_mirrors',
                'scanner__important_files_listing',
                'scanner__heuristic_analysis',
                'scanner__schedule_send_heuristic_suspicious_files',
                'scanner__signature_analysis',
                'scanner__binary_analysis',
                'scanner__os_cron_analysis',
                'scanner__db_trigger_analysis',
                'scanner__path_exclusions_view',
                'scanner__auto_cure',
                'scanner__frontend_analysis',
                'scanner__frontend_analysis__csrf',
                'scanner__frontend_analysis__domains_exclusions_view',
                'scanner__list_unknown',
                'scanner__list_unknown__older_than',
                'scanner__list_approved_by_cleantalk',
                'scanner__fs_watcher',
                'scanner__fs_watcher__snapshots_period',
            ],
            'vulnerability_check' => [
                'vulnerability_check__test_before_install',
                'vulnerability_check__enable_cron',
                'vulnerability_check__warn_on_modules_pages',
                'vulnerability_check__show_reports',
            ],
            'admin_bar' => [
                'admin_bar__show',
                'admin_bar__admins_online_counter',
                'admin_bar__brute_force_counter',
                'admin_bar__firewall_counter',
                'wp__dashboard_widget__show',
            ],
            'misc' => [
                'misc__backend_logs_enable',
                'misc__prevent_logins_collecting',
                'misc__prevent_logins_collecting_on_password_reset',
                'misc__show_link_in_login_form',
                'wp__disable_xmlrpc',
                'wp__disable_rest_api',
                'data__set_cookies',
                'misc__forbid_to_show_in_iframes',
                'data__additional_headers',
                'wp__upload_dir_prevent_php_execution',
                'wp__use_builtin_http_api',
                'misc_disable_file_editor',
                'misc__complete_deactivation',
                'action_adjust',
                'monitoring__users',
            ],
            'spbc_trusted_and_affiliate' => [
                'spbc_trusted_and_affiliate__shortcode',
                'spbc_trusted_and_affiliate__shortcode_tag',
                'spbc_trusted_and_affiliate__footer',
                'spbc_trusted_and_affiliate__add_id',
            ],
        ];
    }

    private static function orderGroupElements($grouped_settings)
    {
        $ordering_ruleset = self::getOrderingRuleset();

        foreach ($ordering_ruleset as $group_name => $ruleset) {
            // UI-only field (not a saved option); rendered by React ActionShuffleSalts
            if ($group_name === 'auth_and_logging_in') {
                $grouped_settings['auth_and_logging_in']['action_shuffle_salts'] = true;
            }
            $ordered = [];
            foreach ($ruleset as $key) {
                if (isset($grouped_settings[$group_name][$key])) {
                    $ordered[$key] = $grouped_settings[$group_name][$key];
                }
            }
            $grouped_settings[$group_name] = $ordered;
        }

        // Rebuild in $ordering_ruleset key order (PHP arrays keep insertion order)
        $result = [];
        if (isset($grouped_settings['apikey'])) {
            $result['apikey'] = $grouped_settings['apikey'];
        }
        foreach (array_keys($ordering_ruleset) as $group_name) {
            if (isset($grouped_settings[$group_name])) {
                $result[$group_name] = $grouped_settings[$group_name];
            }
        }
        return $result;
    }

    /**
     * Role slugs and labels for React multiselects (matches PHP settings fields).
     *
     * @return array<int, array{value: string, label: string}>
     */
    private static function getWpUserRolesOptionsForReact()
    {
        $wp_roles = wp_roles();
        $out      = array();

        foreach ($wp_roles->roles as $slug => $details) {
            $name    = isset($details['name']) ? $details['name'] : (string) $slug;
            $out[] = array(
                'value' => (string) $slug,
                'label' => $name,
            );
        }

        return $out;
    }

    /**
     * @param string $type
     * @return array
     */
    private static function getExclusionsStat($type = 'dir')
    {
        $exclusions = [];

        switch ($type) {
            case 'dir':
                $exclusions = get_option('spbc_upload_dirs_stat');
                break;
            case 'url':
                $exclusions = get_option('spbc_upload_urls_stat');
                break;
        }

        $out = [];

        if (is_array($exclusions) && !empty($exclusions)) {
            foreach ($exclusions as $k => $v) {
                $out[] = array('key' => $k, 'value' => $v);
            }
            return $out;
        }

        return [];
    }
}
