<?php
/**
 * Plugin Name: Maple GDPR Cookies
 * Plugin URI: https://mapleopentech.ca/maple-gdpr-cookies
 * Description: A lightweight, secure, and fully GDPR-compliant cookie consent plugin with script blocking
 * Version: 4.1.3
 * Requires at least: 5.0
 * Requires PHP: 7.2
 * Author: Your Name
 * License: GPL v2 or later
 * Text Domain: maple-gdpr-cookies
 * WC requires at least: 3.0
 * WC tested up to: 8.5
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

// Define plugin constants
define('MGC_PLUGIN_FILE', __FILE__);
define('MGC_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('MGC_PLUGIN_URL', plugin_dir_url(__FILE__));
define('MGC_PLUGIN_VERSION', '4.1.3');
define('MGC_DB_VERSION', '2.0');
define('MGC_MIN_PHP_VERSION', '7.2');
define('MGC_MIN_WP_VERSION', '5.0');

/**
 * Plugin activation checks
 */
function mgc_check_requirements() {
    $errors = array();

    // Check PHP version
    if (version_compare(PHP_VERSION, MGC_MIN_PHP_VERSION, '<')) {
        $errors[] = sprintf(
            __('Maple GDPR Cookies requires PHP %s or higher. Your server is running PHP %s.', 'maple-gdpr-cookies'),
            MGC_MIN_PHP_VERSION,
            PHP_VERSION
        );
    }

    // Check WordPress version
    if (version_compare(get_bloginfo('version'), MGC_MIN_WP_VERSION, '<')) {
        $errors[] = sprintf(
            __('Maple GDPR Cookies requires WordPress %s or higher. You are running WordPress %s.', 'maple-gdpr-cookies'),
            MGC_MIN_WP_VERSION,
            get_bloginfo('version')
        );
    }

    // Check for MySQL version if using utf8mb4
    global $wpdb;
    if ($wpdb->db_version() && version_compare($wpdb->db_version(), '5.5.3', '<')) {
        $errors[] = __('Maple GDPR Cookies requires MySQL 5.5.3 or higher for utf8mb4 support.', 'maple-gdpr-cookies');
    }

    return $errors;
}

/**
 * Create database tables on activation
 */
function mgc_create_tables() {
    global $wpdb;

    $charset_collate = $wpdb->get_charset_collate();
    $table_name = $wpdb->prefix . 'mgc_consent_logs';

    $sql = "CREATE TABLE IF NOT EXISTS $table_name (
        id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
        user_id bigint(20) UNSIGNED NULL,
        ip_address varchar(45) NOT NULL,
        user_agent varchar(255) NOT NULL,
        consent_type varchar(20) NOT NULL,
        categories text NULL,
        consent_given tinyint(1) NOT NULL,
        consent_date datetime NOT NULL,
        PRIMARY KEY  (id),
        KEY user_id (user_id),
        KEY ip_address (ip_address),
        KEY consent_date (consent_date)
    ) $charset_collate;";

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);

    // Store database version
    update_option('mgc_db_version', MGC_DB_VERSION);
}

/**
 * Set default options on activation
 */
function mgc_set_defaults() {
    $default_options = array(
        'enabled' => true,
        'notice_text' => __('We use cookies to make this site work properly and to understand how you use it. This includes <strong>essential cookies</strong> (required), <strong>analytics cookies</strong> (to understand site usage), and <strong>marketing cookies</strong> (for personalized content). You can accept all, reject optional cookies, or customize your preferences.', 'maple-gdpr-cookies'),
        'accept_button_text' => __('Accept All', 'maple-gdpr-cookies'),
        'reject_button_text' => __('Reject Optional', 'maple-gdpr-cookies'),
        'settings_button_text' => __('Cookie Settings', 'maple-gdpr-cookies'),
        'privacy_policy_url' => get_privacy_policy_url(),
        'privacy_policy_text' => __('Privacy Policy', 'maple-gdpr-cookies'),
        'cookie_expiry' => 365,
        'position' => 'bottom',
        'theme' => 'light',
        'animation' => 'slide',
        'button_color' => 'blue',
        'custom_button_color' => '',
        'custom_button_hover_color' => '',
        'show_reject_button' => true,
        'show_settings_button' => true,
        'preference_display_type' => 'icon',
        'custom_css' => '',
        'enable_analytics' => true,
        'enable_marketing' => true,
        'enable_functional' => true,
        'enable_logging' => true
    );

    foreach ($default_options as $key => $value) {
        if (get_option('mgc_' . $key) === false) {
            add_option('mgc_' . $key, $value);
        }
    }
}

/**
 * Clear all plugin caches - FIXED VERSION
 */
function mgc_clear_all_caches() {
    // Method 1: Clear WordPress object cache (if available)
    if (function_exists('wp_cache_flush')) {
        wp_cache_flush();
    }

    // Method 2: Clear plugin-specific transients
    global $wpdb;

    // Get all mgc transients
    $transients = $wpdb->get_col(
        "SELECT option_name FROM $wpdb->options
         WHERE option_name LIKE '_transient_mgc_%'
         OR option_name LIKE '_transient_timeout_mgc_%'"
    );

    // Delete each transient
    foreach ($transients as $transient) {
        if (strpos($transient, '_transient_timeout_') === 0) {
            continue; // Skip timeout entries, they'll be deleted with the transient
        }

        $transient_key = str_replace('_transient_', '', $transient);
        delete_transient($transient_key);
    }

    // Method 3: Clear specific plugin caches
    $cache_keys = array(
        'mgc_settings',
        'mgc_stats',
        'mgc_consent_logs'
    );

    foreach ($cache_keys as $key) {
        wp_cache_delete($key, 'maple-gdpr-cookies');
        delete_transient($key);
    }

    // Method 4: Clear WooCommerce cache if present
    if (function_exists('wc_delete_shop_order_transients')) {
        wc_delete_shop_order_transients();
    }

    // Method 5: Trigger cache clear hooks for other plugins
    do_action('mgc_clear_caches');
}

/**
 * Plugin activation
 */
function mgc_activate() {
    // Check requirements
    $errors = mgc_check_requirements();
    if (!empty($errors)) {
        deactivate_plugins(plugin_basename(__FILE__));
        wp_die(
            implode('<br>', $errors),
            __('Plugin Activation Error', 'maple-gdpr-cookies'),
            array('back_link' => true)
        );
    }

    // Create database tables
    mgc_create_tables();

    // Set default options
    mgc_set_defaults();

    // Clear all caches - now using fixed function
    mgc_clear_all_caches();

    // Set activation flag
    set_transient('mgc_activation_redirect', true, 30);
}
register_activation_hook(__FILE__, 'mgc_activate');

/**
 * Plugin deactivation
 */
function mgc_deactivate() {
    // Clear all caches
    mgc_clear_all_caches();

    // Clear scheduled events
    wp_clear_scheduled_hook('mgc_cleanup_logs');
    wp_clear_scheduled_hook('mgc_optimize_database');
}
register_deactivation_hook(__FILE__, 'mgc_deactivate');

/**
 * Plugin uninstall - only if user chooses to delete data
 */
function mgc_uninstall() {
    global $wpdb;

    // Always clear scheduled tasks even if keeping data
    wp_clear_scheduled_hook('mgc_cleanup_logs');
    wp_clear_scheduled_hook('mgc_optimize_database');

    // Check if user wants to keep data
    if (get_option('mgc_keep_data_on_uninstall', false)) {
        return;
    }

    // Drop database tables
    $table_name = $wpdb->prefix . 'mgc_consent_logs';
    $wpdb->query("DROP TABLE IF EXISTS $table_name");

    // Delete all plugin options
    $wpdb->query("DELETE FROM $wpdb->options WHERE option_name LIKE 'mgc_%'");

    // Clear all caches
    mgc_clear_all_caches();
}
register_uninstall_hook(__FILE__, 'mgc_uninstall');

/**
 * Load plugin textdomain for translations
 */
function mgc_load_textdomain() {
    load_plugin_textdomain(
        'maple-gdpr-cookies',
        false,
        dirname(plugin_basename(__FILE__)) . '/languages'
    );
}
add_action('plugins_loaded', 'mgc_load_textdomain');

/**
 * Enqueue frontend scripts and styles
 */
function mgc_enqueue_frontend_assets() {
    // Only load if enabled
    if (!get_option('mgc_enabled', true)) {
        return;
    }

    // Check if user already has consent cookie
    $has_consent = isset($_COOKIE['mgc_consent']);

    // Enqueue CSS
    wp_enqueue_style(
        'mgc-frontend',
        MGC_PLUGIN_URL . 'public/css/frontend.css',
        array(),
        MGC_PLUGIN_VERSION
    );

    // Add custom CSS if provided
    $custom_css = get_option('mgc_custom_css');
    if (!empty($custom_css)) {
        wp_add_inline_style('mgc-frontend', $custom_css);
    }

    // Add custom button colors if provided
    $custom_button_color = get_option('mgc_custom_button_color');
    $custom_button_hover_color = get_option('mgc_custom_button_hover_color');

    if (!empty($custom_button_color) || !empty($custom_button_hover_color)) {
        $color_css = '';

        if (!empty($custom_button_color)) {
            $color_css .= '.mgc-button { background: ' . esc_attr($custom_button_color) . ' !important; }';
            $color_css .= '.mgc-floating-button { background: ' . esc_attr($custom_button_color) . ' !important; }';
        }

        if (!empty($custom_button_hover_color)) {
            $color_css .= '.mgc-button:hover { background: ' . esc_attr($custom_button_hover_color) . ' !important; }';
            $color_css .= '.mgc-floating-button:hover { background: ' . esc_attr($custom_button_hover_color) . ' !important; }';
        }

        wp_add_inline_style('mgc-frontend', $color_css);
    }

    // Enqueue the compliant JS (blocks scripts before consent)
    wp_enqueue_script(
        'mgc-frontend-compliant',
        MGC_PLUGIN_URL . 'public/js/frontend-compliant.js',
        array(),
        MGC_PLUGIN_VERSION,
        false // Load in head for early script blocking
    );

    // Localize script with settings
    wp_localize_script('mgc-frontend-compliant', 'mgcSettings', array(
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('mgc_consent_nonce'),
        'noticeText' => get_option('mgc_notice_text'),
        'acceptButtonText' => get_option('mgc_accept_button_text'),
        'rejectButtonText' => get_option('mgc_reject_button_text'),
        'settingsButtonText' => get_option('mgc_settings_button_text'),
        'privacyPolicyUrl' => get_option('mgc_privacy_policy_url'),
        'privacyPolicyText' => get_option('mgc_privacy_policy_text'),
        'cookieExpiry' => intval(get_option('mgc_cookie_expiry', 365)),
        'position' => get_option('mgc_position', 'bottom'),
        'theme' => get_option('mgc_theme', 'light'),
        'animation' => get_option('mgc_animation', 'slide'),
        'buttonColor' => get_option('mgc_button_color', 'blue'),
        'showRejectButton' => (bool) get_option('mgc_show_reject_button', true),
        'showSettingsButton' => (bool) get_option('mgc_show_settings_button', true),
        'preferenceDisplayType' => get_option('mgc_preference_display_type', 'icon')
    ));
}
add_action('wp_enqueue_scripts', 'mgc_enqueue_frontend_assets');

/**
 * Enqueue admin scripts and styles
 */
function mgc_enqueue_admin_assets($hook) {
    // Only load on plugin settings pages
    if (strpos($hook, 'maple-gdpr-cookies') === false) {
        return;
    }

    // Enqueue WordPress color picker
    wp_enqueue_style('wp-color-picker');

    // Enqueue admin CSS
    wp_enqueue_style(
        'mgc-admin',
        MGC_PLUGIN_URL . 'admin/css/admin.css',
        array(),
        MGC_PLUGIN_VERSION
    );

    // Enqueue admin JS
    wp_enqueue_script(
        'mgc-admin',
        MGC_PLUGIN_URL . 'admin/js/admin.js',
        array('jquery', 'wp-color-picker'),
        MGC_PLUGIN_VERSION,
        true
    );
}
add_action('admin_enqueue_scripts', 'mgc_enqueue_admin_assets');

/**
 * Add admin menu
 */
function mgc_add_admin_menu() {
    add_menu_page(
        __('Maple GDPR Cookies', 'maple-gdpr-cookies'),
        __('Cookie Settings', 'maple-gdpr-cookies'),
        'manage_options',
        'maple-gdpr-cookies',
        'mgc_admin_page',
        'dashicons-shield',
        100
    );

    add_submenu_page(
        'maple-gdpr-cookies',
        __('Settings', 'maple-gdpr-cookies'),
        __('Settings', 'maple-gdpr-cookies'),
        'manage_options',
        'maple-gdpr-cookies',
        'mgc_admin_page'
    );

    add_submenu_page(
        'maple-gdpr-cookies',
        __('Consent Logs', 'maple-gdpr-cookies'),
        __('Consent Logs', 'maple-gdpr-cookies'),
        'manage_options',
        'maple-gdpr-cookies-logs',
        'mgc_logs_page'
    );
}
add_action('admin_menu', 'mgc_add_admin_menu');

/**
 * Admin page callback
 */
function mgc_admin_page() {
    if (!current_user_can('manage_options')) {
        return;
    }

    // Handle form submission
    if (isset($_POST['mgc_save_settings']) && check_admin_referer('mgc_settings_nonce')) {
        mgc_save_settings();
    }

    include MGC_PLUGIN_PATH . 'admin/views/settings.php';
}

/**
 * Logs page callback
 */
function mgc_logs_page() {
    if (!current_user_can('manage_options')) {
        return;
    }

    include MGC_PLUGIN_PATH . 'admin/views/logs.php';
}

/**
 * Save settings
 */
function mgc_save_settings() {
    $settings = array(
        'enabled',
        'notice_text',
        'accept_button_text',
        'reject_button_text',
        'settings_button_text',
        'privacy_policy_url',
        'privacy_policy_text',
        'cookie_expiry',
        'position',
        'theme',
        'animation',
        'button_color',
        'custom_button_color',
        'custom_button_hover_color',
        'show_reject_button',
        'show_settings_button',
        'preference_display_type',
        'custom_css',
        'enable_analytics',
        'enable_marketing',
        'enable_functional',
        'enable_logging'
    );

    // List of checkbox fields (need special handling since unchecked = no POST data)
    $checkbox_fields = array(
        'enabled',
        'show_reject_button',
        'show_settings_button',
        'enable_analytics',
        'enable_marketing',
        'enable_functional',
        'enable_logging'
    );

    foreach ($settings as $setting) {
        // Special handling for checkboxes
        if (in_array($setting, $checkbox_fields)) {
            // Checkbox: if it's in POST and = '1', it's checked. Otherwise it's unchecked.
            $value = (isset($_POST['mgc_' . $setting]) && $_POST['mgc_' . $setting] == '1') ? true : false;
        } else {
            $value = isset($_POST['mgc_' . $setting]) ? $_POST['mgc_' . $setting] : '';

            // Sanitize based on type
            if ($setting === 'cookie_expiry') {
                $value = absint($value);
                // Enforce minimum and maximum values for GDPR compliance
                if ($value < 1) $value = 1;
                if ($value > 365) $value = 365;
            } elseif ($setting === 'custom_css') {
                $value = wp_strip_all_tags($value);
                // Remove any javascript: or data: URLs to prevent CSS injection attacks
                $value = preg_replace('/url\s*\(\s*[\'"]?\s*(?:javascript|data):/i', 'url(blocked:', $value);
                // Limit length to prevent abuse (10KB should be more than enough for custom CSS)
                $value = substr($value, 0, 10000);
            } elseif (in_array($setting, array('custom_button_color', 'custom_button_hover_color'))) {
                // Sanitize hex color
                $value = sanitize_text_field($value);
                // Validate hex color format
                if (!empty($value) && !preg_match('/^#[a-fA-F0-9]{6}$/', $value)) {
                    $value = ''; // Clear invalid hex colors
                }
            } elseif ($setting === 'preference_display_type') {
                // Validate preference display type
                $value = sanitize_text_field($value);
                if (!in_array($value, array('icon', 'footer', 'neither'))) {
                    $value = 'icon'; // Default to icon if invalid
                }
            } else {
                $value = sanitize_text_field($value);
            }
        }

        update_option('mgc_' . $setting, $value);
    }

    // Clear caches after saving
    mgc_clear_all_caches();

    add_settings_error(
        'mgc_messages',
        'mgc_message',
        __('Settings saved successfully.', 'maple-gdpr-cookies'),
        'updated'
    );
}

/**
 * AJAX handler for saving consent
 */
function mgc_save_consent() {
    check_ajax_referer('mgc_consent_nonce', 'nonce');

    // Rate limiting - max 10 consent saves per hour per IP to prevent abuse
    $ip = mgc_get_ip_address();
    $rate_key = 'mgc_consent_rate_' . md5($ip);
    $attempts = get_transient($rate_key);

    if ($attempts && $attempts >= 10) {
        wp_send_json_error(array(
            'message' => __('Too many requests. Please try again later.', 'maple-gdpr-cookies')
        ), 429);
        return;
    }

    // Increment rate limit counter
    set_transient($rate_key, ($attempts ? $attempts + 1 : 1), HOUR_IN_SECONDS);

    $consent_type = sanitize_text_field($_POST['consent_type']);
    $categories = isset($_POST['categories']) ? array_map('sanitize_text_field', $_POST['categories']) : array();

    // Log consent if enabled
    if (get_option('mgc_enable_logging', true)) {
        mgc_log_consent($consent_type, $categories);
    }

    wp_send_json_success(array(
        'message' => __('Consent saved successfully', 'maple-gdpr-cookies')
    ));
}
add_action('wp_ajax_mgc_save_consent', 'mgc_save_consent');
add_action('wp_ajax_nopriv_mgc_save_consent', 'mgc_save_consent');

/**
 * Log user consent
 */
function mgc_log_consent($consent_type, $categories = array()) {
    global $wpdb;

    $table_name = $wpdb->prefix . 'mgc_consent_logs';

    // Get and anonymize IP address (GDPR compliance)
    $ip_address = mgc_anonymize_ip(mgc_get_ip_address());

    $wpdb->insert(
        $table_name,
        array(
            'user_id' => get_current_user_id(),
            'ip_address' => $ip_address,
            'user_agent' => sanitize_text_field(substr($_SERVER['HTTP_USER_AGENT'], 0, 255)),
            'consent_type' => $consent_type,
            'categories' => json_encode($categories),
            'consent_given' => ($consent_type === 'accept'),
            'consent_date' => current_time('mysql')
        ),
        array('%d', '%s', '%s', '%s', '%s', '%d', '%s')
    );
}

/**
 * Get user IP address
 */
function mgc_get_ip_address() {
    $ip = '';

    // Check if behind a proxy and validate
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        // X-Forwarded-For can contain multiple IPs, get the first one (original client)
        $ip_list = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        $ip = trim($ip_list[0]);
    } elseif (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }

    // Validate it's a real IP address
    if (!filter_var($ip, FILTER_VALIDATE_IP)) {
        // If invalid, fall back to direct connection IP
        $ip = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
    }

    return sanitize_text_field($ip);
}

/**
 * Anonymize IP address (GDPR compliance)
 * Removes last octet for IPv4, last segment for IPv6
 */
function mgc_anonymize_ip($ip) {
    // Validate and anonymize IPv4
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
        return preg_replace('/\.\d+$/', '.0', $ip);
    }

    // Validate and anonymize IPv6
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
        return preg_replace('/:[^:]+$/', ':0', $ip);
    }

    // If invalid IP, return masked version
    return '0.0.0.0';
}

/**
 * Schedule cleanup tasks
 */
function mgc_schedule_cleanup() {
    if (!wp_next_scheduled('mgc_cleanup_logs')) {
        wp_schedule_event(time(), 'daily', 'mgc_cleanup_logs');
    }

    if (!wp_next_scheduled('mgc_optimize_database')) {
        wp_schedule_event(time(), 'weekly', 'mgc_optimize_database');
    }
}
add_action('wp', 'mgc_schedule_cleanup');

/**
 * Cleanup old consent logs
 */
function mgc_cleanup_old_logs() {
    global $wpdb;

    $table_name = $wpdb->prefix . 'mgc_consent_logs';
    $retention_days = apply_filters('mgc_log_retention_days', 365);

    $wpdb->query(
        $wpdb->prepare(
            "DELETE FROM $table_name WHERE consent_date < DATE_SUB(NOW(), INTERVAL %d DAY)",
            $retention_days
        )
    );
}
add_action('mgc_cleanup_logs', 'mgc_cleanup_old_logs');

/**
 * Optimize database tables
 */
function mgc_optimize_database_tables() {
    global $wpdb;

    $table_name = $wpdb->prefix . 'mgc_consent_logs';
    $wpdb->query("OPTIMIZE TABLE $table_name");
}
add_action('mgc_optimize_database', 'mgc_optimize_database_tables');

/**
 * Add settings link on plugins page
 */
function mgc_add_settings_link($links) {
    $settings_link = '<a href="' . admin_url('admin.php?page=maple-gdpr-cookies') . '">' . __('Settings', 'maple-gdpr-cookies') . '</a>';
    array_unshift($links, $settings_link);
    return $links;
}
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'mgc_add_settings_link');

/**
 * Redirect to settings page on activation
 */
function mgc_activation_redirect() {
    if (get_transient('mgc_activation_redirect')) {
        delete_transient('mgc_activation_redirect');

        if (!isset($_GET['activate-multi'])) {
            wp_safe_redirect(admin_url('admin.php?page=maple-gdpr-cookies'));
            exit;
        }
    }
}
add_action('admin_init', 'mgc_activation_redirect');

/**
 * Cookie Preferences Shortcode
 * Usage: [mgc_cookie_preferences] or [mgc_cookie_preferences text="Manage Cookies"]
 */
function mgc_cookie_preferences_shortcode($atts) {
    // Only show if plugin is enabled
    if (!get_option('mgc_enabled', true)) {
        return '';
    }

    // Parse attributes
    $atts = shortcode_atts(array(
        'text' => __('Cookie Preferences', 'maple-gdpr-cookies'),
        'class' => 'mgc-preferences-link'
    ), $atts);

    // Return link with data attribute that JavaScript will handle
    return sprintf(
        '<a href="#" class="%s" data-mgc-preferences-trigger aria-label="%s">%s</a>',
        esc_attr($atts['class']),
        esc_attr($atts['text']),
        esc_html($atts['text'])
    );
}
add_shortcode('mgc_cookie_preferences', 'mgc_cookie_preferences_shortcode');
