<?php

namespace Fab\Helper\WooCommerce;

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

/**
 * WooCommerce Product Helper.
 *
 * @package    Fab
 * @subpackage Fab/Helper/WooCommerce
 */
class Product {

    // Load traits.
    use \Fab\Plugin\Helper\Singleton;

    /**
     * Get product data for display.
     *
     * @param int $product_id Product ID.
     * @return array|false Product data or false if product not found or not visible.
     */
    public function get_product_data( $product_id ) {
        $product = wc_get_product( $product_id );

        if ( ! $product || ! $product->is_visible() ) {
            return false;
        }

        // Get price HTML - will be empty if no price.
        $price_html = $this->get_formatted_price_html( $product );

        // Get regular and sale prices based on product type.
        $product_type  = $product->get_type();
        $regular_price = '';
        $sale_price    = '';
        $has_price     = false;

        if ( 'variable' === $product_type ) {
            // For variable products, get price range.
            $min_regular_price = $product->get_variation_regular_price( 'min', true );
            $max_regular_price = $product->get_variation_regular_price( 'max', true );
            $min_sale_price    = $product->get_variation_sale_price( 'min', true );
            $max_sale_price    = $product->get_variation_sale_price( 'max', true );

            // Set regular price to min for consistency.
            $regular_price = $min_regular_price;
            $sale_price    = $min_sale_price;
            $has_price     = ! empty( $regular_price );

            // Get variation data.
            $variations = $this->get_variations_data( $product );
        } elseif ( 'grouped' === $product_type ) {
            // For grouped products, get price range from child products.
            $child_regular_prices = array();
            $child_sale_prices    = array();
            $child_ids            = $product->get_children();

            if ( ! empty( $child_ids ) ) {
                foreach ( $child_ids as $child_id ) {
                    $child_product = wc_get_product( $child_id );
                    if ( $child_product && $child_product->is_purchasable() ) {
                        // Get regular price and sale price from each child product.
                        $child_regular_price = $child_product->get_regular_price();
                        $child_sale_price    = $child_product->get_sale_price();

                        // If regular price is empty, use price as fallback.
                        if ( '' === $child_regular_price ) {
                            $child_regular_price = $child_product->get_price();
                        }

                        if ( '' !== $child_regular_price ) {
                            $child_regular_prices[] = $child_regular_price;
                        }

                        if ( '' !== $child_sale_price ) {
                            $child_sale_prices[] = $child_sale_price;
                        }
                    }
                }
            }

            if ( ! empty( $child_regular_prices ) ) {
                $min_regular_price = min( $child_regular_prices );
                $max_regular_price = max( $child_regular_prices );
                $regular_price     = $min_regular_price;

                // Set sale price if available.
                if ( ! empty( $child_sale_prices ) ) {
                    $min_sale_price = min( $child_sale_prices );
                    $max_sale_price = max( $child_sale_prices );
                    $sale_price     = $min_sale_price;
                } else {
                    $min_sale_price = '';
                    $max_sale_price = '';
                    $sale_price     = '';
                }

                $has_price = true;
            } else {
                $has_price = false;
            }

            $variations = array();
        } else {
            // For simple and other product types.
            $regular_price = $product->get_regular_price();
            $sale_price    = $product->get_sale_price();
            $has_price     = ! empty( $regular_price );
            $variations    = array();
        }

        // Get stock information.
        $stock_status   = $product->get_stock_status();
        $stock_quantity = $product->get_stock_quantity();
        $manage_stock   = $product->get_manage_stock();

        $product_data = array(
            'title'          => $product->get_name(),
            'url'            => $product->get_permalink(),
            'thumbnail'      => get_the_post_thumbnail_url( $product_id, 'thumbnail' ),
            'excerpt'        => $product->get_short_description(),
            'categories'     => get_the_terms( $product_id, 'product_cat' ),
            'tags'           => get_the_terms( $product_id, 'product_tag' ),
            'product_type'   => $product_type,
            'regular_price'  => $regular_price,
            'sale_price'     => $sale_price,
            'is_on_sale'     => $has_price ? $product->is_on_sale() : false,
            'has_price'      => $has_price,
            'price_html'     => $price_html,
            'variations'     => isset( $variations ) ? $variations : array(),
            'stock_status'   => $stock_status,
            'stock_quantity' => $stock_quantity,
            'manage_stock'   => $manage_stock,
        );

        // Add price range data for variable and grouped products.
        if ( 'variable' === $product_type || 'grouped' === $product_type ) {
            $product_data['min_regular_price'] = isset( $min_regular_price ) ? $min_regular_price : '';
            $product_data['max_regular_price'] = isset( $max_regular_price ) ? $max_regular_price : '';
            $product_data['min_sale_price']    = isset( $min_sale_price ) ? $min_sale_price : '';
            $product_data['max_sale_price']    = isset( $max_sale_price ) ? $max_sale_price : '';
            $product_data['price_range_html']  = $product->get_price_html();

            // Add information about whether the product has a sale price.
            $product_data['has_sale_price'] = ! empty( $min_sale_price ) && $min_sale_price !== $min_regular_price;

            if ( 'grouped' === $product_type && ! empty( $child_ids ) ) {
                $product_data['child_products'] = count( $child_ids );

                // Add information about child products that have sale prices.
                if ( isset( $child_sale_prices ) && ! empty( $child_sale_prices ) ) {
                    $product_data['child_sale_products'] = count( $child_sale_prices );
                }
            }
        }

        return $product_data;
    }

    /**
     * Get formatted price HTML.
     *
     * @param \WC_Product $product WooCommerce product object.
     * @return string Formatted price HTML or empty string if no price.
     */
    public function get_formatted_price_html( $product ) {
        // For variable and grouped products, use WooCommerce's built-in price HTML.
        if ( $product->is_type( 'variable' ) || $product->is_type( 'grouped' ) ) {
            $price_html = $product->get_price_html();
            if ( empty( $price_html ) ) {
                return '';
            }

            // Ensure price HTML is properly displayed for variable and grouped products.
            return '<div class="text-right"><span class="text-sm font-bold">' . $price_html . '</span></div>';
        }

        // For simple and other product types.
        $regular_price = $product->get_regular_price();
        if ( '' === $regular_price || empty( $regular_price ) ) {
            return '';
        }

        $is_on_sale = $product->is_on_sale();

        if ( $is_on_sale ) {
            $sale_price = $product->get_sale_price();
            if ( '' === $sale_price || empty( $sale_price ) ) {
                return '<div class="text-right"><span class="text-sm font-bold">' . wc_price( $regular_price ) . '</span></div>';
            }

            return '<div class="text-right">' .
                    '<span class="text-xs text-gray-500 line-through block">' . wc_price( $regular_price ) . '</span>' .
                    '<span class="text-sm font-bold block">' . wc_price( $sale_price ) . '</span>' .
                    '</div>';
        }

        return '<div class="text-right"><span class="text-sm font-bold">' . wc_price( $regular_price ) . '</span></div>';
    }

    /**
     * Get variations data for a variable product.
     *
     * @param \WC_Product_Variable $product Variable product object.
     * @return array Array of variation data.
     */
    public function get_variations_data( $product ) {
        if ( ! $product || ! $product->is_type( 'variable' ) ) {
            return array();
        }

        $variations           = array();
        $available_variations = $product->get_available_variations();

        foreach ( $available_variations as $variation_data ) {
            $variation_id = $variation_data['variation_id'];
            $variation    = wc_get_product( $variation_id );

            if ( ! $variation ) {
                continue;
            }

            // Get attributes.
            $attributes = array();
            foreach ( $variation_data['attributes'] as $attribute_name => $attribute_value ) {
                $taxonomy  = str_replace( 'attribute_', '', $attribute_name );
                $term_name = $attribute_value;

                // If this is a taxonomy attribute, get the term name.
                if ( taxonomy_exists( $taxonomy ) ) {
                    $term = get_term_by( 'slug', $attribute_value, $taxonomy );
                    if ( $term && ! is_wp_error( $term ) ) {
                        $term_name = $term->name;
                    }
                }

                $attributes[] = array(
                    'name'  => wc_attribute_label( $taxonomy, $product ),
                    'value' => $term_name,
                );
            }

            // Get price data.
            $regular_price = $variation->get_regular_price();
            $sale_price    = $variation->get_sale_price();
            $has_price     = ! empty( $regular_price );

            // Ensure price is properly formatted.
            $formatted_regular_price = wc_price( $regular_price );
            $formatted_sale_price    = ! empty( $sale_price ) ? wc_price( $sale_price ) : '';

            // Get stock information for variation.
            $variation_stock_status   = $variation->get_stock_status();
            $variation_stock_quantity = $variation->get_stock_quantity();
            $variation_manage_stock   = $variation->get_manage_stock();

            $variations[] = array(
                'variation_id'            => $variation_id,
                'attributes'              => $attributes,
                'is_in_stock'             => $variation->is_in_stock(),
                'regular_price'           => $regular_price,
                'sale_price'              => $sale_price,
                'is_on_sale'              => $has_price ? $variation->is_on_sale() : false,
                'has_price'               => $has_price,
                'price_html'              => $this->get_formatted_price_html( $variation ),
                'formatted_regular_price' => isset( $formatted_regular_price ) ? $formatted_regular_price : '',
                'formatted_sale_price'    => isset( $formatted_sale_price ) ? $formatted_sale_price : '',
                'image'                   => isset( $variation_data['image'] ) ? $variation_data['image'] : array(),
                'stock_status'            => $variation_stock_status,
                'stock_quantity'          => $variation_stock_quantity,
                'manage_stock'            => $variation_manage_stock,
            );
        }

        return $variations;
    }
}
