<?php
/**
 * Ensure the file is not accessed directly.
 */
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Badge
 *
 * @package   Store Manager
 * @author    ShopManagerX
 * @link      http://domain.tld
 * @license   GPL 2.0+
 * @copyright 2024 ShopManagerX
 */

use CPBW\App\Badge;
use CPBW\App\Utilities\Settings;

/**
 * Apply badge to a product.
 */
if ( ! function_exists( 'cpbw_apply_product_badges' ) ) {
    function cpbw_apply_product_badges($product) {

        // Skip AJAX and admin screens
        if (wp_doing_ajax() || is_admin()) {
            return [];
        }

        $badges = (new Badge)->apply_product_badges($product);

        // Ensure it’s an array
        return is_array($badges) ? $badges : [];
    }
}

/**
 * Sanitize badge HTML safely.
 * Only allow <style> tags and inline styles on div/span for badges.
 */
if ( ! function_exists( 'cpbw_sanitize_badge_html' ) ) {
    function cpbw_sanitize_badge_html($html) {
        return wp_kses_post($html);
    }
}

if( ! function_exists( 'cpbw_allow_style_tags') ) {
    /**
     * Allow <style> tags with attributes in wp_kses.
     *
     * @param array  $tags    Allowed HTML tags.
     * @param string $context Context for allowed tags.
     * @return array Modified allowed tags.
     */
    function cpbw_allow_style_tags( $tags, $context ) {
        if ( 'post' === $context ) {
            $tags['style'] = [
                'type'   => true,
                'media'  => true,
                'scoped' => true,
            ];
        }

        return $tags;
    }
    
    add_filter( 'wp_kses_allowed_html', 'cpbw_allow_style_tags', 10, 2 );
}

/**
 * Elementor: Append product badges to product image widgets.
 * Works in all contexts: shop, archive, single product, related,
 * upsells, cross-sells, and custom Elementor loop/grid widgets on any page.
 */
if ( ! function_exists( 'cpbw_add_badge_on_product_grid_image' ) ) {

    /**
     * Extract the attachment ID from the rendered widget content or widget settings.
     *
     * @param string $widget_name
     * @param object $widget
     * @param string $content
     * @return int Attachment ID or 0 if not found
     */
    function cpbw_get_rendered_image_id( $widget_name, $widget, $content ) {
        if ( $widget_name === 'image' ) {
            $widget_settings = $widget->get_settings_for_display();
            return (int) ( $widget_settings['image']['id'] ?? 0 );
        }

        // WooCommerce widgets stamp every <img> with wp-image-{id} class
        preg_match( '/wp-image-(\d+)/', $content, $matches );
        return isset( $matches[1] ) ? (int) $matches[1] : 0;
    }

    /**
     * Reverse lookup: find the product that owns this image as its featured image.
     * Works in ALL contexts — main loop, related, upsells, cross-sells, Elementor grid.
     * The image ID match is the only guard needed — logos/banners will never match
     * a product's _thumbnail_id so they are naturally excluded.
     *
     * @param int $rendered_image_id
     * @return int|null Product ID or null
     */
    function cpbw_get_product_id_from_image( $rendered_image_id ) {
        $products = get_posts( [
            'post_type'      => 'product',
            'post_status'    => 'publish',
            'posts_per_page' => 1,
            'fields'         => 'ids',      // Only fetch IDs — lightweight
            'no_found_rows'  => true,       // Skip pagination count — faster
            'meta_query'     => [
                [
                    'key'   => '_thumbnail_id',
                    'value' => $rendered_image_id,
                    'type'  => 'NUMERIC',
                ],
            ],
        ] );

        return ! empty( $products ) ? $products[0] : null;
    }

    /**
     * Build the combined badges HTML string.
     *
     * @param array $badges
     * @return string
     */
    function cpbw_build_badges_html( $badges ) {
        $badges_html = '';
        foreach ( $badges as $badge_html ) {
            $badges_html .= cpbw_sanitize_badge_html( $badge_html );
        }
        return $badges_html;
    }

    /**
     * Inject badges into the widget's rendered content.
     *
     * @param string $content        Original widget HTML
     * @param string $badges_html    Badge HTML to inject
     * @param bool   $custom_wrapper Whether to use the custom wrapper div
     * @return string Modified content
     */
    function cpbw_inject_badges_into_content( $content, $badges_html, $custom_wrapper ) {
        if ( $custom_wrapper ) {
            return '<div class="cpbw-product-badge-wrapper">' . $content . $badges_html . '</div>';
        }

        return preg_replace(
            '/(<img[^>]*>)/i',
            '<div style="position:relative;display:inline-block;">$1' . $badges_html . '</div>',
            $content,
            1
        );
    }

    /**
     * Main filter callback.
     * No page context check needed — the image-to-product reverse lookup
     * acts as the guard. If the image doesn't belong to a product, nothing happens.
     *
     * @param string $content Rendered widget HTML
     * @param object $widget  Elementor widget instance
     * @return string
     */
    function cpbw_add_badge_on_product_grid_image( $content, $widget ) {

        $settings = cpbw_get_cached_settings();

        // Respect admin setting — skip if badges disabled for list/archive pages
        if ( $settings['show_badge_on'] !== 'both' && $settings['show_badge_on'] !== 'list' ) {
            return $content;
        }

        // Only process widgets that render product or generic images
        $supported_widgets = [
            'woocommerce-product-images',
            'woocommerce-product-image',
            'woocommerce-product-gallery',
            'woocommerce-product-gallery-vertical',
            'woocommerce-product-gallery-horizontal',
            'image', // Generic image widget — verified below via reverse lookup
        ];

        $widget_name = $widget->get_name();

        if ( ! in_array( $widget_name, $supported_widgets, true ) ) {
            return $content;
        }

        // Determine which attachment ID this widget is actually rendering
        $rendered_image_id = cpbw_get_rendered_image_id( $widget_name, $widget, $content );

        if ( ! $rendered_image_id ) {
            return $content;
        }

        // Reverse lookup — if no product owns this image, it's a logo/banner/etc. — skip
        $product_id = cpbw_get_product_id_from_image( $rendered_image_id );

        if ( ! $product_id ) {
            return $content;
        }

        $product = wc_get_product( $product_id );

        if ( ! $product instanceof WC_Product ) {
            return $content;
        }

        $badges = cpbw_apply_product_badges( $product );

        if ( empty( $badges ) ) {
            return $content;
        }

        $badges_html = cpbw_build_badges_html( $badges );

        return cpbw_inject_badges_into_content( $content, $badges_html, $settings['custom_wrapper'] );
    }

    add_filter( 'elementor/widget/render_content', 'cpbw_add_badge_on_product_grid_image', 10, 2 );
}