<?php

/**
 * Class CT_Ultimate_GDPR_Controller_Cmptcf
 */



class CT_Ultimate_GDPR_Controller_Cmptcf extends CT_Ultimate_GDPR_Controller_Abstract
{

    const ID = 'ct-ultimate-gdpr-cmptcf';

    private $cmptcf_options;

    private $tcf_version = '48';

    private $vl_key = 'ct_ultimate_gdpr-tcfvendorlist';

    private $vl_key2 = 'ct_ultimate_gdpr-noniabvendors';

    private $submenu_page_slug_niv;

    private $default_bots = 'Googlebot, Bingbot, Slurp, DuckDuckBot, Baiduspider, YandexBot, Sogou, Exabot, facebot, facebookexternalhit';

    private $default_options;

    // https://vendor-list.consensu.org/v3/purposes-[COUNTRY_CODE].json
    private $tcf_translations = array(
        // 'ar'  => 'Arabic',
        //'bg'  => 'Bulgarian',
        //'bs'  => 'Bosnian',
        'ca'  => 'Catalan',
        'cs'  => 'Czech',
        'da'  => 'Danish',
        'de'  => 'German',
        'el'  => 'Greek',
        'es'  => 'Spanish',
        'et'  => 'Estonian',
        //'eu'  => 'Basque',
        'fi'  => 'Finnish',
        'fr'  => 'French',
        'gl'  => 'Galician',
        'hr'  => 'Croatian',
        'hu'  => 'Hungarian',
        'it'  => 'Italian',
        //'ja'  => 'Japanese',
        'lt'  => 'Lithuanian',
        'lv'  => 'Latvian',
        'mt'  => 'Maltese',
        'nl'  => 'Dutch',
        'no'  => 'Norwegian',
        'pl'  => 'Polish',
        'pt_br' => 'Portuguese (Brazil)',
        'pt_pt' => 'Portuguese (Portugal)',
        'ro'  => 'Romanian',
        'ru'  => 'Russian',
        'sk'  => 'Slovak',
        'sl'  => 'Slovenian',
        'sr_cyrl' => 'Serbian (Cyrillic)',
        'sr_latn' => 'Serbian (Latin)',
        'sv'  => 'Swedish',
        'tr'  => 'Turkish',
        'uk'  => 'Ukrainian',
        'zh'  => 'Chinese'
    );

    private $icon_position = array(
        'bottom_right'  => 'Bottom right',
        'bottom_center'  => 'Bottom center',
        'bottom_left'  => 'Bottom left',
    );


    private $featuresMapping = [];
    private $specialPurposesMapping = [];
    private $purposesMapping = [];
    private $dataDeclarationMapping = [];

    /**
     * @return string
     */
    private $vendors = [];

    private $only_used_vendors = false;

    private $non_iab_vendors = [];

    public function get_id()
    {
        return self::ID;
    }

    private function get_non_iab_vendors(){
        $vendors = get_option($this->vl_key2, []);
        $vendors = array_values($vendors);

        return $vendors;
    }

    /**
     * Init after construct
     */
    public function init()
    {
        $this->cmptcf_options = get_option('ct-ultimate-gdpr-cmptcf',  $this->default_options);
        $this->cmptcf_options = wp_parse_args($this->cmptcf_options, $this->default_options);

        if($this->do_optimize_js()){
            $this->only_used_vendors = true;
        }

        if($this->is_display_noniab()){
            $this->non_iab_vendors = $this->get_non_iab_vendors();
        } else {
            $this->non_iab_vendors = [];
        }



        add_action('wp_enqueue_scripts', array($this, 'frontend_enqueue_scripts'), 1);

        add_action('wp_enqueue_scripts', array($this, 'deregister_scripts'), 1001);

        add_action('wp_head', array( $this, 'get_header_script'), 1);

        add_action('wp_head', array($this, 'add_custom_klaro_script'), 1);

        add_action('rest_api_init', array($this, 'klaro_config_init'));

        add_action('rest_api_init', array($this, 'vendor_list_init'));

        add_action('admin_init', array($this, 'update_vendor_list'));

        add_action('ctgdpr_update_vendor_list', array($this,'fetch_vendor_list'));

        add_action('wp_ajax_ctgdpr_update_vendor_list', array($this,'ajax_ctgdpr_update_vendor_list'));

        add_action( 'wp_ajax_ct_ultimate_gdpr_consent_give_tcf', array( $this, 'give_consent_tcf' ) );
        add_action( 'wp_ajax_nopriv_ct_ultimate_gdpr_consent_give_tcf', array( $this, 'give_consent_tcf' ) );


        if($this->tcf_enabled()){
            add_filter( 'ct_ultimate_gdpr_controller_should_render', array( $this, 'gdpr_popup_should_render' ) );
            add_filter( 'ct_ultimate_gdpr_service_gtm_head_snippet', array( $this, 'do_not_render' ) );
            add_filter( 'ct_ultimate_gdpr_service_ga4_head_snippet', array( $this, 'do_not_render' ) );

            // plugins
            if ($this->is_pixelyoursite_consent_mode()) {
                $this->setup_pixelyoursite_filters();
                add_action('wp_footer', array($this, 'add_pixelyoursite_script_footer'), 21);
            }
        }

        // non-IAB vendors
        add_action('admin_menu', array( $this,'tcf_add_admin_menu'), 20 );
        add_action('admin_post_add_vendor', array( $this,'tcf_handle_add_vendor') );
        add_action('wp_ajax_fetch_vendors', array( $this,'tcf_fetch_vendors') );
        add_action('wp_ajax_delete_vendor', array( $this,'tcf_handle_delete_vendor') );
        add_action('admin_enqueue_scripts', array( $this,'tcf_enqueue_admin_scripts'));
        add_shortcode('tcf_non_iab_vendors', array($this, 'tcf_shortcode'));

    }

    private function tcf_enabled() {
        return isset($this->cmptcf_options['cmptcf_enable_tcf']) && $this->cmptcf_options['cmptcf_enable_tcf'] === 'on';
    }

    private function collapsible_enabled() {
        return isset($this->cmptcf_options['cmptcf_collapsible_read_more']) && $this->cmptcf_options['cmptcf_collapsible_read_more'] === 'on';
    }

    private function is_defer_enabled() {
        return isset($this->cmptcf_options['cmptcf_defer_script_loading']) && $this->cmptcf_options['cmptcf_defer_script_loading'] === 'on';
    }

    private function is_vendor_fetching_disabled() {
        return isset($this->cmptcf_options['cmptcf_vendor_fetching_disabled']) && $this->cmptcf_options['cmptcf_vendor_fetching_disabled'] === 'on';
    }

    private function is_debug_mode() {
        return isset($this->cmptcf_options['cmptcf_debug_mode']) && $this->cmptcf_options['cmptcf_debug_mode'] === 'on';
    }
    private function get_privacy_url() {
        return isset($this->cmptcf_options['cmptcf_privacy_url']) ? $this->cmptcf_options['cmptcf_privacy_url'] : '';
    }
    private function is_consent_logging_disabled() {
        return isset($this->cmptcf_options['cmptcf_disable_tc_string_logging']) && $this->cmptcf_options['cmptcf_disable_tc_string_logging'] === 'on';
    }
    private function is_consent_mode() {
        return isset($this->cmptcf_options['cmptcf_consent_mode']) && $this->cmptcf_options['cmptcf_consent_mode'] === 'on';
    }
    private function is_pixelyoursite_consent_mode() {
        return isset($this->cmptcf_options['cmptcf_pixelyoursite_consent']) && $this->cmptcf_options['cmptcf_pixelyoursite_consent'] === 'on';
    }
    private function is_display_noniab() {
        return isset($this->cmptcf_options['cmptcf_display_noniab']) && $this->cmptcf_options['cmptcf_display_noniab'] === 'on';
    }

    private function do_optimize_js(){
        return isset($this->cmptcf_options['cmptcf_optimize_js']) && $this->cmptcf_options['cmptcf_optimize_js'] === 'on';
    }
    private function get_botlist(){
        return isset($this->cmptcf_options['cmptcf_botlist']) ? $this->cmptcf_options['cmptcf_botlist'] : '';
    }
    private function run_geolocation(){
        return isset($this->cmptcf_options['cmptcf_geolocation']) && $this->cmptcf_options['cmptcf_geolocation'] === 'on';
    }

    private function get_filtered_vendors() {
        if (isset($this->cmptcf_options['cmptcf_vendors_ids']) && $this->cmptcf_options['cmptcf_vendors_ids'] != '') {
            // Explode the string into an array
            $vendorIdsArray = explode(',', $this->cmptcf_options['cmptcf_vendors_ids']);

            // Trim spaces from each element in the array
            $trimmedVendorIds = array_map('trim', $vendorIdsArray);

            return $trimmedVendorIds;
        } else {
            return array();
        }
    }

    private function get_excluded_pages() {
        if (isset($this->cmptcf_options['cmptcf_exclude_pages']) && $this->cmptcf_options['cmptcf_exclude_pages'] != '') {
            // Explode the string into an array
            $vendorIdsArray = explode(',', $this->cmptcf_options['cmptcf_exclude_pages']);

            // Trim spaces from each element in the array
            $trimmedVendorIds = array_map('trim', $vendorIdsArray);

            return $trimmedVendorIds;
        } else {
            return array();
        }
    }

    private function get_lang() {
        // List of supported languages
        $supported_languages = array_keys($this->tcf_translations);

        // Check if WPML is active and get the current language
        $wpml_language = apply_filters('wpml_current_language', NULL);
        if (!is_null($wpml_language)) {
            // Replace hyphens with underscores to match the plugin's language code format
            $wpml_language_formatted = str_replace('-', '_', $wpml_language);

            // If WPML returns a supported language, use it
            if (!empty($wpml_language_formatted) && in_array($wpml_language_formatted, $supported_languages)) {
                return $wpml_language_formatted;
            }
        }

        return isset($this->cmptcf_options['cmptcf_lang']) ? $this->cmptcf_options['cmptcf_lang'] : '';
    }


    private function get_tab2_description() {
        return isset($this->cmptcf_options['cmptcf_tab2_description']) ? $this->cmptcf_options['cmptcf_tab2_description'] : '';
    }
    private function get_motive_color() {
        return isset($this->cmptcf_options['cmptcf_motive_color']) ? $this->cmptcf_options['cmptcf_motive_color'] : '';
    }
    private function get_icon_position() {
        return isset($this->cmptcf_options['cmptcf_icon_position']) ? $this->cmptcf_options['cmptcf_icon_position'] : '';
    }


    /**
     * Do actions on frontend
     */
    public function front_action()
    {
    }

    /**
     * Do actions in admin (general)
     */
    public function admin_action()
    {
    }


    /**
     * Do actions on current admin page
     */
    protected function admin_page_action()
    {
        if ( $this->is_request_consents_log() ) {
            $this->download_consents_log();
        }
    }
    private function is_request_consents_log() {
        return ! ! ct_ultimate_gdpr_get_value( 'ct-ultimate-gdpr-tcf-log', $this->get_request_array() );
    }


    private function download_consents_log() {

        $rendered = $this->logger->render_logs( $this->logger->get_logs( 'tcf' ) );
        $filename = urlencode($this->get_id() . '-tcf-logs.txt');

        // Download
        header("Content-Type: application/octet-stream");
        header("Content-Disposition: attachment; filename={$filename}");
        echo $rendered;
        exit;

    }

    /**
     * Get view template string
     * @return string
     */
    public function get_view_template()
    {
        return 'admin/admin-cmptcf';
    }

    /**
     * Add menu page (if not added in admin controller)
     */
    public function add_menu_page()
    {
        add_submenu_page(
            CT_Ultimate_GDPR::instance()->get_admin_controller()->get_option_name(),
            esc_html__('TCF Compliance', 'ct-ultimate-gdpr'),
            esc_html__('TCF Compliance', 'ct-ultimate-gdpr'),
            'manage_options',
            $this->get_id(),
            array($this, 'render_menu_page')
        );

        add_submenu_page(
            CT_Ultimate_GDPR::instance()->get_admin_controller()->get_option_name(),
            esc_html__('TCF Consent report', 'ct-ultimate-gdpr'),
            esc_html__('TCF Consent report', 'ct-ultimate-gdpr'),
            'manage_options',
            'ct-ultimate-gdpr-cmptcf-reports',
            array($this, 'render_tcf_logs_report')
        );


    }

    private function decodeTCString($tcString) {
        return IABTcf\Decoder::decode($tcString);
    }

    public function render_tcf_logs_report(){
        // Security check
        if (!current_user_can('manage_options')) {
            wp_die(__('You do not have sufficient permissions to access this page.'));
        }

        echo '<div class="wrap"><h1>'. esc_html__('TCF Consent Logs', 'ct-ultimate-gdpr') . '</h1>';
        echo "<div class='postbox'><div class='inside'>";
        ?>
        <form method="post">
            <label for="from">From:</label>
            <input type="text" id="from" name="from_date" value="<?php echo $_POST['from_date'] ?? '' ?>">
            <label for="to" style="margin-left:10px;">To:</label>
            <input type="text" id="to" name="to_date" value="<?php echo $_POST['to_date'] ?? '' ?>">

            <br><br>
            <div>
                <input type="checkbox" id="weekly_report" name="weekly_report" <?php echo isset($_POST['weekly_report']) ? 'checked' : ''; ?>>
                <label for="weekly_report"  class="regular-text"><?php echo esc_html__('Show Week-by-Week', 'ct-ultimate-gdpr'); ?></label>
            </div>
            <br>
             <div>
                <input type="submit" value="<?php echo esc_html__('Generate report', 'ct-ultimate-gdpr'); ?>" class="button button-primary button-large">
             </div>
        </form>
        <script>
            jQuery(document).ready(function($) {
                $('#from, #to').datepicker({
                    dateFormat : 'yy-mm-dd',
                    maxDate: 0
                });
            });
        </script>
        <?php

        echo '</div></div>';
        // Process form and display results
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['from_date'], $_POST['to_date'])) {
            $weekly_report = isset($_POST['weekly_report']);
            $this->display_consents($_POST['from_date'], $_POST['to_date'], $weekly_report);
        }
        echo '</div>';

    }

    private function display_consents($from, $to, $weekly = false) {
        global $wpdb;

        require_once __DIR__ . '/../../vendor/iabtcf/vendor/autoload.php';

        $tcf_consent_logs = $this->logger->get_logs('tcf', $from, $to);

        $weekly_stats = [];

        // Define cookie mapping
        $cookie_types = [
            '1' => 'Necessary Cookies',
            '2' => 'Functional Cookies',
            '3' => 'Analytics Cookies',
            '4' => 'Advertising Cookies'
        ];

        // Initialize counters for each cookie type and overall consents
        $cookie_counts = [
            '1' => 0,
            '2' => 0,
            '3' => 0,
            '4' => 0
        ];

        $data = $this->get_vendor_list();
        $vendors = isset($data['vendors']) ? $data['vendors'] : null;
        $purposes = isset($data['purposes']) ? $data['purposes'] : null;

        $purposes_map = [];
        foreach ($purposes as $item) {
            if (isset($item['id']) && isset($item['name'])) {
                $purposes_map[$item['id']] = $item['name'];
            }
        }

        $total_consents = 0;
        $total_consents_cookies = 0;
        $withdrawn_consents = 0;
        $cookies_no_group = 0;
        $purpose_counts = array_fill_keys(array_keys($purposes_map), 0);
        $purpose_li_counts = array_fill_keys(array_keys($purposes_map), 0);
        $vendor_counts = [];
        $vendor_li_counts = [];

        // Process each log entry
        foreach ($tcf_consent_logs as $entry) {
            if (!empty($entry['data'])) {
                $data = json_decode($entry['data'], true);

                // week stats start
                $date = new DateTime();
                $date->setTimestamp($entry['time']);
                $week = $date->format("o-W");  // ISO-8601 year-numbering and week numbering

                if (!isset($weekly_stats[$week])) {
                    $weekly_stats[$week] = [
                        'total_consents' => 0,
                        'withdrawn_consents' => 0,
                        'consents_cookies' => 0,
                        'no_group' => 0,
                        'cookie_counts' => array_fill_keys(array_keys($cookie_types), 0)
                    ];
                }

                $week_data = &$weekly_stats[$week];
                // week stats end


                if (!empty($data['cookies'])) {
                    $total_consents_cookies++;
                    $week_data['consents_cookies']++;

                    foreach ($data['cookies'] as $cookie) {
                        if (isset($cookie_counts[$cookie])) {
                            $cookie_counts[$cookie]++;
                            $week_data['cookie_counts'][$cookie]++;
                        }
                    }
                }

                if (empty($data['cookies'])) {
                    $cookies_no_group++;
                    $week_data['no_group']++;
                }

                try {
                    if (empty($data['tcf'])) {
                        // fallback for old data format
                        $decoded = $this->decodeTCString($entry['data']);
                    } else {
                        $decoded = $this->decodeTCString($data['tcf']);
                    }
                } catch (Exception $e) {
                    // error_log('Failed to decode TCF string: ' . $e->getMessage());
                    $decoded = null;
                }


                if ($decoded) {
                    $total_consents++;
                    $week_data['total_consents']++;

                    // Count purposes consent
                    $purposesConsentIds = $decoded->getPurposesConsent();
                    foreach ($purposesConsentIds as $purposeId) {
                        if (isset($purposes_map[$purposeId])) {
                            $purpose_counts[$purposeId]++;
                        }
                    }

                    // Count Legitimate purposes consent
                    $purposesLiConsentIds = $decoded->getPurposesLITransparency();
                    foreach ($purposesLiConsentIds as $purposeId) {
                        if (isset($purposes_map[$purposeId])) {
                            $purpose_li_counts[$purposeId]++;
                        }
                    }

                    // Count vendor consents
                    $vendorConsentIds = $decoded->getVendorConsent();
                    foreach ($vendorConsentIds as $vendorId) {
                        if (!isset($vendor_counts[$vendorId])) {
                            $vendor_counts[$vendorId] = 0;
                        }
                        $vendor_counts[$vendorId]++;
                    }

                    // Count vendor Li consents
                    $vendorLiConsentIds = $decoded->getVendorLegitimateInterest();
                    foreach ($vendorLiConsentIds as $vendorId) {
                        if (!isset($vendor_li_counts[$vendorId])) {
                            $vendor_li_counts[$vendorId] = 0;
                        }
                        $vendor_li_counts[$vendorId]++;
                    }

                    if(empty($purposesConsentIds) &&
                        empty($purposesLiConsentIds) &&
                        empty($vendorConsentIds) &&
                        empty($decoded->getSpecialFeatureOptIns())
                    ) {
                        $withdrawn_consents++;
                        $week_data['withdrawn_consents']++;
                    }
                }
            }
        }

        // Calculate percentages
        $withdrawn_consents_percentage = $total_consents > 0 ? round(($withdrawn_consents / $total_consents) * 100, 2) : 0;

        arsort($purpose_counts); // Sort purposes by count, descending
        $top_purposes = array_slice($purpose_counts, 0, 22, true);

        arsort($purpose_li_counts); // Sort purposes by count, descending
        $top_purposes_li = array_slice($purpose_li_counts, 0, 22, true);

        arsort($vendor_counts); // Sort vendors by count, descending
        $top_vendors = array_slice($vendor_counts, 0, 10, true);

        arsort($vendor_li_counts); // Sort vendors by count, descending
        $top_vendors_li = array_slice($vendor_li_counts, 0, 10, true);


        // Display results
        echo "<h1>Report ({$from} - {$to})</h1>";
        echo "<hr>";
        echo "<div class='wrap tcf-results'>";

        if($weekly):
            echo "<h5>Week-by-Week</h5>";

            echo "<div class='tcf-results__weeks'>";

            foreach ($weekly_stats as $week => $data) {

                // Parse the week and year from the $week string
                list($year, $week_number) = explode('-', $week);

                // Create a DateTime object for the first day of this week
                $startOfWeek = new DateTime();
                $startOfWeek->setISODate($year, $week_number);

                // Clone the start date and add 6 days to get the end of the week
                $endOfWeek = clone $startOfWeek;
                $endOfWeek->modify('+6 days');

                // Format the dates to display
                $displayWeek = $startOfWeek->format('M d') . ' - ' . $endOfWeek->format('M d, Y');

                // Prepare the previous week's date for comparisons, not for display
                $prev_week_date = clone $startOfWeek;
                $prev_week_date->modify('-1 week');
                $prev_week = $prev_week_date->format('o-W');

                echo "<div class='postbox single-week'><div class='inside'>";
                echo "<h6>Week of $displayWeek<br>($week)</h6>";
                echo "<h6>Ad Choices</h6>";
                $this->print_week_data('Total actions logged', $data['total_consents'], $weekly_stats[$prev_week]['total_consents'] ?? null);
                $this->print_week_data('Consent withdrawn', $data['withdrawn_consents'], $weekly_stats[$prev_week]['withdrawn_consents'] ?? null);
                echo "<h6 style='margin-top:10px;'>Cookie Preferences</h6>";
                $this->print_week_data('Total consents logged (at least 1 group)', $data['consents_cookies'], $weekly_stats[$prev_week]['consents_cookies'] ?? null);
                $this->print_week_data('No level chosen', $data['no_group'], $weekly_stats[$prev_week]['no_group'] ?? null);

                foreach ($cookie_types as $id => $label) {
                    $this->print_week_data($label, $data['cookie_counts'][$id], $weekly_stats[$prev_week]['cookie_counts'][$id] ?? null);
                }
                echo "</div></div>";
            }
            echo "</div><!-- / tcf-results__weeks -->";

            echo "<hr>";
        endif;

        echo "<h5>Totals</h5>";

        echo "<div class='ct-dashboard-report'>";
        echo "<div class='ct-dashboard-report__column'>";

            echo "<h2>Ad Choices</h2>";
            echo "<div class='postbox'><div class='inside'>";
            echo "<div class='number-container'><span class='number-label'>Total actions logged</span> <span class='number-value number-align'>{$total_consents}</span></div>";
            echo "<div class='number-container'><span class='number-label'>Consent withdrawn</span> <span class='number-value number-align'><small>({$withdrawn_consents_percentage}%)</small> {$withdrawn_consents}</span></div>";
            echo "</div></div>";

            echo "<div class='postbox'><div class='inside'>";
            echo "<p>Consented Purposes</p>";
            foreach ($top_purposes as $id => $count) {
                if($count > 0){
                    echo "<div class='number-container'><span class='number-label'>{$purposes_map[$id]}</span> <span class='number-value number-align'>$count</span></div>";
                }
            }
            echo "</div></div>";

            echo "<div class='postbox'><div class='inside'>";
            echo "<p>Consented Purposes (Legitimate interest)</p>";
            foreach ($top_purposes_li as $id => $count) {
                if($count > 0){
                    echo "<div class='number-container'><span class='number-label'>{$purposes_map[$id]}</span> <span class='number-value number-align'>$count</span></div>";
                }
            }
            echo "</div></div>";


            echo "<div class='postbox'><div class='inside'>";
            echo "<p>Top 10 Consented Partners</p>";
            foreach ($top_vendors as $vendorId => $count) {
                $vendorName = $vendors[$vendorId]['name'];
                echo "<div class='number-container'><span class='number-label'>$vendorName</span> <span class='number-value number-align'>$count</span></div>";
            }
            echo "</div></div>";

            echo "<div class='postbox'><div class='inside'>";
            echo "<p>Top 10 Consented Partners (Legitimate interest)</p>";
            foreach ($top_vendors_li as $vendorId => $count) {
                $vendorName = $vendors[$vendorId]['name'];
                echo "<div class='number-container'><span class='number-label'>$vendorName</span> <span class='number-value number-align'>$count</span></div>";
            }
            echo "</div></div>";

            echo "<hr>";

        echo "</div> <!-- / column -->";
        echo "<div class='ct-dashboard-report__column'>";

            echo "<h2>Cookie Preferences</h2>";
            echo "<div class='postbox'><div class='inside'>";
            echo "<div class='number-container'><span class='number-label'>Total consents logged (at least 1 group)</span> <span class='number-value number-align'>{$total_consents_cookies}</span></div>";
            echo "<div class='number-container'><span class='number-label'>No level chosen</span> <span class='number-value number-align'>{$cookies_no_group}</span></div>";
            echo "</div></div>";

            echo "<div class='postbox'><div class='inside'>";
            echo "<p>User consent breakdown</p>";
            foreach ($cookie_counts as $cookie_id => $count) {
                $percentage = $total_consents_cookies > 0 ? round(($count / $total_consents_cookies) * 100, 2) : 0;

                echo "<div class='number-container'><span class='number-label'>{$cookie_types[$cookie_id]}</span> <span class='number-value number-align'><small>($percentage%)</small> $count </span></div>";

            }
            echo "</div></div>";

        echo "</div> <!-- / column -->";
        echo "</div> <!-- / ct-dashboard-report -->";

        echo "</div>"; // Close wrap

    }
    private function print_week_data($label, $current, $previous) {
        $style = 'style="text-align: right;"';  // Aligns the text to the right for better visibility
        if ($previous === null) {
            $change_str = '<span style="color: gray;">N/A</span>';  // Gray color for N/A
        } else if ($previous == 0) {
            if ($current == 0) {
                $change_str = '<span style="color: black;">0%</span>';  // Black color for no change
            } else {
                $change_str = '<span style="color: green;">100%</span>';  // Green color for increase from 0
            }
        } else {
            $change = round((($current - $previous) / $previous) * 100, 2);
            if ($change > 0) {
                $icon = "↑";
                $color = "green";  // Positive change in green
            } elseif ($change < 0) {
                $icon = "↓";
                $color = "red";  // Negative change in red
            } else {
                $icon = "";
                $color = "black";  // No change in black
            }
            $change_str = "<span style='color: $color;'>". ($change > 0 ? "+" : "") . $change . "% $icon</span>";
        }

        echo "<div class='number-container'><span class='number-label'>$label</span><span class='number-value' $style>$current</span> <small class='number-container__icon'>$change_str</small></div>";
    }




    /**
     * @return mixed
     */
    public function add_option_fields()
    {

        $section_1_id =  $this->get_id().'_col_1';
        $section_2_id =  $this->get_id().'_col_2';
        $section_3_id =  $this->get_id().'_col_3';
        $section_4_id =  $this->get_id().'_col_4';
        $section_5_id =  $this->get_id().'_col_5';

        /* Section */

        add_settings_section(
            $section_3_id , // ID
            esc_html__('Main settings', 'ct-ultimate-gdpr'), // Title
            array($this, 'section3_description_callback'),
            $this->get_id() // Page
        );

        /* Section */

        add_settings_section(
            $section_1_id , // ID
            esc_html__('Ad Choices', 'ct-ultimate-gdpr'), // Title
            '',
            $this->get_id() // Page
        );

        add_settings_section(
            $section_2_id, // ID
            esc_html__('Cookie Preferences', 'ct-ultimate-gdpr'), // Title
            array($this, 'section2_description_callback'),
            $this->get_id() // Page
        );

        add_settings_section(
            $section_4_id, // ID
            esc_html__('Performance / SEO', 'ct-ultimate-gdpr'), // Title
            '',
            $this->get_id() // Page
        );

        add_settings_section(
            $section_5_id, // ID
            esc_html__('Plugins integrations', 'ct-ultimate-gdpr'), // Title
            '',
            $this->get_id() // Page
        );

        add_settings_field(
            'cmptcf_enable_tcf', // ID
            esc_html__('Enable TCF 2.2 Integration', 'ct-ultimate-gdpr'), // Title
            array($this, 'render_field_cmptcf_enable_tcf'), // Callback
            $this->get_id(), // Page
            $section_3_id // Section
        );

        add_settings_field(
            'cmptcf_lang', // ID
            esc_html__( 'Enable translations', 'ct-ultimate-gdpr' ), // Title
            array( $this, 'render_field_cmptcf_lang' ), // Callback
            $this->get_id(),
            $section_3_id
        );
        add_settings_field(
            'cmptcf_motive_color', // ID
            esc_html__( 'Motive color', 'ct-ultimate-gdpr' ), // Title
            array( $this, 'render_field_cmptcf_motive_color' ), // Callback
            $this->get_id(),
            $section_3_id
        );
        add_settings_field(
            'cmptcf_icon_position', // ID
            esc_html__( 'Trigger icon position', 'ct-ultimate-gdpr' ), // Title
            array( $this, 'render_field_cmptcf_icon_position' ), // Callback
            $this->get_id(),
            $section_3_id
        );

        add_settings_field(
            'cmptcf_head_script',
            esc_html__( 'Custom HEAD code', 'ct-ultimate-gdpr' ),
            array( $this, 'render_field_cmptcf_head_script' ),
            $this->get_id(),
            $section_3_id
        );
        add_settings_field(
            'cmptcf_exclude_pages', // Unique identifier for the field to disable logging
            esc_html__('Minimize on pages', 'ct-ultimate-gdpr'), // Title
            array($this, 'render_field_cmptcf_exclude_pages'), // Callback to render the field
            $this->get_id(), // The page on which to display this field
            $section_3_id // The section to which this field belongs
        );

        add_settings_field(
            'cmptcf_collapsible_read_more', // ID
            esc_html__('Use collapsible popup content', 'ct-ultimate-gdpr'), // Title
            array($this, 'render_field_cmptcf_collapsible_read_more'), // Callback
            $this->get_id(), // Page
            $section_3_id // Section
        );

        /**
         * Section
         */


        add_settings_field(
            'cmptcf_privacy_url',
            esc_html__('Privacy policy url', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_privacy_url'),
            $this->get_id(),
            $section_1_id
        );

        // Add settings field for manual update
        add_settings_field(
            'cmptcf_vl_manual_update',
            esc_html__('Update Vendor List', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_vl_manual_update'),
            $this->get_id(),
            $section_1_id
        );

        add_settings_field(
            'cmptcf_disable_tc_string_logging', // Unique identifier for the field to disable logging
            esc_html__('Disable user consent logging (TCString)', 'ct-ultimate-gdpr'), // Title
            array($this, 'render_field_cmptcf_disable_tc_string_logging'), // Callback to render the field
            $this->get_id(), // The page on which to display this field
            $section_1_id
        );


        add_settings_field(
            'cmptcf_vendors_ids', // Unique identifier for the field to disable logging
            esc_html__('Vendor ID Filter', 'ct-ultimate-gdpr'), // Title
            array($this, 'render_field_cmptcf_vendors_ids'), // Callback to render the field
            $this->get_id(), // The page on which to display this field
            $section_1_id // The section to which this field belongs
        );

        add_settings_field(
            'cmptcf_display_noniab',
            esc_html__('Display Non-IAB Vendors', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_display_noniab'),
            $this->get_id(),
            $section_1_id
        );

        add_settings_field(
            'cmptcf_debug_mode',
            esc_html__('Enable debug mode', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_debug_mode'),
            $this->get_id(),
            $section_1_id
        );



        add_settings_field(
            'cmptcf_consent_mode', // Unique identifier for the field to disable logging
            esc_html__('Google Consent Mode v2', 'ct-ultimate-gdpr'), // Title
            array($this, 'render_field_cmptcf_consent_mode'), // Callback to render the field
            $this->get_id(), // The page on which to display this field
            $section_2_id // The section to which this field belongs
        );

        add_settings_field(
            'cmptcf_pixelyoursite_consent', // Unique identifier for the field to disable logging
            esc_html__('PixelYourSite (Consent Mode v2)', 'ct-ultimate-gdpr'), // Title
            array($this, 'render_field_cmptcf_pixelyoursite_consent'), // Callback to render the field
            $this->get_id(), // The page on which to display this field
            $section_5_id // The section to which this field belongs
        );

        add_settings_field(
            'cmptcf_tab2_description',
            esc_html__('Introduction text', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_tab2_description'),
            $this->get_id(),
            $section_2_id
        );


        add_settings_field(
            'cmptcf_necessary_cookies',
            esc_html__('Necessary Cookies option visible', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_necessary_cookies'),
            $this->get_id(),
            $section_2_id
        );
        add_settings_field(
            'cmptcf_functional_cookies',
            esc_html__('Functional Cookies option visible', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_functional_cookies'),
            $this->get_id(),
            $section_2_id
        );
        add_settings_field(
            'cmptcf_analytics_cookies',
            esc_html__('Analytics Cookies option visible', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_analytics_cookies'),
            $this->get_id(),
            $section_2_id
        );
        add_settings_field(
            'cmptcf_advertising_cookies',
            esc_html__('Advertising Cookies option visible', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_advertising_cookies'),
            $this->get_id(),
            $section_2_id
        );

        // Performance
        add_settings_field(
            'cmptcf_defer_script_loading',
            esc_html__('Enable Defer Loading', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_defer_script_loading'),
            $this->get_id(),
            $section_4_id
        );

        add_settings_field(
            'cmptcf_vendor_fetching_disabled',
            esc_html__('Disable Ajax vendor description fetching', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_vendor_fetching_disabled'),
            $this->get_id(),
            $section_4_id
        );
        add_settings_field(
            'cmptcf_optimize_js',
            esc_html__('Preload and optimize JS loading', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_optimize_js'),
            $this->get_id(),
            $section_4_id
        );
        add_settings_field(
            'cmptcf_botlist',
            esc_html__('Bot User Agents', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_botlist'),
            $this->get_id(),
            $section_4_id
        );
        add_settings_field(
            'cmptcf_geolocation',
            esc_html__('EEA Geolocation', 'ct-ultimate-gdpr'),
            array($this, 'render_field_cmptcf_geolocation'),
            $this->get_id(),
            $section_4_id
        );
    }


    public function render_field_cmptcf_necessary_cookies() {
        $this->render_cookie_option_field('necessary_cookies', 'cmptcf_necessary_cookies');
    }
    public function render_field_cmptcf_advertising_cookies() {
        $this->render_cookie_option_field('advertising_cookies', 'cmptcf_advertising_cookies');
    }
    public function render_field_cmptcf_functional_cookies() {
        $this->render_cookie_option_field('functional_cookies', 'cmptcf_functional_cookies');
    }
    public function render_field_cmptcf_analytics_cookies() {
        $this->render_cookie_option_field('analytics_cookies', 'cmptcf_analytics_cookies');
    }

    public function render_field_cmptcf_disable_tc_string_logging(){
        $admin = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name(__FUNCTION__);

        printf(
            "<input class='ct-ultimate-gdpr-field' type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name(__FUNCTION__),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );

        // Description
        echo '<p class="description">';
        esc_html_e('User consent is automatically logged for compliance and auditing purposes. If you do not wish to save these records, make option On to disable logging.', 'ct-ultimate-gdpr');
        echo '</p>';
    }


    private function get_vl_last_update() {
        $text = '<span id="vl_updated_time">';
        // Retrieve the last update time from the database.
        $last_update = get_option($this->vl_key.'_last_updated');

        // Retrieve the vendor list data from the database.
        $vendor_list = get_option($this->vl_key);

        // Initialize a variable for the "recently_updated" date.
        $recently_updated = '';

        // Check if the vendor list is an array and contains the "recently_updated" key.
        if (is_array($vendor_list) && isset($vendor_list['lastUpdated'])) {
            $recently_updated = $vendor_list['lastUpdated'];
        }

        // Display the last update time.
        $text .= 'Last fetched: ' . esc_html($last_update) . '<br>';

        // Display the "recently_updated" date.
        $text .= 'Vendor List version: ' . esc_html($recently_updated);

        $text .= '</span>';

        return $text;
    }


    public function render_field_cmptcf_vl_manual_update(){
        // The nonce field for security
        wp_nonce_field('ct-ultimate-gdpr_vl_manual_update', 'ct-ultimate-gdpr_vl_manual_update');
        echo '<button id="ct-ultimate-gdpr_update_button" class="button button-primary">'.esc_html__('Update Now', 'ct-ultimate-gdpr').'</button>';
         echo "
         <script>
         jQuery(document).ready(function($) {
            $('#ct-ultimate-gdpr_update_button').on('click', function(e) {
                e.preventDefault();
                 var updateButton = $(this);
                 
                var data = {
                    'action': 'ctgdpr_update_vendor_list', // This should match the action hook for the AJAX call
                    '_nonce': $('#ct-ultimate-gdpr_vl_manual_update').val() // The nonce field passed for security
                };
                
                updateButton.prop('disabled', true).text('". esc_js(__('Updating...', 'ct-ultimate-gdpr')) . "');

        
                $.post(ajaxurl, data, function(response) {
                    if (response.success) {
                        alert('Vendor list updated');
                        $('#vl_updated_time').fadeOut(function() {
                            $(this).html(response.data.update_times_html).fadeIn();
                        });
                        
                        updateButton.text('" . esc_js(__('Update Now', 'ct-ultimate-gdpr')) ."');
                        updateButton.prop('disabled', false);
                    } else {
                        updateButton.text('". esc_js(__('Update Failed, Try Again', 'ct-ultimate-gdpr')) ."');
                    
                    }
                }).fail(function() {
                    updateButton.text('". esc_js(__('Update Failed, Try Again', 'ct-ultimate-gdpr')) ."');
                });
            });
        });
         </script>                  
";

        echo '<p class="description">';
        echo 'The vendor list is <strong>automatically updated weekly</strong>. Use the button above to manually update if immediate changes are required.';
        echo '<br><br>';
        echo $this->get_vl_last_update();
        echo '</p>';


    }

    public function ajax_ctgdpr_update_vendor_list(){
        check_ajax_referer('ct-ultimate-gdpr_vl_manual_update', '_nonce');

        $success = $this->fetch_vendor_list();

        if ($success) {
            $update_times_html = $this->get_vl_last_update();

            wp_send_json_success(array(
                'update_times_html' => $update_times_html
            ));
        } else {
            wp_send_json_error('Failed to update vendor list.');
        }
    }

    public function section3_description_callback()
    {
        echo '<h6>'. esc_html__('Activate the TCF 2.2 compliant Ad Choices modal. This allows users to select their advertising preferences and view a comprehensive list of all advertising partners (vendors).', 'ct-ultimate-gdpr') . '</h6>';
    }
    public function section2_description_callback()
    {
        echo '<h6>'. esc_html__('Manage your cookie settings in the Cookie Preferences tab, designed for Google Consent Mode integration.', 'ct-ultimate-gdpr'). '</h6>';
    }

    public function render_field_cmptcf_enable_tcf()
    {
        $admin = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name(__FUNCTION__);

        printf(
            "<input class='ct-ultimate-gdpr-field' type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name(__FUNCTION__),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );

    }

    public function render_field_cmptcf_collapsible_read_more()
    {
        $admin = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name(__FUNCTION__);

        printf(
            "<input class='ct-ultimate-gdpr-field' type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name(__FUNCTION__),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );

    }

    public function render_field_cmptcf_defer_script_loading(){
        $admin = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name(__FUNCTION__);

        printf(
            "<input class='ct-ultimate-gdpr-field' type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name(__FUNCTION__),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );
    }

    public function render_field_cmptcf_vendor_fetching_disabled(){
        $admin = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name(__FUNCTION__);

        printf(
            "<input class='ct-ultimate-gdpr-field' type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name(__FUNCTION__),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );

        // Description
        echo '<p class="description">';
        esc_html_e('By default, descriptions are loaded on demand to improve performance. To load all descriptions at once, set this option to On.', 'ct-ultimate-gdpr');
        echo '</p>';
    }

    public function render_field_cmptcf_optimize_js(){
        $admin = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name(__FUNCTION__);

        printf(
            "<input class='ct-ultimate-gdpr-field' type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name(__FUNCTION__),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );
 ;
    }


    public function render_field_cmptcf_botlist() {
        $admin      = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name( __FUNCTION__ );
        printf(
            "<input type='text' id='%s' name='%s' value='%s' />",
            $admin->get_field_name( __FUNCTION__ ),
            $admin->get_field_name_prefixed( $field_name ),
            $admin->get_option_value_escaped( $field_name, '')
        );

        // Description
        $description = esc_html__("Enter user agent strings separated by commas to identify bots and crawlers. The TCF consent banner won't show for these agents. Leave blank to display the banner to all visitors.", "ct-ultimate-gdpr");
        $description .= "<br><strong>". esc_html__("Example: ", "ct-ultimate-gdpr") . "</strong>" . esc_html($this->default_bots);

        echo "<p class='description'>{$description}</p>";
    }

    public function render_field_cmptcf_geolocation(){
        $admin = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name(__FUNCTION__);

        printf(
            "<input class='ct-ultimate-gdpr-field' type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name(__FUNCTION__),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );

        // Description
        echo '<p class="description">';
        esc_html_e("Display popup only for users in the European Economic Area (EEA) based on their browser's timezone.", 'ct-ultimate-gdpr');
        $disclaimer = "<br><strong>". esc_html__("Disclaimer: ", "ct-ultimate-gdpr") . "</strong>" . esc_html("Technically, detecting user location is never 100% reliable. However, using the browser timezone approach is privacy-friendly, fast, and compatible with static caching.", "ct-ultimate-gdpr");
        echo $disclaimer;
        echo '</p>';
    }



    public function render_field_cmptcf_display_noniab(){
        $admin = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name(__FUNCTION__);

        printf(
            "<input class='ct-ultimate-gdpr-field' type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name(__FUNCTION__),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );

    }

    public function render_field_cmptcf_debug_mode(){
        $admin = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name(__FUNCTION__);

        printf(
            "<input class='ct-ultimate-gdpr-field' type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name(__FUNCTION__),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );
        // Description
        echo '<p class="description">';
        esc_html_e('This will display the TC string in browser’s developer tools console for debugging purposes.', 'ct-ultimate-gdpr');
        echo '</p>';
    }


    public function render_field_cmptcf_privacy_url() {

        $admin      = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name( __FUNCTION__ );
        printf(
            "<input type='text' id='%s' name='%s' value='%s' />",
            $admin->get_field_name( __FUNCTION__ ),
            $admin->get_field_name_prefixed( $field_name ),
            $admin->get_option_value_escaped( $field_name, '')
        );
        // Description
        echo '<p class="description">';
        esc_html_e('ex: https://www.example.com/privacy/', 'ct-ultimate-gdpr');
        echo '</p>';
    }


    public function render_field_cmptcf_consent_mode(){
        $admin = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name(__FUNCTION__);

        printf(
            "<input class='ct-ultimate-gdpr-field' type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name(__FUNCTION__),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );

        // Description
        echo '<p class="description">';
        echo "This option enabled is transmitting user consent choices to GTM or gtag.js. This feature does not track users or collect data itself; it only communicates consent status to existing Google tracking setup. <br>It's essential to ensure your tracking code is added via the 'Custom HEAD code' option.";
        echo ' More info in: <a href="https://gdpr-plugin.readthedocs.io/en/latest/tcf/TCF.html#google-consent-mode-v2" target="_blank">docs</a>';
        echo '</p>';
    }


    public function render_field_cmptcf_pixelyoursite_consent(){
        $admin = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name(__FUNCTION__);

        printf(
            "<input class='ct-ultimate-gdpr-field' type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name(__FUNCTION__),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );

        // Description
        echo '<p class="description">';
        echo "Enable this option if you are using the PixelYourSite plugin with a configured Google Analytics tracking ID. GA4 tracking code is managed by the PixelYourSite plugin, so you can leave the Custom HEAD code field empty.";
        echo '</p>';
    }


    public function render_field_cmptcf_vendors_ids() {

        $admin      = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name( __FUNCTION__ );
        printf(
            "<input type='text' id='%s' name='%s' value='%s' />",
            $admin->get_field_name( __FUNCTION__ ),
            $admin->get_field_name_prefixed( $field_name ),
            $admin->get_option_value_escaped( $field_name, '')
        );

        // Description
        echo '<p class="description">';
        esc_html_e("Enter a list of vendor IDs, separated by commas, to selectively display only these vendors in the TCF modal. Enter 0 to exclude all IAB vendors from the display.", "ct-ultimate-gdpr");
        echo '</p>';

    }

    public function render_field_cmptcf_tab2_description() {

        $admin      = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name( __FUNCTION__ );
        printf(
            "<textarea id='%s_desc' name='%s_desc'>%s</textarea>",
            $admin->get_field_name( __FUNCTION__ ),
            $admin->get_field_name_prefixed( $field_name ),
            $admin->get_option_value_escaped( $field_name, '')
        );

        // Description
        echo '<p class="description">';
        esc_html_e("Custom text that will show up in the Tab", "ct-ultimate-gdpr");
        echo '</p>';

    }


    private function render_cookie_option_field($cookie_type, $function_suffix) {
        $admin      = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $function_suffix;

        // Checkbox
        printf(
            "<input type='checkbox' id='%s' name='%s' %s />",
            $admin->get_field_name($function_suffix),
            $admin->get_field_name_prefixed($field_name),
            $admin->get_option_value_escaped($field_name) ? 'checked' : ''
        );

        // TextArea for description
        printf(
            "<textarea id='%s_desc' name='%s_desc'>%s</textarea>",
            $admin->get_field_name($function_suffix),
            $admin->get_field_name_prefixed($field_name . '_desc'),
            $admin->get_option_value_escaped($field_name . '_desc', '')
        );

        echo '<p class="description">';
        esc_html_e('Custom Description for ' . str_replace('_', ' ', ucfirst($cookie_type)) . '.', 'ct-ultimate-gdpr');
        echo '</p>';
    }

    public function render_field_cmptcf_lang(){
        $admin       = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name  = $admin->get_field_name( __FUNCTION__ );
        $field_value = $admin->get_option_value( $field_name );

        printf(
            '<select class="ct-ultimate-gdpr-field" id="%s" name="%s">',
            $field_name,
            $admin->get_field_name_prefixed( $field_name )
        );

        // Add the initial 'Select' option
        echo '<option value="">' . esc_html__( 'English', 'ct-ultimate-gdpr' ) . '</option>';

        // Loop through the translations array
        foreach ( $this->tcf_translations as $value => $label ) {
            $selected = $value == $field_value ? 'selected' : '';
            echo "<option value='$value' $selected>" . esc_html($label) . "</option>";
        }

        echo '</select>';

        echo '<p class="description">';
        echo 'While you can enable translations for various languages, please be aware that certain content elements, such as the list of partners, purposes, examples, and descriptions are directly sourced from the official site of The Transparency & Consent Framework (TCF) v2.2 to ensure compliance with their standardized guidelines.';
        if (function_exists('icl_object_id') || defined('ICL_SITEPRESS_VERSION')) {
            echo '<br><br><strong>Info:</strong> Your consent modal will automatically use the language settings from WPML (WordPress Multilingual Plugin), if available.';
        }
        echo '</p>';

    }


    public function render_field_cmptcf_motive_color() {

        $admin      = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name( __FUNCTION__ );
        printf(
            "<input class='ct-color-field ct-ultimate-gdpr-field' type='text' id='%s' name='%s' value='%s' />",
            $admin->get_field_name( __FUNCTION__ ),
            $admin->get_field_name_prefixed( $field_name ),
            $admin->get_option_value_escaped( $field_name, '')
        );

    }

    public function render_field_cmptcf_icon_position(){
        $admin       = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name  = $admin->get_field_name( __FUNCTION__ );
        $field_value = $admin->get_option_value( $field_name );

        printf(
            '<select class="ct-ultimate-gdpr-field" id="%s" name="%s">',
            $field_name,
            $admin->get_field_name_prefixed( $field_name )
        );

        foreach ( $this->icon_position as $value => $label ) {
            $selected = $value == $field_value ? 'selected' : '';
            echo "<option value='$value' $selected>" . esc_html($label) . "</option>";
        }

        echo '</select>';

        echo '<p class="description">';
        echo 'Specify the location of the icon used to reopen the TCF consent modal';
        echo '</p>';

    }


    public function render_field_cmptcf_head_script() {

        $admin      = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name( __FUNCTION__ );
        printf(
            "<textarea class='ct-ultimate-gdpr-field' id='%s' name='%s' rows='10' cols='100'>%s</textarea>",
            $admin->get_field_name( __FUNCTION__ ),
            $admin->get_field_name_prefixed( $field_name ),
            $admin->get_option_value_escaped( $field_name, '' )
        );

        echo '<p class="description">';
        echo 'Use this option to add your Google Tag Manager, Google Analytics 4, or other tracking scripts directly into the HEAD of all pages.';
        echo '</p>';

    }

    public function render_field_cmptcf_exclude_pages() {

        $admin      = CT_Ultimate_GDPR::instance()->get_admin_controller();
        $field_name = $admin->get_field_name( __FUNCTION__ );
        printf(
            "<input type='text' id='%s' name='%s' value='%s' />",
            $admin->get_field_name( __FUNCTION__ ),
            $admin->get_field_name_prefixed( $field_name ),
            $admin->get_option_value_escaped( $field_name, '')
        );

        // Description
        echo '<p class="description">';
        esc_html_e("Enter page IDs, separated by commas, where the TCF modal will show minimized. Ideal for pages like Privacy Policy, ensuring minimal distraction.", "ct-ultimate-gdpr");
        echo '</p>';

    }

    /**
     * TCF functionality
     */

    private function output_crawler_detection_script() {
        $botlist_string = $this->get_botlist();

        if(!empty($botlist_string)){
            $botlist_array = array_map('trim', explode(',', $botlist_string));
            $botlist_json = json_encode($botlist_array);

            echo "<script>
    (function() {
        var crawlers = $botlist_json;
        var isCrawler = crawlers.some(function(crawler) {
            return navigator.userAgent.indexOf(crawler) !== -1;
        });

        window.isCtCrawlerDetected = isCrawler;
    })();
    </script>";
        };
    }

    private function output_geolocation_script(){

        if ($this->run_geolocation()) {
            // git: wrzutki/ct-timezones-gdpr
echo '<script>
!function(e){const r=["Atlantic/Azores","Europe/Lisbon","Atlantic/Madeira","Portugal","Atlantic/Reykjavik","Iceland","Europe/Dublin","Eire","Europe/London","GB","GB-Eire","Europe/Guernsey","Europe/Isle_of_Man","Europe/Jersey","Europe/Belfast","Atlantic/Canary","Europe/Madrid","Africa/Ceuta","Europe/Amsterdam","Europe/Berlin","Europe/Busingen","Arctic/Longyearbyen","Europe/Copenhagen","Europe/Oslo","Europe/Stockholm","Atlantic/Jan_Mayen","Europe/Bratislava","Europe/Brussels","Europe/Amsterdam","Europe/Luxembourg","Europe/Budapest","Europe/Copenhagen","Europe/Ljubljana","Europe/Luxembourg","Europe/Oslo","Atlantic/Jan_Mayen","Europe/Paris","Europe/Monaco","Europe/Prague","Europe/Bratislava","Europe/Rome","Europe/San_Marino","Europe/Vatican","Europe/Malta","Europe/Stockholm","Europe/Vaduz","Europe/Vienna","Europe/Warsaw","Poland","Europe/Zagreb","Europe/Zurich","Europe/Busingen","Europe/Vaduz","Europe/Athens","Europe/Bucharest","Europe/Helsinki","Europe/Mariehamn","Asia/Nicosia","Asia/Famagusta","Europe/Nicosia","Europe/Riga","Europe/Sofia","Europe/Tallinn","Europe/Vilnius"];e.ctCheckUserTimezone=function(){try{const e=Intl.DateTimeFormat().resolvedOptions().timeZone;return{isInGDPRTimezone:r.includes(e),userTimezone:e}}catch(e){return console.error("Error detecting user timezone:",e),{isInGDPRTimezone:!0,userTimezone:null}}}}(this);
</script>';

        }
    }

    private function get_bundle_file_name() {
        $dir = 'assets/tcf/dist/';
        $current_lang = $this->get_lang();

        // Default path
        $path = $dir . 'bundle.js';

        if (empty($current_lang)) {
            // English
            $locale_path = $dir . 'bundle-en.js';
        } else {
            $locale_path = $dir . 'bundle-' . $current_lang . '.js';
        }

        // Check if the locale-specific bundle exists
        if (file_exists(ct_ultimate_gdpr_path($locale_path))) {
            /**
             * comment out for development (load bundle.js)
             */
            $path = $locale_path;
        }

        return ct_ultimate_gdpr_url($path);
    }


    public function frontend_enqueue_scripts($hook_suffix)
    {
        /**
         * @TODO - optimiza loading places
         */
        if ($this->tcf_enabled()) {

            $this->output_crawler_detection_script();

            $this->output_geolocation_script();

            wp_enqueue_script('ct-ultimate-gdpr-tcfcmp', $this->get_bundle_file_name(),
                array(),
                $this->tcf_version,
                false
            );

            if($this->is_defer_enabled()){
                add_filter('script_loader_tag', function($tag, $handle) {
                    if ('ct-ultimate-gdpr-tcfcmp' !== $handle) {
                        return $tag;
                    }
                    // return str_replace(' src', ' async="async" src', $tag);
                    return str_replace(' src', ' defer="defer" src', $tag);
                }, 10, 2);
            }

            $base_url = rtrim(home_url(), '/');
            $minimize_modal = in_array(get_the_ID(), $this->get_excluded_pages());

            // Localize the script with new data
            $translation_array = array(
                'GVL_BASE_URL' => esc_url($base_url . '/wp-json/custom/v1'),
                'GVL_LATEST_FILENAME' => 'get-vendor-list?v='. $this->tcf_version,
                'DEBUG_MODE' => $this->is_debug_mode(),
                'CONSENT_MODE' => $this->is_consent_mode(),
                'HIDE_TAB_1' => "",
                'HIDE_TAB_2' => $this->should_hide_tab_2(),
                'VENDOR_FETCH_DISABLED' => $this->is_vendor_fetching_disabled(),
                'MINIMIZE' => $minimize_modal
            );

            wp_localize_script('ct-ultimate-gdpr-tcfcmp', 'ct_ultimate_gdpr_tcf', $translation_array);


        }
    }

    public function deregister_scripts(){

        // deregister other js files
        if ($this->tcf_enabled()) {
            if($this->do_optimize_js()){
                wp_dequeue_script('ct-ultimate-gdpr-service-facebook-pixel');
                wp_dequeue_script('ct-ultimate-gdpr-cookie-list');
                wp_dequeue_script('ct-ultimate-gdpr-shortcode-block-cookie');
                wp_dequeue_script('ct-ultimate-gdpr-cookie-popup');
                wp_dequeue_script('ct-ultimate-gdpr-base64');

                // CSS
                wp_dequeue_style('ct-ultimate-gdpr-jquery-ui');
                wp_dequeue_style('ct-ultimate-gdpr');
                wp_dequeue_style('ct-ultimate-gdpr-font-awesome');
                wp_dequeue_style('ct-ultimate-gdpr-cookie-popup');
                wp_dequeue_style('ct-ultimate-gdpr-custom-fonts');
            }
        }

    }

    public function get_header_script() {
        if ($this->tcf_enabled()) {
            $htmlCode = $this->get_option( 'cmptcf_head_script' );
            echo $htmlCode;
        }
    }

    public function add_custom_klaro_script()
    {

        if ($this->tcf_enabled()) {
            $base_url = home_url();
            $nonce = wp_create_nonce('ct_ultimate_gdpr_tcf_nonce');

            $defer_attr = "";
            if($this->is_defer_enabled()){
               $defer_attr = 'defer="defer"';
            }

            // preload data
            if($this->do_optimize_js()){
                $script_url_2 = esc_url($base_url . '/wp-json/custom/v1/get-vendor-list') . '?v=' . $this->tcf_version;
                echo '<link rel="preload" href="' . $script_url_2 . '" as="fetch" crossorigin="anonymous">';
            }

            $script_url = esc_url($base_url . '/wp-json/custom/v1/generate-tcf-config') . '?v=' . $this->tcf_version;
            echo '<script src="' . $script_url . '" '. $defer_attr .' ></script>';

            /**
             * preload
             */
            if($this->do_optimize_js()) {
                $script_url_3 = esc_url($this->get_bundle_file_name()) . '?ver=' . $this->tcf_version;
                echo '<link rel="preload" href="' . $script_url_3 . '" as="script">';
            }

            if (!$this->is_consent_logging_disabled()) {
                echo "
<script>
document.addEventListener('ctTCModelUpdated', function(e) {
    sendTCStringToServer(e.detail.encodedTCString, e.detail.cookiesConsent);
});
function sendTCStringToServer(encodedTCString, cookiesConsent) {    
    let params = new URLSearchParams({
        'action': 'ct_ultimate_gdpr_consent_give_tcf',
        'data[tcf]': encodedTCString,
        'nonce': '{$nonce}'
    });
    cookiesConsent.forEach(cookie => params.append('data[cookies][]', cookie));
    
    fetch('". admin_url('admin-ajax.php') ."', {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body: params
    })
    .then(response => response.ok ? response.json() : Promise.reject('Failed to load'))
    .then(data => {})
    .catch(error => {}); 
}
</script>
";
            }

            $motive_color = $this->get_motive_color();
            $collapse_read_more = $this->collapsible_enabled();
            $icon_pos = $this->get_icon_position();
            $custom_css = "";

if ($collapse_read_more) {
$custom_css .= "
.klaro .cookie-modal .read-more-btn {
    display: flex !important;
}
.klaro .cookie-modal #cm-tab1-panel {
    max-height: 200px;
}
@media (max-width: 767px) {
    .klaro .cookie-modal #cm-tab1-panel {
        max-height: 120px;
    }
}";
} else {
$custom_css .= "
@media (max-width: 767px) {
    .klaro .cookie-modal .cm-modal.cm-klaro {
        top: 0 !important;
    }
}";
}

if ($motive_color) {
$custom_css .= "
.klaro .cookie-modal .cm-list-input:checked+.cm-list-label .slider, .klaro .context-notice .cm-list-input:checked+.cm-list-label .slider, .klaro .cookie-notice .cm-list-input:checked+.cm-list-label .slider {
  background-color: " . $motive_color . " !important;
}
.klaro .cookie-modal .cm-list-input.required:checked+.cm-list-label .slider, .klaro .context-notice .cm-list-input.required:checked+.cm-list-label .slider, .klaro .cookie-notice .cm-list-input.required:checked+.cm-list-label .slider {
    background-color: " . $motive_color . " !important;
}
.klaro .cookie-modal .cm-list-input.half-checked:checked+.cm-list-label .slider, .klaro .context-notice .cm-list-input.half-checked:checked+.cm-list-label .slider, .klaro .cookie-notice .cm-list-input.half-checked:checked+.cm-list-label .slider {
    background-color: " . $motive_color . " !important;
}
.klaro .cookie-modal .cm-list-input.only-required+.cm-list-label .slider, .klaro .context-notice .cm-list-input.only-required+.cm-list-label .slider, .klaro .cookie-notice .cm-list-input.only-required+.cm-list-label .slider {
    background-color: " . $motive_color . " !important;
}
.klaro .cm-btn.cm-btn-success {
    background-color: " . $motive_color . " !important;    
}
.klaro .cookie-modal a, .klaro .context-notice a, .klaro .cookie-notice a {
    color: " . $motive_color . " !important;    
}
.klaro .clickable {
    color: " . $motive_color . " !important;
}
#ct-consent-btn-1 {
    color: " . $motive_color . ";    
}";
}

if ($icon_pos == 'bottom_left') {
$custom_css .= "
body .ct-consent-settings-button {
    right: auto;
    left: 10px;
}";
}
if ($icon_pos == 'bottom_center') {
$custom_css .= "
body .ct-consent-settings-button {
    right: auto;
    left: 50%;
    margin-left: -32px;
}";
}

if (!empty($custom_css)) {
    echo "<style>$custom_css</style>";
}
        }
    }

    public function klaro_config_init()
    {
        register_rest_route('custom/v1', '/generate-tcf-config', array(
            'methods' => 'GET',
            'callback' => array($this, 'generate_klaro_config'),
            'args' => array(
                'id' => array(
                    'required' => false
                )
            ),
            'permission_callback' => function () {
                return true; // You can add authentication here if needed
            },
        ));
    }

    public function vendor_list_init()
    {
        register_rest_route('custom/v1', '/get-vendor-list', array(
            'methods' => 'GET',
            'callback' => array($this, 'vendor_list_config'),
            'permission_callback' => function () {
                return true; // You can add authentication here if needed
            },
        ));
    }


    private function filter_vendors($allVendors) {

        // Get the list of vendor IDs to keep
        $vendorIdsToKeep = $this->get_filtered_vendors();

        if(empty($vendorIdsToKeep)){
            return $allVendors;
        }

        // Filter the array to keep only vendors with IDs in $vendorIdsToKeep
        $filteredVendors = array_filter($allVendors, function($vendor) use ($vendorIdsToKeep) {
            return in_array($vendor['id'], $vendorIdsToKeep);
        });

        return $filteredVendors;
    }

    public function vendor_list_config(WP_REST_Request $request) {
        $data = $this->get_vendor_list($this->only_used_vendors);

        if (empty($data)) {
            // Return an error if the data is not available
            return new WP_Error('no_data', 'No vendor data found', array('status' => 404));
        }

        // Return the data as a REST response
        return new WP_REST_Response($data, 200);
    }

    private function buildToggleSection($title, $items, $includeExtended = false, $ajaxFetch = true) {
        //if (empty($items)) return "";

        $dataAttrHtml = '';
        if($ajaxFetch){
            $dataAttrHtml = 'data-id="'. $title .'"';
        }

        $section = '<div class="toggle-section" '. $dataAttrHtml .'>';
        $section .= '<p class="toggle-title">{' . $title . '} ▼</p>';

        if ($includeExtended) {
            $section .= '<ul class="toggle-content" style="display:none;">';
            foreach ($items as $item) {
                if(is_array($item)) {
                    $section .= '<li>' . htmlspecialchars($item['name']) . '</li>';
                } else {
                    $section .= '<li>' . htmlspecialchars($item) . '</li>';
                }

            }
            $section .= '</ul>';
        }

        $section .= '</div>';
        return $section;
    }
    private function buildDetailsSection($titleKey, $detailsContent, $includeExtended = false) {
        //if (empty($detailsContent)) return "";

        $section = '<div class="toggle-section" data-id="'. $titleKey .'">';
        $section .= '<p class="toggle-title">{' . $titleKey . '} ▼</p>';

        if ($includeExtended) {
            $section .= '<div class="toggle-content" style="display:none;">';
            $section .= $detailsContent;
            $section .= '</div>';
        }

        $section .= '</div>';
        return $section;
    }


    private function build_description($p, $vendors = array()){
        if(empty($vendors)){
            $data = $this->get_vendor_list($this->only_used_vendors);
            $vendors = isset($data['vendors']) ? $data['vendors'] : null;
        }

        if(! is_array($vendors)){
            return;
        }

        if(!is_array($p)){
            $p = isset($vendors[$p]) ? $vendors[$p] : null;
        }

        if(is_null($p)){
            return ['', ''];
        }

        $pName = $p['name'];
        $privacyPolicy = $p['urls'][0]['privacy'];
        $legIntClaim = isset($p['urls'][0]['legIntClaim']) ? $p['urls'][0]['legIntClaim'] : null;

        // Map purposes to their descriptions
        $purposesConsent = array_map(function ($purposeId) {
            return $this->purposesMapping[$purposeId];
        }, $p['purposes']);

        $purposesLegitimate = array_map(function ($purposeId){
            return $this->purposesMapping[$purposeId];
        }, $p['legIntPurposes']);

        $specialPurposes = array_map(function ($specialPurposeId) {
            return isset($this->specialPurposesMapping[$specialPurposeId]) ? $this->specialPurposesMapping[$specialPurposeId] : null;
        }, $p['specialPurposes']);

        $features = array_map(function ($featureId)  {
            return $this->featuresMapping[$featureId];
        }, $p['features']);


        if (isset($p['dataDeclaration']) && is_array($p['dataDeclaration'])) {
            $dataDeclarations = array_map(function ($dataDeclarationId) {
                return $this->dataDeclarationMapping[$dataDeclarationId];
            }, $p['dataDeclaration']);
        }


        $seconds = isset($p['cookieMaxAgeSeconds']) ? $p['cookieMaxAgeSeconds'] : null;
        $consentExpiry = null;

        if ($seconds !== null) {
            $minutes = floor($seconds / 60);
            $hours = floor($minutes / 60);
            $days = floor($hours / 24);

            if ($days >= 1) {
                $consentExpiry = "$days days";
            } else {
                $consentExpiry = "$minutes minutes";
            }
        }

        $description = '';
        $fullDescription = '';

        if ($privacyPolicy) {
            $description .= '<p><a href="' . $privacyPolicy . '" target="_blank">{privacyPolicy}</a></p>';
        }
        if ($legIntClaim) {
            $description .= '<p><a href="' . $legIntClaim . '" target="_blank">{legitimateInterestClaim}</a></p>';
        }

        // copy initial state
        $fullDescription .= $description;


        // Purposes (Consent)
        //$description .= $this->buildToggleSection('purposesConsent', $purposesConsent);
        $fullDescription .= $this->buildToggleSection('purposesConsent', $purposesConsent, true);

        // Purposes (Legitimate Interest)
        //$description .= $this->buildToggleSection('purposesLegitimateInterest', $purposesLegitimate);
        $fullDescription .= $this->buildToggleSection('purposesLegitimateInterest', $purposesLegitimate, true);

        // Special Purposes
        //$description .= $this->buildToggleSection('specialPurposes', $specialPurposes);
        $fullDescription .= $this->buildToggleSection('specialPurposes', $specialPurposes, true);

        // Features
        //$description .= $this->buildToggleSection('features', $features);
        $fullDescription .= $this->buildToggleSection('features', $features, true);

        // Data Declaration
        //$description .= $this->buildToggleSection('dataDeclaration', $dataDeclarations);
        $fullDescription .= $this->buildToggleSection('dataDeclaration', $dataDeclarations, true);

        // Consent details
        $yourConsentDetails = '';

        if ($consentExpiry) {
            $yourConsentDetails .= '<p>{maximumCookieLifetime}: ' . htmlspecialchars($consentExpiry) . '</p>';
        }

        if ($p['cookieRefresh']) {
            $yourConsentDetails .= '<p>{cookieExpiryRefreshed}</p>';
        }

        if (isset($p['usesCookies']) && $p['usesCookies']) {
            $yourConsentDetails .= '<p>{trackingMethodCookies}' .
                (isset($p['usesNonCookieAccess']) && $p['usesNonCookieAccess'] ? ' {andOthers}' : '') .
                '</p>';
        } elseif (isset($p['usesNonCookieAccess']) && $p['usesNonCookieAccess']) {
            $yourConsentDetails .= '<p>{trackingMethodOthers}</p>';
        }

        // apply to main description string
        //$description .= $this->buildDetailsSection('deviceStorage', $yourConsentDetails);
        $fullDescription .= $this->buildDetailsSection('deviceStorage', $yourConsentDetails, true);

        if (isset($p['dataRetention'])) {
            $retentionDetails = "";

            if (isset($p['dataRetention']['stdRetention'])) {
                $retentionDetails .= "<strong>{standardRetention}: </strong>";
                $retentionDetails .= $this->formatRetention($p['dataRetention']['stdRetention']) . "<br>";
            }

            if (isset($p['dataRetention']['purposes']) && !empty($p['dataRetention']['purposes'])) {
                $retentionDetails .= "<strong>{purposes}:</strong><br>";
                foreach ($p['dataRetention']['purposes'] as $purposeId => $days) {
                    $purposeName = $this->purposesMapping[$purposeId];
                    $retentionDetails .= "$purposeName: " . $this->formatRetention($days) . "<br>";
                }
            }

            if (isset($p['dataRetention']['specialPurposes']) && !empty($p['dataRetention']['specialPurposes'])) {
                $retentionDetails .= "<strong>{specialPurposes}:</strong><br>";
                foreach ($p['dataRetention']['specialPurposes'] as $specialPurposeId => $days) {
                    if (isset($this->specialPurposesMapping[$specialPurposeId])) {
                        $specialPurposeName = $this->specialPurposesMapping[$specialPurposeId];
                        $retentionDetails .= "$specialPurposeName: " . $this->formatRetention($days) . "<br>";
                    } else {
                        // Handle the case where the special purpose ID doesn't exist in the mapping
                        $retentionDetails .= "Unknown special purpose ID: $specialPurposeId<br>";
                    }
                }
            }

            //$description .= $this->buildDetailsSection('dataRetention', $retentionDetails);
            $fullDescription .= $this->buildDetailsSection('dataRetention', $retentionDetails,true);
        }

        return [
            'shortDescription' => $description,
            'fullDescription' => $fullDescription
        ];
    }

    private function prepare_data($data, $staticConfig){

        // add filter to allow translations modifications
        $custom_translations = apply_filters('ct_ultimate_gdpr_tcf_translations', $staticConfig['translations']);

        $remove_secured_keys = apply_filters('ct_ultimate_gdpr_tcf_remove_secured_keys', true);


        /**
         * secure some keys from being overwritten (TCF approved texts)
         * ... disabled for now.. we need ability to change description if using only non-IAB vendors
         */
        $secured_keys = array(
            'consentModal' => array(
                'description222'
            )
        );
        if($remove_secured_keys){
            foreach ($custom_translations as $lang => &$values) {
                foreach ($secured_keys as $keyToUnset => $subKeys) {
                    foreach ($subKeys as $subKey) {
                        if (isset($values[$keyToUnset][$subKey])) {
                            unset($values[$keyToUnset][$subKey]);
                        }
                    }
                }
            }
        }


        $staticConfig['translations'] = wp_parse_args($custom_translations, $staticConfig['translations'] );


        // tab2 description
        $tab2_desc = $this->get_tab2_description();
        if($tab2_desc){
            $staticConfig["translations"]["en"]["tab2"]["description"] =  $tab2_desc;
        }


        // prepare data for partners description
        // Convert the 'purposes', 'specialPurposes', and 'features' arrays into associative arrays
        foreach ($data['purposes'] as $purpose) {
            $this->purposesMapping[$purpose['id']] = $purpose['name'];
        }

        foreach ($data['specialPurposes'] as $specialPurpose) {
            $this->specialPurposesMapping[$specialPurpose['id']] = $specialPurpose['name'];
        }

        foreach ($data['features'] as $feature) {
            $this->featuresMapping[$feature['id']] = $feature['name'];
        }

        foreach ($data['dataCategories'] as $dataCategory) {
            $this->dataDeclarationMapping[$dataCategory['id']] = [
                'name' => $dataCategory['name'],
                'description' => $dataCategory['description']
            ];
        }

        return $staticConfig;
    }

    private function get_vendors_count(){
        $vendorsPurposeCount = [];

        $all_vendors = array_merge($this->vendors, $this->non_iab_vendors);

        foreach ($all_vendors as $vendor) {
            foreach ($vendor['purposes'] as $purposeId) {
                if (!isset($vendorsPurposeCount[$purposeId])) {
                    $vendorsPurposeCount[$purposeId] = 0;
                }
                $vendorsPurposeCount[$purposeId]++;
            }
        }

        return $vendorsPurposeCount;
    }

    public function generate_klaro_config(WP_REST_Request $request)
    {

        $staticConfig_path = ct_ultimate_gdpr_path('assets/tcf/config.json');
        if (file_exists($staticConfig_path)) {
            $staticConfig = json_decode(file_get_contents($staticConfig_path), true);
        }

        // Fetch dynamic data (for example from a database, or another file)
        $data = $this->get_vendor_list();

        if(! $data){
            return;
        }
        // apply translations
        $current_lang = $this->get_lang();
        if($current_lang){
            $tcf_translations_path = ct_ultimate_gdpr_path("assets/tcf/lang/purposes-". $current_lang .".json");
            if (file_exists($tcf_translations_path)) {
                $tcf_translations = json_decode(file_get_contents($tcf_translations_path), true);
                // merge $data and $tcf_translations
                $data = array_merge($data, $tcf_translations);
                // set klaro lang
                $staticConfig['lang'] = $current_lang;
            }
        }

        /**
         * Filter vendors
         */
        $this->vendors = $this->filter_vendors($data['vendors']);



        $vendorsPurposeCount = $this->get_vendors_count();
        $vendorCount = count($this->vendors);

        // Non-IAB vendors
        $nonIabVendorCount = count($this->non_iab_vendors);

        // Modify the description by replacing {partnersCount} with the actual count
        $staticConfig['translations']['zz']['partnersCount'] =  (string)($vendorCount + $nonIabVendorCount);

        $staticConfig = $this->prepare_data($data, $staticConfig);

        $vendorDesc = array();


        // Generate the dynamic services node
        $services = array_merge(
            array_map(function ($p) use ($vendorsPurposeCount) {
                $illustrationsList = '';
                if (isset($p['illustrations']) && is_array($p['illustrations'])) {
                    $illustrationsList .= '<div class="toggle-section">';
                    $illustrationsList .= '<p class="toggle-title">{examples} ▼</p>';
                    $illustrationsList .= '<ul class="toggle-content" style="display:none;">';
                    foreach ($p['illustrations'] as $illustration) {
                        $illustrationsList .= '<li>' . $illustration . '</li>';
                    }
                    $illustrationsList .= '</ul></div>';
                }
                $vendorCount = isset($vendorsPurposeCount[$p['id']]) ? ' (' . $vendorsPurposeCount[$p['id']] . ' {partners})' : '';

                return array(
                    'name' => 'pu_' . $p['id'],
                    'title' => $p['name'] . $vendorCount,
                    'description' => $p['description'] . $illustrationsList,
                    'purposes' => array('purposes'),
                    'required' => false
                );
            }, $data['purposes']),
            array_map(function ($p) {
                return array(
                    'name' => 'spfu_' . $p['id'],
                    'title' => $p['name'],
                    'description' => $p['description'],
                    'purposes' => array('special_features'),
                    'required' => false
                );
            }, $data['specialFeatures']),
            array_map(function ($p) use (&$vendorDesc) {

                $desc_array = $this->build_description($p, $this->vendors);

                // single endpoint
                $description_full = $desc_array['fullDescription'];
                $vendorDesc[$p['id']] = $description_full;
                // single endpoint


                $vendor_item = array(
                    'name' => 've_' . $p['id'],
                    'title' => $p['name'],
                    'purposes' => array('partners'),
                    'required' => false,
                    'iab' => 'iab'
                );

                $vendor_item['description'] = '';

                if($this->is_vendor_fetching_disabled()){
                    $vendor_item['description'] .=  $desc_array['fullDescription'];
                } else {
                    $vendor_item['description'] .= $desc_array['shortDescription'];
                }

                if(!empty($p['legIntPurposes'])){
                    $vendor_item['purposesLegitimate'] = true;
                }

                return $vendor_item;

            }, $this->vendors)
        );


        /**
         * return single vendor desc data for ajax
         */
        $vendor_id = $request->get_param('id');
        if(!is_null($vendor_id)){
            $resultDescription = isset($vendorDesc[$vendor_id]) ? $vendorDesc[$vendor_id] : null;

            if(!is_null($resultDescription)){
                // Prepare the response
                $response = new WP_REST_Response($resultDescription);
                $response->set_status(200);
                $response->header('Content-Type', 'text/plain');

                return $response;
            }

            return new WP_Error( 'no_vendor_found', 'No description found', array( 'status' => 404 ) );
        }

        $purposesLegitimateVendors = array_filter($services, function($service) {
            return strpos($service['name'], 've_') === 0 && isset($service['purposesLegitimate']) && $service['purposesLegitimate'] === true;
        });

        $purposesLegitimateVendorsModified = array_map(function($service) {
            $service['name'] = str_replace('ve_', 'veli_', $service['name']);
            $service['purposes'] = ['li_partners'];
            $service['default'] = false;
            return $service;
        }, $purposesLegitimateVendors);


        $services = array_merge($services, $purposesLegitimateVendorsModified);


        /**
         * Add at the end
         *
         */
        $service1 = array_map(function ($p) {
            return array(
                'name' => 'fe_' . $p['id'],
                'title' => $p['name'],
                'description' => $p['description'],
                'purposes' => array('features'),
                'required' => true
            );
        }, $data['features']);

        $service2 = array_map(function ($p) {
            return array(
                'name' => 'sppu_' . $p['id'],
                'title' => $p['name'],
                'description' => $p['description'],
                'purposes' => array('special_purposes'),
                'required' => true
            );
        }, $data['specialPurposes']);

        $service3 = array_map(function ($p) {
            // Retrieve the privacy policy URL for English language
            $privacyPolicy = '';
            foreach ($p['urls'] as $url) {
                if ($url['langId'] === 'en') {
                    $privacyPolicy = $url['privacy'];
                    break;
                }
            }

            $non_iab_desc = '';

            // Add privacy policy link if it exists
            if (!empty($privacyPolicy)) {
                $non_iab_desc .= '<p><a href="' . $privacyPolicy . '" target="_blank">{privacyPolicy}</a></p>';
            }

            // Add vendor description
            $non_iab_desc .= wpautop($p['description']);

            // Add purposes
            if (!empty($p['purposes'])) {
                $purposesConsent = array_map(function ($purposeId) {
                    return $this->purposesMapping[$purposeId];
                }, $p['purposes']);

                $non_iab_desc .= $this->buildToggleSection('purposesConsent', $purposesConsent, true, false);
            }

            return array(
                'name' => 'niv_' . $p['id'],
                'title' => $p['name'],
                'description' => $non_iab_desc,
                'purposes' => array('partners'),
                'required' => false,
                'iab' => 'noniab'
            );
        }, $this->non_iab_vendors);

        // order of displaying
        $services = array_merge($services, $service3);
        $services = array_merge($services, $service1);
        $services = array_merge($services, $service2);


        $cookieCategories = $this->load_cookie_category_data();

        $cookieCategoriesList = array_values($cookieCategories);

        $services = array_merge($services, $cookieCategoriesList);

        // Overwrite the services node in the staticConfig
        $staticConfig['services'] = $services;

        // overwrite main privacy url
        $mainPrivacyUrl = $this->get_privacy_url();
        if($mainPrivacyUrl){
            $staticConfig['translations']['zz']['privacyPolicyUrl'] = $this->get_privacy_url();
        }

        $jsConfig = 'var klaroConfig2 = ' . json_encode($staticConfig) . ';';

        // Set content type to JavaScript
        header('Content-Type: text/javascript');

        // Return the JS string
        echo $jsConfig;
        exit;

    }

    private function load_cookie_category_data() {

        $cookieCategories = [
            'necessary' => [
                'name' => 'cookies_1',
                'title' => '{necessaryCookies}',
                'description' => '{necessaryCookiesDesc}',
                'purposes' => ['cookies'],
                'required' => true
            ],
            'functional' => [
                'name' => 'cookies_2',
                'title' => '{functionalCookies}',
                'description' => '{functionalCookiesDesc}',
                'purposes' => ['cookies'],
                'required' => false
            ],
            'analytics' => [
                'name' => 'cookies_3',
                'title' => '{analyticsCookies}',
                'description' => "{analyticsCookiesDesc}",
                'purposes' => ['cookies'],
                'required' => false
            ],
            'advertising' => [
                'name' => 'cookies_4',
                'title' => '{advertisingCookies}',
                'description' => '{advertisingCookiesDesc}',
                'purposes' => ['cookies'],
                'required' => false
            ]
        ];

        $options = $this->cmptcf_options;
        if ($options) {
            $options = maybe_unserialize($options);

            // Check each category and update or remove as necessary
            foreach ($cookieCategories as $key => &$category) {
                $optionEnabledKey = 'cmptcf_' . $key . '_cookies';
                $optionDescKey = 'cmptcf_' . $key . '_cookies_desc';

                // If 'enabled' state is not 'on', remove the element from the array
                if (!isset($options[$optionEnabledKey]) || $options[$optionEnabledKey] !== 'on') {
                    unset($cookieCategories[$key]);
                } else {
                    // Update description if available, otherwise keep original
                    if (!empty($options[$optionDescKey])) {
                        $category['description'] = $options[$optionDescKey];
                    }
                }
            }
            unset($category); // Unset reference to last element
        }

        return $cookieCategories;
    }

    private function should_hide_tab_2() {
        $cookieCategories = $this->load_cookie_category_data();

        if(empty($cookieCategories)){
            return true;
        }

        return false;
    }



    private function get_vendor_list($only_used = false) {
        // Check if the vendor list is stored in the database
        $vendor_list = get_option($this->vl_key);

        // If not, use the fallback static file
        if (!$vendor_list) {
            $file_path = ct_ultimate_gdpr_path('assets/tcf/vendor-list.json');
            if (file_exists($file_path)) {
                $vendor_list = json_decode(file_get_contents($file_path), true);
            }
        }

        if($only_used){
            $vendor_list['vendors'] = $this->filter_vendors($vendor_list['vendors']);
        }


        return $vendor_list;
    }

    public function update_vendor_list(){

        if(! $this->tcf_enabled()){
            return;
        }

        if (!current_user_can('manage_options')) {
            return;
        }

        if (!wp_next_scheduled('ctgdpr_update_vendor_list')) {
            wp_schedule_event(time(), 'weekly', 'ctgdpr_update_vendor_list');
        }
    }

    public function fetch_vendor_list() {
        $response = wp_remote_get('https://vendor-list.consensu.org/v3/vendor-list.json');

        if (is_wp_error($response)) {
            $error_message = $response->get_error_message();
            return false;
        } elseif (is_array($response) && $response['response']['code'] == 200) {
            $body = $response['body'];
            $data = json_decode($body, true);
            if (json_last_error() === JSON_ERROR_NONE && is_array($data)) {
                // Optionally, do additional checks to ensure $data contains what you expect.
                update_option($this->vl_key, $data,'no');
                update_option($this->vl_key.'_last_updated', current_time('mysql'),'no');
                return true;
            } else {
                // Handle the case where json_decode fails or does not return an array.
                return false;
            }
        } else {
            // Handle other kinds of HTTP errors.
            return false;
        }
    }

    public function give_consent_tcf(){

        check_ajax_referer('ct_ultimate_gdpr_tcf_nonce', 'nonce');

        $time = time();
        $data = ct_ultimate_gdpr_get_value('data', $this->get_request_array(), '' );

        if($data){
            $this->logger->consent( array(
                'type'       => 'tcf',
                'time'       => $time,
                'user_id'    => $this->user->get_current_user_id(),
                'user_ip'    => ct_ultimate_gdpr_get_permitted_user_ip(),
                'user_agent' => ct_ultimate_gdpr_get_permitted_user_agent(),
                'data'       => $data,
            ) );
        }
    }


    /**
     * Plugins
     */
    private function setup_pixelyoursite_filters()
    {
        add_filter('pys_analytics_storage_mode', array($this, 'set_pixelyoursite_default_consent'));
        add_filter('pys_ad_storage_mode', array($this, 'set_pixelyoursite_default_consent'));
        add_filter('pys_ad_user_data_mode', array($this, 'set_pixelyoursite_default_consent'));
        add_filter('pys_ad_personalization_mode', array($this, 'set_pixelyoursite_default_consent'));
    }

    public function set_pixelyoursite_default_consent($value)
    {
        return false;
    }
    public function add_pixelyoursite_script_footer()
    {
        ?>
        <script>
            // PixelYourSite integration
            window.dataLayer = window.dataLayer || [];
            function gtag() {
                dataLayer.push(arguments);
            }

            // Check if 'consentMode' exists in localStorage
            if(localStorage.getItem('consentMode') !== null) {
                const consentModeData = localStorage.getItem('consentMode');
                try {
                    const consentModeObj = JSON.parse(consentModeData);
                    if (typeof consentModeObj === 'object' && consentModeObj !== null) {
                        // consentModeObj['wait_for_update'] = 500;
                        gtag('consent', 'update', consentModeObj);
                    }
                } catch (e) {
                    // console.error('Invalid consentMode data in localStorage:', e);
                }
            }
        </script>
        <?php
    }

    /**
     * Non-IAB vendors
     */
    function tcf_add_admin_menu() {


        $this->submenu_page_slug_niv = add_submenu_page(
            CT_Ultimate_GDPR::instance()->get_admin_controller()->get_option_name(),
            esc_html__('TCF Non-IAB Vendors', 'ct-ultimate-gdpr'),
            esc_html__('TCF Non-IAB Vendors', 'ct-ultimate-gdpr'),
            'manage_options',
            'ct-ultimate-gdpr-cmptcf-non-iab-vendors',
            array($this, 'tcf_render_admin_page')
        );

    }
    public function tcf_render_admin_page() {
        echo $this->get_vendor_form_html();
        echo $this->get_vendor_list_html();
    }

    public function tcf_shortcode() {
        return $this->get_vendor_list_html(false);
    }

    public function get_vendor_list_html($show_delete = true) {
        ob_start();
        ?>
        <table id="tcf-vendors-list" class="widefat fixed striped">
            <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Purposes</th>
                <th>Description</th>
                <th>Privacy policy URL</th>
                <th>Actions</th>
            </tr>
            </thead>
            <tbody>
            <!-- Vendor rows will be populated here via JS -->
            </tbody>
        </table>
        <script>

                // Fetch and display vendors on page load
                function fetchVendors() {
                    jQuery.ajax({
                        url: ajaxurl,
                        data: {
                            action: 'fetch_vendors',
                            show_delete: <?php echo $show_delete ? 'true' : 'false'; ?>
                        },
                        success: function(response) {
                            jQuery('#tcf-vendors-list tbody').html(response);
                        }
                    });
                }
                fetchVendors();

        </script>
        <?php
        return ob_get_clean();
    }

    public function get_vendor_form_html() {

        $data = $this->get_vendor_list();
        $vendors = isset($data['vendors']) ? $data['vendors'] : null;
        $purposes = isset($data['purposes']) ? $data['purposes'] : null;

        $purposes_map = [];
        foreach ($purposes as $item) {
            if (isset($item['id']) && isset($item['name'])) {
                $purposes_map[$item['id']] = $item['name'];
            }
        }
        ob_start();
        ?>
        <div class="wrap">
            <h1>TCF Non-IAB Vendors</h1>
            <form id="tcf-add-vendor-form" action="<?php echo admin_url('admin-post.php'); ?>" method="post" class="form-wrap">
                <h2>Add New Vendor</h2>
                <table class="form-table">
                    <tr>
                        <th><label for="vendor-name">Vendor Name</label></th>
                        <td><input type="text" id="vendor-name" name="vendor-name" class="regular-text" required></td>
                    </tr>
                    <tr>
                        <th><label for="vendor-purposes">Purposes</label></th>
                        <td>
                            <select id="vendor-purposes" name="vendor-purposes[]" multiple="multiple" class="regular-select">
                                <?php foreach ($purposes_map as $purpose_id => $purpose_name): ?>
                                    <option value="<?php echo $purpose_id; ?>"><?php echo $purpose_name; ?></option>
                                <?php endforeach; ?>
                            </select>
                        </td>
                    </tr>
                    <tr>
                        <th><label for="vendor-description">Vendor Description</label></th>
                        <td><textarea id="vendor-description" name="vendor-description" class="large-text" rows="5" required></textarea></td>
                    </tr>
                    <tr>
                        <th><label for="vendor-privacy-url">Privacy URL</label></th>
                        <td><input type="url" id="vendor-privacy-url" name="vendor-privacy-url" class="regular-text" required></td>
                    </tr>
                </table>

                <input type="hidden" name="action" value="add_vendor">
                <?php wp_nonce_field('add_vendor_nonce', 'vendor_nonce'); ?>

                <p class="submit">
                    <button type="submit" class="button button-primary">Add Vendor</button>
                </p>
            </form>


        </div>
        <script>
            jQuery(document).ready(function($) {
                if (typeof $.fn.select2 !== 'undefined') {
                    $('#vendor-purposes').select2({
                        placeholder: 'Select purposes',
                        width: '100%'
                    });
                }

                // Handle form submissions
                $('#tcf-add-vendor-form').on('submit', function(event) {
                    event.preventDefault();

                    var formData = $(this).serialize();
                    var actionUrl = $(this).attr('action');
                    // formData += '&action=add_vendor';

                    $.ajax({
                        url: actionUrl,
                        type: 'POST',
                        data: formData,
                        success: function(response) {
                            if (response.success) {
                                fetchVendors();
                                $('#tcf-add-vendor-form')[0].reset();
                                $('#vendor-purposes').val(null).trigger('change');
                            } else {
                                alert('Error: ' + response.data);
                            }
                        }
                    });
                });

                $(document).on('click', '.delete-vendor', function() {
                    var vendorId = $(this).data('id');

                    $.ajax({
                        url: ajaxurl,
                        type: 'POST',
                        data: {
                            action: 'delete_vendor',
                            vendor_id: vendorId
                        },
                        success: function(response) {
                            if (response.success) {
                                fetchVendors(); // Refresh vendor list
                            } else {
                                alert('Error: ' + response.data);
                            }
                        }
                    });
                });
            });

        </script>
        <?php
        return ob_get_clean();
    }
    function tcf_handle_add_vendor() {

        $last_vendor_option_name = $this->vl_key2 .'_last_vendor';

        // Verify nonce
        if (!isset($_POST['vendor_nonce']) || !wp_verify_nonce($_POST['vendor_nonce'], 'add_vendor_nonce')) {
            wp_die('Invalid nonce');
        }

        if (isset($_POST['vendor-name'])) {
            $vendor_name = sanitize_text_field($_POST['vendor-name']);
            $vendor_purposes=[];
            if(isset($_POST['vendor-purposes'])){
                $vendor_purposes = array_map('intval', $_POST['vendor-purposes']);
            };

            $vendor_description = wp_kses_post($_POST['vendor-description']);
            $vendor_privacy_url = esc_url_raw($_POST['vendor-privacy-url']);

            $vendors = $this->get_non_iab_vendors();

            // Generate new vendor ID
            $last_vendor_id = get_option($last_vendor_option_name, 0);
            $new_vendor_id = $last_vendor_id + 1;

            // Create new vendor entry
            $new_vendor = [
                'id' => $new_vendor_id,
                'name' => $vendor_name,
                'description' => $vendor_description,
                'purposes' => $vendor_purposes,
                'urls' => [
                    [
                        'langId' => 'en', // Assuming English for now
                        'privacy' => $vendor_privacy_url
                    ]
                ]
            ];

            // Add new vendor to the list
            $vendors[] = $new_vendor;

            update_option($this->vl_key2, $vendors);
            update_option($last_vendor_option_name, $new_vendor_id);

            wp_send_json_success();
            exit;
        } else {
            wp_die('Invalid data');
        }
    }
    function tcf_fetch_vendors() {
        $show_delete = isset($_GET['show_delete']) ? filter_var($_GET['show_delete'], FILTER_VALIDATE_BOOLEAN) : false;

        $vendors = $this->get_non_iab_vendors();
        foreach ($vendors as $vendor) {
            echo '<tr>';
            echo '<td>' . esc_html($vendor['id']) . '</td>';
            echo '<td>' . esc_html($vendor['name']) . '</td>';
            echo '<td>' . implode(', ', array_map('intval', $vendor['purposes'])) . '</td>';

            // Display description if available (it was part of the old format)
            if (isset($vendor['description'])) {
                echo '<td>' . esc_html($vendor['description']) . '</td>';
            } else {
                echo '<td></td>';
            }

            // Display the URLs (assuming only one language entry for now)
            if (!empty($vendor['urls'][0])) {
                $url_info = $vendor['urls'][0];
                echo '<td><a href="' . esc_url($url_info['privacy']) . '" target="_blank">' . esc_html($url_info['privacy']) . '</a></td>';
            } else {
                echo '<td></td>';
            }

            if ($show_delete):
                echo '<td><button class="delete-vendor" data-id="' . esc_attr($vendor['id']) . '">Delete</button></td>';
            else:
                echo '<td></td>';
            endif;
            echo '</tr>';
        }
        wp_die();
    }

    function tcf_handle_delete_vendor() {
        if (isset($_POST['vendor_id'])) {
            $vendor_id = intval($_POST['vendor_id']);
            $vendors = $this->get_non_iab_vendors();

            // Filter out the vendor with the specified ID
            $vendors = array_filter($vendors, function($vendor) use ($vendor_id) {
                return $vendor['id'] !== $vendor_id;
            });

            // Save the updated list of vendors back to the database
            update_option($this->vl_key2, $vendors);

            wp_send_json_success();
        } else {
            wp_send_json_error('Invalid vendor ID');
        }
    }

    function tcf_enqueue_admin_scripts($hook_suffix) {
        // Get the current screen
        $screen = get_current_screen();

        // Check if we are on the specific admin page
        if ($screen->id === $this->submenu_page_slug_niv) {
            wp_enqueue_style('ct-select2-css', 'https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css');
            wp_enqueue_script('ct-select2-js', 'https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/js/select2.min.js', array('jquery'), '', true);
        }
    }


    /**
     * Helpers
     */

    private function formatRetention($days) {

        if ($days === 0) {
            return 0;
        }

        $years = floor($days / 365);
        $remainingDays = $days % 365;

        $formatted = "";
        if ($years > 0) {
            $formatted .= "$years year" . ($years > 1 ? "s" : "");
        }

        if ($remainingDays > 0) {
            if ($formatted) {
                $formatted .= " - ";
            }
            $formatted .= "$remainingDays day" . ($remainingDays > 1 ? "s" : "");
        }

        return $formatted;
    }

    public function gdpr_popup_should_render(){
        return false;
    }
    public function do_not_render(){
        return '';
    }

}
