<?php
/**
 * Metaboxes
 *
 * @package Spin_Wheel
 */

// Exit if accessed directly
if (!defined('ABSPATH')) {
    exit;
}

/**
 * SWP_Metaboxes Class
 */
class SWP_Metaboxes {
    
    /**
     * Instance
     *
     * @var SWP_Metaboxes
     */
    private static $instance = null;
    
    /**
     * Get instance
     *
     * @return SWP_Metaboxes
     */
    public static function instance() {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Constructor
     */
    private function __construct() {
        add_action('add_meta_boxes', [$this, 'add_metaboxes']);
        add_action('save_post_swp_wheel', [$this, 'save_metaboxes'], 10, 2);
    }
    
    /**
     * Add metaboxes
     */
    public function add_metaboxes() {
        // Remove default editor
        remove_post_type_support('swp_wheel', 'editor');
        
        // Add single modern editor metabox
        add_meta_box(
            'swp_modern_editor',
            __('Wheel Configuration', 'spin-wheel'),
            [$this, 'render_modern_editor'],
            'swp_wheel',
            'normal',
            'high'
        );
        
        // Add shortcode metabox in sidebar
        add_meta_box(
            'swp_wheel_shortcode',
            __('Usage', 'spin-wheel'),
            [$this, 'render_shortcode_metabox'],
            'swp_wheel',
            'side',
            'high'
        );
    }
    
    /**
     * Render modern editor
     *
     * @param WP_Post $post Post object
     */
    public function render_modern_editor($post) {
        include SPIN_WHEEL_PATH . 'admin/templates/admin-wheel-editor.php';
    }
    
    /**
     * Render shortcode metabox
     *
     * @param WP_Post $post Post object
     */
    public function render_shortcode_metabox($post) {
        include SPIN_WHEEL_PATH . 'admin/templates/metabox-shortcode.php';
    }
    
    /**
     * Save metaboxes
     *
     * @param int $post_id Post ID
     * @param WP_Post $post Post object
     */
    public function save_metaboxes($post_id, $post) {
        // Check nonce
        if (!isset($_POST['swp_metabox_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['swp_metabox_nonce'])), 'swp_save_metabox')) {
            return;
        }
        
        // Check autosave
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
            return;
        }
        
        // Check permissions
        if (!current_user_can('edit_post', $post_id)) {
            return;
        }
        
        // Save wheel type
        if (isset($_POST['swp_wheel_type'])) {
            update_post_meta($post_id, '_swp_wheel_type', sanitize_text_field(wp_unslash($_POST['swp_wheel_type'])));
        }
        
        // Save wheel mode
        if (isset($_POST['swp_wheel_mode'])) {
            update_post_meta($post_id, '_swp_wheel_mode', sanitize_text_field(wp_unslash($_POST['swp_wheel_mode'])));
        }
        
        // Save settings
        if (isset($_POST['swp_settings']) && is_array($_POST['swp_settings'])) {
            // Recursively sanitize every value (string leaves via sanitize_text_field,
            // numeric/bool preserved) so nested arrays cannot bypass sanitization.
            $settings = swp_sanitize_recursive(wp_unslash($_POST['swp_settings'])); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- swp_sanitize_recursive() sanitizes every leaf

            // Handle device targeting checkboxes (set to 0 if not checked)
            $settings['device_desktop'] = isset($settings['device_desktop']) ? 1 : 0;
            $settings['device_tablet'] = isset($settings['device_tablet']) ? 1 : 0;
            $settings['device_mobile'] = isset($settings['device_mobile']) ? 1 : 0;
            
            // Handle other checkboxes
            $settings['one_entry_per_user'] = isset($settings['one_entry_per_user']) ? 1 : 0;
            $settings['enable_winner_notifications'] = isset($settings['enable_winner_notifications']) ? 1 : 0;
            $settings['enable_confetti'] = isset($settings['enable_confetti']) ? 1 : 0;
            $settings['enable_auto_rotation'] = isset($settings['enable_auto_rotation']) ? 1 : 0;
            
            // Handle advanced conditions (preserve array structure)
            if (isset($settings['advanced_conditions']) && is_array($settings['advanced_conditions'])) {
                $advanced_conditions = [];
                foreach ($settings['advanced_conditions'] as $condition) {
                    if (!empty($condition['type']) && !empty($condition['operator']) && !empty($condition['value'])) {
                        $advanced_conditions[] = [
                            'type'     => sanitize_text_field($condition['type']),
                            'operator' => sanitize_text_field($condition['operator']),
                            'value'    => sanitize_text_field($condition['value']),
                        ];
                    }
                }
                $settings['advanced_conditions'] = $advanced_conditions;
            } else {
                $settings['advanced_conditions'] = [];
            }
            
            // Handle multi-select arrays
            if (isset($settings['user_status']) && is_array($settings['user_status'])) {
                $settings['user_status'] = array_map('sanitize_text_field', $settings['user_status']);
            }
            if (isset($settings['user_roles']) && is_array($settings['user_roles'])) {
                $settings['user_roles'] = array_map('sanitize_text_field', $settings['user_roles']);
            }
            if (isset($settings['page_targeting']) && is_array($settings['page_targeting'])) {
                $settings['page_targeting'] = array_map('intval', $settings['page_targeting']);
            }
            
            // Sanitize remaining text fields
            foreach ($settings as $key => $value) {
                if (!is_array($value)) {
                    $settings[$key] = sanitize_text_field($value);
                }
            }
            
            update_post_meta($post_id, '_swp_settings', $settings);
        }
        
        // Save prizes
        if (isset($_POST['swp_prizes'])) {
            $prizes = [];
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- each prize field is sanitized individually in the loop below
            $raw_prizes = isset($_POST['swp_prizes']) && is_array($_POST['swp_prizes']) ? wp_unslash($_POST['swp_prizes']) : array();
            foreach ($raw_prizes as $prize) {
                if (!is_array($prize)) { continue; }
                $prizes[] = [
                    'label'       => isset($prize['label']) ? sanitize_text_field($prize['label']) : '',
                    'code'        => isset($prize['code']) ? sanitize_text_field($prize['code']) : '',
                    'image'       => !empty($prize['image']) ? esc_url_raw($prize['image']) : '',
                    'probability' => isset($prize['probability']) ? floatval($prize['probability']) : 0,
                    'is_winning'  => isset($prize['is_winning']) ? 1 : 0,
                    'color'       => isset($prize['color']) ? sanitize_hex_color($prize['color']) : '',
                ];
            }
            update_post_meta($post_id, '_swp_prizes', $prizes);
        }
        
        // Save styles
        if (isset($_POST['swp_styles']) && is_array($_POST['swp_styles'])) {
            $raw_styles = wp_unslash($_POST['swp_styles']); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- each element sanitized in the loop below
            $styles     = [];

            foreach ($raw_styles as $key => $value) {
                $key = sanitize_text_field($key);

                if ($key === 'blocks_config' || $key === 'buttons_config') {
                    // JSON string: validate, sanitize the decoded structure, re-encode.
                    $decoded = is_string($value) ? json_decode($value, true) : null;
                    if (is_array($decoded) && json_last_error() === JSON_ERROR_NONE) {
                        $styles[$key] = wp_json_encode(swp_sanitize_recursive($decoded));
                    } else {
                        $styles[$key] = ''; // Missing or invalid JSON.
                    }
                } elseif (is_array($value)) {
                    $styles[$key] = swp_sanitize_recursive($value);
                } else {
                    $styles[$key] = sanitize_text_field($value);
                }
            }

            update_post_meta($post_id, '_swp_styles', $styles);
        }
        
        // Save form settings
        if (isset($_POST['swp_form_settings'])) {
            // Get global settings for default
            $global_settings = get_option('swp_settings', []);
            
            $button_text = isset($_POST['swp_form_settings']['button_text']) ? sanitize_text_field( wp_unslash( $_POST['swp_form_settings']['button_text'] ) ) : '';
            // Apply global default if button_text is empty
            if (empty($button_text)) {
                $button_text = $global_settings['default_submit_button_text'] ?? 'Spin Now!';
            }
            
            $form_settings = [
                'title'         => isset($_POST['swp_form_settings']['title']) ? sanitize_text_field( wp_unslash( $_POST['swp_form_settings']['title'] ) ) : '',
                'description'   => isset($_POST['swp_form_settings']['description']) ? wp_kses_post( wp_unslash( $_POST['swp_form_settings']['description'] ) ) : '',
                'name_label'    => isset($_POST['swp_form_settings']['name_label']) ? sanitize_text_field( wp_unslash( $_POST['swp_form_settings']['name_label'] ) ) : '',
                'email_label'   => isset($_POST['swp_form_settings']['email_label']) ? sanitize_text_field( wp_unslash( $_POST['swp_form_settings']['email_label'] ) ) : '',
                'phone_label'   => isset($_POST['swp_form_settings']['phone_label']) ? sanitize_text_field( wp_unslash( $_POST['swp_form_settings']['phone_label'] ) ) : '',
                'show_name'     => isset($_POST['swp_form_settings']['show_name']) ? 1 : 0,
                'show_email'    => isset($_POST['swp_form_settings']['show_email']) ? 1 : 0,
                'show_phone'    => isset($_POST['swp_form_settings']['show_phone']) ? 1 : 0,
                'require_name'  => (isset($_POST['swp_form_settings']['show_name']) && isset($_POST['swp_form_settings']['require_name'])) ? 1 : 0,
                'require_email' => (isset($_POST['swp_form_settings']['show_email']) && isset($_POST['swp_form_settings']['require_email'])) ? 1 : 0,
                'require_phone' => (isset($_POST['swp_form_settings']['show_phone']) && isset($_POST['swp_form_settings']['require_phone'])) ? 1 : 0,
                'button_text'   => $button_text,
                'show_submit_button' => isset($_POST['swp_form_settings']['show_submit_button']) ? 1 : 0,
                'enable_otp'    => isset($_POST['swp_form_settings']['enable_otp']) ? 1 : 0,
                'otp_method'    => isset($_POST['swp_form_settings']['otp_method']) ? sanitize_text_field( wp_unslash( $_POST['swp_form_settings']['otp_method'] ) ) : 'email',
                'otp_expiry'    => isset($_POST['swp_form_settings']['otp_expiry']) ? intval($_POST['swp_form_settings']['otp_expiry']) : 5,
                'show_participant_info' => isset($_POST['swp_form_settings']['show_participant_info']) ? 1 : 0,
                'enable_terms_checkbox' => isset($_POST['swp_form_settings']['enable_terms_checkbox']) ? 1 : 0,
                'terms_label'   => isset($_POST['swp_form_settings']['terms_label']) ? wp_kses_post( wp_unslash( $_POST['swp_form_settings']['terms_label'] ) ) : '',
            ];

            // UTM capture and phone collection are Pro controls; they only appear in
            // the POST when the Pro add-on rendered them. Runtime license gating still
            // applies at spin time.
            $form_settings['enable_utm_capture'] = !empty($_POST['swp_form_settings']['enable_utm_capture']) ? 1 : 0;

            $show_phone_effective = !empty($form_settings['show_phone']);
            if (empty($form_settings['show_name']) && empty($form_settings['show_email']) && !$show_phone_effective) {
                $form_settings['show_email'] = 1;
            }
            
            $otp_method = $form_settings['otp_method'];
            if (!empty($form_settings['enable_otp'])) {
                if (empty($form_settings['show_email']) && in_array($otp_method, ['email', 'both'], true)) {
                    $form_settings['enable_otp'] = 0;
                }
                if (!$show_phone_effective && in_array($otp_method, ['sms', 'both'], true)) {
                    $form_settings['enable_otp'] = 0;
                }
            }
            
            update_post_meta($post_id, '_swp_form_settings', $form_settings);
        }
        
        // Site-wide auto-embed: one published wheel ID in SWP_OPTION_AUTO_EMBED_WHEEL_ID.
        if (!wp_is_post_revision($post_id)) {
            if (isset($_POST['swp_usage_mode'])) {
                $mode = sanitize_text_field(wp_unslash($_POST['swp_usage_mode']));
                if ($mode === 'auto_embed') {
                    if ($post->post_status === 'publish') {
                        update_option(SWP_OPTION_AUTO_EMBED_WHEEL_ID, (int) $post_id);
                    }
                } else {
                    if ((int) get_option(SWP_OPTION_AUTO_EMBED_WHEEL_ID, 0) === (int) $post_id) {
                        delete_option(SWP_OPTION_AUTO_EMBED_WHEEL_ID);
                    }
                }
            }
            if ($post->post_status !== 'publish' && (int) get_option(SWP_OPTION_AUTO_EMBED_WHEEL_ID, 0) === (int) $post_id) {
                delete_option(SWP_OPTION_AUTO_EMBED_WHEEL_ID);
            }
        }
    }
}
