<?php
// If this file is called directly, abort.
if (! defined('ABSPATH')) {
    exit;
}

// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
// phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching
// phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter

abstract class GGM_Commerce_Base_Widget extends \Elementor\Widget_Base
{

    // This property will hold our product data once it's fetched.
    protected $product_data = null;

    /** @var array Per-request cache for product data by ID — shared across all widget instances */
    private static $product_data_cache = [];

    /**
     * The constructor. Its main job is to fetch the product data for the current context.
     */
    public function __construct($data = [], $args = null)
    {
        parent::__construct($data, $args);

        // Completely skip product data initialization on admin pages
        // Preview product loading is handled in get_product_data() method instead
        if (is_admin()) {
            return;
        }

        // Skip if not in proper context
        if (!function_exists('get_the_ID')) {
            return;
        }

        // The ID of the current post being processed in the loop (or the current page).
        $current_post_id = get_the_ID();

        // Ensure we have a valid post ID
        if (empty($current_post_id)) {
            return;
        }

        // Check if we are on a single product page (supports both ?id= and /slug/ URLs)
        $product_id = GGM_Commerce_Helpers::get_current_product_id();

        if (empty($product_id)) {
            // If not on a product details page, check if we're in a loop with linked product
            $product_id = get_post_meta($current_post_id, '_ggm_commerce_product_id', true);
        }

        // If we found a valid product ID, fetch its data from our custom table.
        if (! empty($product_id)) {
            if (isset(self::$product_data_cache[$product_id])) {
                $this->product_data = self::$product_data_cache[$product_id];
            } else {
                global $wpdb;
                $table_name = $wpdb->prefix . 'ggmc_products';
                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $table_name is safely constructed from $wpdb->prefix
                $this->product_data = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table_name WHERE id = %d", $product_id));
                self::$product_data_cache[$product_id] = $this->product_data;
            }
        }
    }

    /**
     * Get product data - loads preview product if in editor context
     * This is called during render, not in constructor, making it safer
     */
    public function get_product_data() {
        // Check for custom product source setting first
        $settings = $this->get_settings_for_display();
        if (isset($settings['product_source']) && $settings['product_source'] === 'custom') {
            $custom_product_id = !empty($settings['product_id']) ? absint($settings['product_id']) : 0;
            if ($custom_product_id > 0) {
                if (isset(self::$product_data_cache[$custom_product_id])) {
                    return self::$product_data_cache[$custom_product_id];
                }
                global $wpdb;
                $table_name = $wpdb->prefix . 'ggmc_products';
                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $table_name is safely constructed from $wpdb->prefix
                $custom_product = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table_name WHERE id = %d", $custom_product_id));
                if ($custom_product) {
                    self::$product_data_cache[$custom_product_id] = $custom_product;
                    return $custom_product;
                }
            }
        }

        // If we already have product data, return it
        if ($this->product_data !== null) {
            return $this->product_data;
        }

        // Check for global product context (set by Quick View AJAX or other contexts)
        if (isset($GLOBALS['ggmc_current_product_id']) && !empty($GLOBALS['ggmc_current_product_id'])) {
            global $wpdb;
            $table_name = $wpdb->prefix . 'ggmc_products';
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $table_name is safely constructed from $wpdb->prefix
            $this->product_data = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table_name WHERE id = %d", absint($GLOBALS['ggmc_current_product_id'])));
            if ($this->product_data) {
                return $this->product_data;
            }
        }

        // Try to load preview product for Elementor editor
        $preview_data = $this->try_load_preview_product();
        if ($preview_data) {
            $this->product_data = $preview_data;
        }

        return $this->product_data;
    }

    /**
     * Try to load preview product for Elementor editor context
     *
     * @return object|null Preview product data or null if not available
     */
    protected function try_load_preview_product()
    {
        $post_id = null;
        $is_editor_context = false;

        // Check for Elementor AJAX widget render requests
        // These include editor_post_id in the POST data
        if (wp_doing_ajax()) {
            // Check if this is an Elementor editor AJAX request
            // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Elementor handles its own nonce verification for editor AJAX
            if (isset($_POST['action']) && $_POST['action'] === 'elementor_ajax') {
                // Get post ID from editor_post_id (sent by Elementor during widget renders)
                // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Elementor handles its own nonce verification
                if (isset($_POST['editor_post_id'])) {
                    $post_id = absint($_POST['editor_post_id']);
                    $is_editor_context = true;
                }
            }

            // If not an Elementor editor AJAX, skip
            if (!$is_editor_context) {
                return null;
            }
        } else {
            // Non-AJAX: Check via URL parameters
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- URL parameter checks for editor context detection, not form processing
            $is_editor_context = isset($_GET['elementor-preview']) ||
                                 (isset($_GET['action']) && $_GET['action'] === 'elementor');

            // Also check Elementor's Plugin API if available
            if (!$is_editor_context && class_exists('\Elementor\Plugin')) {
                try {
                    $elementor = \Elementor\Plugin::$instance;
                    if ($elementor && isset($elementor->preview) && $elementor->preview) {
                        $is_editor_context = $elementor->preview->is_preview_mode();
                    }
                } catch (\Exception $e) {
                    // Silently continue
                }
            }

            if (!$is_editor_context) {
                return null;
            }

            // Get the post being edited from URL parameters
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- URL parameter for editor context, not form processing
            if (isset($_GET['post'])) {
                $post_id = absint($_GET['post']);
            } elseif (isset($_GET['elementor-preview'])) {
                $post_id = absint($_GET['elementor-preview']);
            }

            // If still no post ID, try to get from Elementor's document manager
            if (empty($post_id) && class_exists('\Elementor\Plugin')) {
                try {
                    $elementor = \Elementor\Plugin::$instance;
                    if ($elementor && isset($elementor->documents) && $elementor->documents) {
                        $current_doc = $elementor->documents->get_current();
                        if ($current_doc) {
                            $post_id = $current_doc->get_main_id();
                        }
                    }
                } catch (\Exception $e) {
                    // Silently continue
                }
            }
        }

        if (empty($post_id)) {
            return null;
        }

        // Try to get preview product data directly using post meta
        // Avoid calling Preview Manager methods that might access Elementor API
        try {
            $preview_product_id = get_post_meta($post_id, '_ggm_preview_product_id', true);

            // If not found in our custom meta, check Elementor's page settings meta
            // Elementor stores document settings in _elementor_page_settings
            if (empty($preview_product_id)) {
                $elementor_settings = get_post_meta($post_id, '_elementor_page_settings', true);
                if (is_array($elementor_settings) && !empty($elementor_settings['ggm_preview_product_id'])) {
                    $preview_product_id = $elementor_settings['ggm_preview_product_id'];
                }
            }

            if (empty($preview_product_id)) {
                return null;
            }

            // Fetch product data directly from database
            global $wpdb;
            $table_name = $wpdb->prefix . 'ggmc_products';
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $table_name is safely constructed from $wpdb->prefix
            $preview_product = $wpdb->get_row(
                $wpdb->prepare("SELECT * FROM $table_name WHERE id = %d", absint($preview_product_id))
            );

            if ($preview_product) {
                return $preview_product;
            }
        } catch (\Exception $e) {
            // If anything fails, just return null and let normal flow continue
            return null;
        }

        return null;
    }
    
    /**
     * Override the default data method to provide Professional or Site Settings styling
     *
     * - Professional mode: Applies plugin's professional styling defaults
     * - Site Settings mode: Returns empty defaults, allowing Elementor's Site Settings to take effect
     */
    public function get_default_data() {
        $data = parent::get_default_data();

        // Check if professional defaults are enabled
        if (GGM_Commerce_Helpers::are_default_styles_enabled()) {
            // Professional mode: Load plugin defaults from config
            $defaults = static::get_static_default_styles();

            if (!empty($defaults) && is_array($defaults)) {
                if (!isset($data['settings'])) {
                    $data['settings'] = [];
                }

                // Apply professional defaults
                foreach ($defaults as $key => $value) {
                    $data['settings'][$key] = $value;
                }
            }
        }
        // else: Site Settings mode - return empty $data, let Elementor use Site Settings

        return $data;
    }

    // This sets the custom category for our widgets in the Elementor panel.
    public function get_categories()
    {
        return ['ggmc-widgets'];
    }
    
    /**
     * Get product image HTML - simplified for local attachments
     */
    public function get_product_image_html($image_id, $size = 'medium', $alt = '', $style = '')
    {
        if (empty($image_id)) {
            return '';
        }
        
        // Check if attachment exists
        $attachment_post = get_post($image_id);
        if (!$attachment_post || $attachment_post->post_type !== 'attachment') {
            return '';
        }
        
        $attributes = ['alt' => $alt];
        if (!empty($style)) {
            $attributes['style'] = $style;
        }
        
        $attachment_image = wp_get_attachment_image($image_id, $size, false, $attributes);
        
        // If wp_get_attachment_image fails, create manual img tag
        if (empty($attachment_image)) {
            $url = wp_get_attachment_url($image_id);
            if ($url) {
                $attributes_str = '';
                foreach ($attributes as $key => $value) {
                    $attributes_str .= ' ' . $key . '="' . esc_attr($value) . '"';
                }
                
                // Set size attributes based on size parameter
                $size_attrs = '';
                if ($size === 'thumbnail') {
                    $size_attrs = ' width="60" height="60"';
                } elseif ($size === 'medium') {
                    $size_attrs = ' width="150" height="150"';
                } elseif ($size === 'large') {
                    $size_attrs = ' width="400" height="400"';
                }
                
                return '<img src="' . esc_url($url) . '"' . $attributes_str . $size_attrs . ' />';
            }
            return '';
        }
        
        return $attachment_image;
    }
    
    /**
     * Get professional design system colors and typography
     * Based on modern, sophisticated design principles
     */
    public static function get_design_system() {
        return [
            'colors' => [
                'primary' => '#2563eb',
                'primary_dark' => '#1d4ed8',
                'text_primary' => '#0f172a',
                'text_secondary' => '#475569',
                'text_muted' => '#64748b',
                'background' => '#ffffff',
                'surface' => '#f8fafc',
                'border' => '#e2e8f0',
                'success' => '#059669',
                'warning' => '#d97706',
                'error' => '#dc2626',
            ],
            'typography' => [
                'font_family' => "'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
                'font_weights' => [
                    'light' => '300',
                    'normal' => '400',
                    'medium' => '500',
                    'semibold' => '600',
                    'bold' => '700',
                ],
                'line_heights' => [
                    'tight' => '1.25',
                    'normal' => '1.5',
                    'relaxed' => '1.625',
                ],
                'letter_spacing' => [
                    'tight' => '-0.025em',
                    'normal' => '0',
                    'wide' => '0.025em',
                ],
            ],
            'spacing' => [
                'xs' => '4px',
                'sm' => '8px',
                'md' => '16px',
                'lg' => '24px',
                'xl' => '32px',
                'xxl' => '48px',
            ],
            'shadows' => [
                'subtle' => '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
                'small' => '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
                'medium' => '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
                'large' => '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
            ],
            'borders' => [
                'subtle' => '1px solid #f1f5f9',
                'light' => '1px solid #e2e8f0',
                'normal' => '1px solid #cbd5e1',
            ],
        ];
    }
    
    /**
     * Get default styles for widgets
     * Override this method in child widgets to provide widget-specific defaults
     *
     * @deprecated Use get_static_default_styles() instead
     */
    public function get_default_styles() {
        return static::get_static_default_styles();
    }

    /**
     * Static method to get default styles without instantiating the widget
     * This is safer for AJAX calls and is the preferred method
     *
     * Child widgets can override this OR use the centralized config
     */
    public static function get_static_default_styles() {
        // Check if defaults have been cleared globally
        if (get_option('ggm_commerce_defaults_cleared', false)) {
            return []; // Return empty array so widget starts with no styling
        }

        // Get defaults from centralized config using the helper method
        // This will extract widget name and fetch from config file
        return static::get_defaults_from_config();
    }

    /**
     * Helper method to get defaults from centralized config
     * Child widgets should call this in their get_static_default_styles()
     *
     * @return array Default styles from centralized config
     */
    protected static function get_defaults_from_config() {
        // Use the helper class to get defaults
        if (class_exists('GGM_Commerce_Helpers')) {
            $called_class = get_called_class();
            $class_name = $called_class;
            $widget_name = '';

            // Extract widget name from class name using multiple patterns
            // Pattern 1: GGM_Commerce_Widget_Add_To_Cart -> ggmc-add-to-cart
            if (strpos($class_name, 'GGM_Commerce_Widget_') === 0) {
                $widget_name = substr($class_name, strlen('GGM_Commerce_Widget_'));
                // Remove any trailing suffixes like _Refactored
                $widget_name = preg_replace('/_Refactored$/', '', $widget_name);
                $widget_name = strtolower(str_replace('_', '-', $widget_name));
                $widget_name = 'ggmc-' . $widget_name;
            }
            // Pattern 2: GGM_Commerce_Product_Grid_Widget -> ggmc-product-grid
            elseif (preg_match('/^GGM_Commerce_(.+)_Widget$/', $class_name, $matches)) {
                $widget_name = strtolower(str_replace('_', '-', $matches[1]));
                $widget_name = 'ggmc-' . $widget_name;
            }
            // Pattern 3: Any other GGM_Commerce_XXX pattern
            elseif (strpos($class_name, 'GGM_Commerce_') === 0) {
                $widget_name = substr($class_name, strlen('GGM_Commerce_'));
                $widget_name = preg_replace('/_Refactored$/', '', $widget_name);
                $widget_name = str_replace('_Widget', '', $widget_name);
                $widget_name = strtolower(str_replace('_', '-', $widget_name));
                $widget_name = 'ggmc-' . $widget_name;
            }

            if (!empty($widget_name)) {
                return GGM_Commerce_Helpers::get_plugin_default_styles($widget_name);
            }
        }

        return [];
    }
}

