<?php
/**
 * Product Gallery Data Handler
 * Handles data operations for product gallery widgets
 */

// 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

class GGM_Commerce_Product_Gallery_Data_Handler {

    /** @var array Per-request cache for product data by ID */
    private static $product_cache = [];

    /**
     * Get product gallery images
     *
     * @param int      $product_id   Product ID.
     * @param int|null $variation_id Optional variation ID for variation-specific images.
     * @return array Array of image objects.
     */
    public function get_product_images($product_id, $variation_id = null) {
        // If a variation is specified and has images, use those instead
        if ($variation_id && class_exists('GGM_Commerce_Variations')) {
            $variation_images = $this->get_variation_images($variation_id);
            if (!empty($variation_images)) {
                return $variation_images;
            }
        }

        // Fall back to parent product images
        return $this->get_parent_product_images($product_id);
    }

    /**
     * Get parent product images (original method logic)
     *
     * @param int $product_id Product ID.
     * @return array Array of image objects.
     */
    private function get_parent_product_images($product_id) {
        global $wpdb;

        $product = $wpdb->get_row($wpdb->prepare(
            "SELECT image_id, gallery_ids FROM {$wpdb->prefix}ggmc_products WHERE id = %d",
            $product_id
        ));

        if (!$product) {
            return [];
        }

        $images = [];

        // ALWAYS add main image first (if exists)
        if (!empty($product->image_id)) {
            $main_image = $this->get_image_data($product->image_id, 0);
            if ($main_image) {
                $images[] = $main_image;
            }
        }

        // Add gallery images (skip duplicates)
        if (!empty($product->gallery_ids)) {
            $gallery_ids = explode(',', $product->gallery_ids);
            $gallery_ids = array_filter($gallery_ids); // Remove empty values

            foreach ($gallery_ids as $idx => $gallery_id) {
                // Skip if this is the main image (avoid duplicates)
                if ($gallery_id == $product->image_id) {
                    continue;
                }

                $image_data = $this->get_image_data($gallery_id, count($images));
                if ($image_data) {
                    $images[] = $image_data;
                }
            }
        }

        return $images;
    }

    /**
     * Get variation-specific images
     *
     * @param int $variation_id Variation ID.
     * @return array Array of image objects, or empty array if no variation images.
     */
    public function get_variation_images($variation_id) {
        if (!class_exists('GGM_Commerce_Variations')) {
            return [];
        }

        $variations_manager = GGM_Commerce_Variations::instance();
        $variation = $variations_manager->get_variation($variation_id);

        if (!$variation) {
            return [];
        }

        // Check if variation has its own images
        if (empty($variation['image_id']) && empty($variation['gallery_ids'])) {
            return []; // No variation-specific images, caller should use parent images
        }

        $images = [];

        // Add variation main image first
        if (!empty($variation['image_id'])) {
            $main_image = $this->get_image_data($variation['image_id'], 0);
            if ($main_image) {
                $images[] = $main_image;
            }
        }

        // Add variation gallery images
        if (!empty($variation['gallery_ids']) && is_array($variation['gallery_ids'])) {
            foreach ($variation['gallery_ids'] as $gallery_id) {
                // Skip if this is the main image
                if ($gallery_id == $variation['image_id']) {
                    continue;
                }

                $image_data = $this->get_image_data($gallery_id, count($images));
                if ($image_data) {
                    $images[] = $image_data;
                }
            }
        }

        return $images;
    }

    /**
     * Get all variation image sets for a product (for JavaScript preloading)
     *
     * @param int $product_id Product ID.
     * @return array Associative array of variation_id => image arrays.
     */
    public function get_all_variation_image_sets($product_id) {
        if (!class_exists('GGM_Commerce_Variations')) {
            return [];
        }

        $variations_manager = GGM_Commerce_Variations::instance();

        // Check if product has variations
        if (!$variations_manager->product_has_variations($product_id)) {
            return [];
        }

        $variations = $variations_manager->get_variations($product_id);
        $image_sets = [];

        // Add parent product images as the default set (key: 0 or 'parent')
        $image_sets['parent'] = $this->get_parent_product_images($product_id);

        // Add each variation's images
        foreach ($variations as $variation) {
            $variation_images = $this->get_variation_images($variation['id']);

            // Only include if variation has its own images
            if (!empty($variation_images)) {
                $image_sets[$variation['id']] = $variation_images;
            }
        }

        return $image_sets;
    }
    
    /**
     * Get image data for gallery
     */
    private function get_image_data($image_id, $index = 0) {
        $attachment_post = get_post($image_id);
        
        if (!$attachment_post || $attachment_post->post_type !== 'attachment') {
            return null;
        }
        
        $image_meta = wp_get_attachment_metadata($image_id);
        $image_url = wp_get_attachment_url($image_id);
        $mime_type = get_post_mime_type($image_id);
        
        return (object) [
            'id' => $image_id,
            'index' => $index,
            'url' => $image_url,
            'mime_type' => $mime_type,
            'title' => $attachment_post->post_title,
            'alt' => get_post_meta($image_id, '_wp_attachment_image_alt', true),
            'caption' => $attachment_post->post_excerpt,
            'description' => $attachment_post->post_content,
            'thumbnail_url' => wp_get_attachment_image_url($image_id, 'thumbnail'),
            'medium_url' => wp_get_attachment_image_url($image_id, 'medium'),
            'large_url' => wp_get_attachment_image_url($image_id, 'large'),
            'full_url' => wp_get_attachment_image_url($image_id, 'full'),
            'thumbnail_srcset' => wp_get_attachment_image_srcset($image_id, 'thumbnail'),
            'medium_srcset' => wp_get_attachment_image_srcset($image_id, 'medium'),
            'large_srcset' => wp_get_attachment_image_srcset($image_id, 'large'),
            'full_srcset' => wp_get_attachment_image_srcset($image_id, 'full'),
            'meta' => $image_meta,
        ];
    }
    
    /**
     * Get product data by ID
     */
    public function get_product($product_id) {
        if (isset(self::$product_cache[$product_id])) {
            return self::$product_cache[$product_id];
        }

        global $wpdb;

        $product = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}ggmc_products WHERE id = %d",
            $product_id
        ));

        self::$product_cache[$product_id] = $product;
        return $product;
    }
    
    /**
     * Get current product ID from various contexts
     */
    public function get_current_product_id() {
        // First, check for Elementor editor preview product
        $preview_product_id = $this->get_preview_product_id();
        if ($preview_product_id) {
            return $preview_product_id;
        }

        // Use the centralized helper method which supports both ?id= and /slug/ URLs
        $product_id = GGM_Commerce_Helpers::get_current_product_id();
        if ($product_id) {
            return $product_id;
        }

        // Try to get from post meta (for product loop pages)
        $current_post_id = get_the_ID();
        if ($current_post_id) {
            $product_id = get_post_meta($current_post_id, '_ggm_commerce_product_id', true);
            if ($product_id) {
                return intval($product_id);
            }
        }

        return null;
    }

    /**
     * Get preview product ID for Elementor editor context
     *
     * @return int|null Preview product ID or null if not in editor context
     */
    private function get_preview_product_id() {
        $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 for Elementor editor context 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
            // 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;
        }

        // Get preview product ID from post meta
        $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'];
            }
        }

        return !empty($preview_product_id) ? absint($preview_product_id) : null;
    }
    
    /**
     * Check if image should be lazy loaded
     */
    public function should_lazy_load($index, $max_visible_thumbnails, $enable_lazy_loading) {
        return $enable_lazy_loading && $index >= $max_visible_thumbnails;
    }
    
    /**
     * Get placeholder image for lazy loading
     */
    public function get_lazy_placeholder() {
        return 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
    }
    
    /**
     * Get image sizes configuration
     */
    public function get_image_sizes() {
        return [
            'thumbnail' => [150, 150, true],
            'medium' => [300, 300, true],
            'large' => [600, 600, false],
            'full' => [0, 0, false],
        ];
    }
    
    /**
     * Validate image for gallery
     */
    public function validate_image($image_id) {
        $attachment = get_post($image_id);
        
        if (!$attachment || $attachment->post_type !== 'attachment') {
            return false;
        }
        
        $mime_type = get_post_mime_type($image_id);
        $allowed_types = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'];
        
        return in_array($mime_type, $allowed_types);
    }
    
    /**
     * Get gallery navigation settings
     */
    public function get_navigation_config($total_images, $max_visible, $current_offset = 0) {
        $show_navigation = $total_images > $max_visible;
        $max_offset = max(0, $total_images - $max_visible);
        $can_go_prev = $current_offset > 0;
        $can_go_next = $current_offset < $max_offset;
        
        return [
            'show_navigation' => $show_navigation,
            'total_images' => $total_images,
            'max_visible' => $max_visible,
            'current_offset' => $current_offset,
            'max_offset' => $max_offset,
            'can_go_prev' => $can_go_prev,
            'can_go_next' => $can_go_next,
        ];
    }
    
    /**
     * Get lightbox configuration data
     */
    public function get_lightbox_config($product, $images, $settings) {
        $config = [
            'enabled' => $settings['enable_lightbox'] === 'yes',
            'show_info' => $settings['lightbox_product_info'] === 'yes',
            'info_position' => $settings['lightbox_info_position'] ?? 'bottom',
            'images' => [],
        ];
        
        if ($config['enabled']) {
            foreach ($images as $image) {
                $config['images'][] = [
                    'id' => $image->id,
                    'url' => $image->full_url,
                    'title' => $image->title,
                    'alt' => $image->alt,
                    'caption' => $image->caption,
                ];
            }
            
            if ($config['show_info'] && $product) {
                $config['product_info'] = [
                    'title' => $settings['lightbox_show_title'] === 'yes' ? ($product->name ?? '') : '',
                    'price' => $settings['lightbox_show_price'] === 'yes' ? GGM_Commerce_Helpers::format_price($product) : '',
                    'description' => $settings['lightbox_show_description'] === 'yes' ? ($product->short_description ?? '') : '',
                    'stock' => $settings['lightbox_show_stock'] === 'yes' ? $this->get_stock_status($product) : '',
                ];
            }
        }
        
        return $config;
    }
    
    /**
     * Get product stock status
     */
    private function get_stock_status($product) {
        if (!isset($product->stock)) {
            return __('In Stock', 'ggm-commerce');
        }

        if ($product->stock > 0) {
            /* translators: %d: stock quantity */
            return sprintf(__('%d in stock', 'ggm-commerce'), $product->stock);
        } else {
            return __('Out of Stock', 'ggm-commerce');
        }
    }
}