<?php
/**
 * Product Card Widget for BoostBot
 *
 * Displays WooCommerce products in chat.
 *
 * @package BoostBot
 * @since 1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Class BoostBot_Product_Card_Widget
 *
 * Product card widget for WooCommerce integration.
 */
class BoostBot_Product_Card_Widget extends BoostBot_Widget_Base {

    /**
     * Widget ID.
     *
     * @var string
     */
    protected $id = 'product_card';

    /**
     * Pro only widget.
     *
     * @var bool
     */
    protected $is_free = false;

    /**
     * Get widget name.
     *
     * @since 1.0.0
     * @return string Widget name.
     */
    public function get_name(): string {
        return __( 'Product Card', 'boostbot' );
    }

    /**
     * Get widget description.
     *
     * @since 1.0.0
     * @return string Widget description.
     */
    public function get_description(): string {
        return __( 'Display WooCommerce products', 'boostbot' );
    }

    /**
     * Get widget icon.
     *
     * @since 1.0.0
     * @return string Icon name.
     */
    public function get_icon(): string {
        return 'shopping-bag';
    }

    /**
     * Get widget schema.
     *
     * @since 1.0.0
     * @return array Widget schema.
     */
    public function get_schema(): array {
        return array(
            'display_mode' => 'card', // card, list, carousel
            'show_price'   => true,
            'show_rating'  => true,
            'show_add_to_cart' => true,
            'show_description' => true,
            'max_products' => 5,
        );
    }

    /**
     * Get widget configuration.
     *
     * @since 1.0.0
     * @param array $data Widget data.
     * @return array Widget configuration.
     */
    public function get_config( array $data = array() ): array {
        $config = parent::get_config( $data );

        // Get language from data or current language
        $language = $data['language'] ?? $data['lang'] ?? '';
        if ( empty( $language ) && class_exists( 'BoostBot_Language' ) ) {
            $language = BoostBot_Language::get_current();
        }

        // Get products
        $products = $this->get_products( $data, $language );
        $config['products'] = $products;

        // WooCommerce specific config — resolve currency for the widget's language
        $wc_currency = $language
            ? BoostBot_Polylang_Context::get_currency_for_language( $language )
            : array(
                'symbol' => function_exists( 'get_woocommerce_currency_symbol' )
                    ? html_entity_decode( get_woocommerce_currency_symbol(), ENT_QUOTES, 'UTF-8' )
                    : '₪',
            );
        $config['woocommerce'] = array(
            'enabled'     => class_exists( 'WooCommerce' ),
            'currency'    => $wc_currency['symbol'],
            'cart_url'    => function_exists( 'wc_get_cart_url' )
                ? wc_get_cart_url()
                : '',
            'ajax_url'    => admin_url( 'admin-ajax.php' ),
        );

        return $config;
    }

    /**
     * Get products based on data.
     *
     * @since 1.0.0
     * @param array  $data     Widget data.
     * @param string $language Language code.
     * @return array Products data.
     */
    private function get_products( array $data, string $language = '' ): array {
        if ( ! class_exists( 'WooCommerce' ) ) {
            return array();
        }

        $products = array();

        // If specific product IDs provided
        if ( ! empty( $data['product_ids'] ) ) {
            $product_ids = is_array( $data['product_ids'] ) 
                ? $data['product_ids'] 
                : array( $data['product_ids'] );

            foreach ( $product_ids as $product_id ) {
                $product = wc_get_product( absint( $product_id ) );
                if ( $product ) {
                    $products[] = $this->format_product( $product );
                }
            }
            return $products;
        }

        // If single product ID
        if ( ! empty( $data['product_id'] ) ) {
            $product = wc_get_product( absint( $data['product_id'] ) );
            if ( $product ) {
                $products[] = $this->format_product( $product );
            }
            return $products;
        }

        $wc_service = new BoostBot_WooCommerce_Service();

        // If category
        if ( ! empty( $data['category'] ) ) {
            return $wc_service->get_products_by_category( $data['category'], $data['limit'] ?? 5, $language );
        }

        // If search query
        if ( ! empty( $data['query'] ) ) {
            return $wc_service->search_products( $data['query'], array(
                'limit' => $data['limit'] ?? 5,
                'lang'  => $language,
            ) );
        }

        // Default: featured products
        return $wc_service->get_featured_products( $data['limit'] ?? 5, $language );
    }

    /**
     * Format product data for frontend.
     *
     * @since 1.0.0
     * @param WC_Product $product Product object.
     * @return array Formatted product data.
     */
    private function format_product( $product ): array {
        $wc_service = new BoostBot_WooCommerce_Service();
        $formatted  = $wc_service->get_product( (int) $product->get_id() );

        if ( ! empty( $formatted ) ) {
            return $formatted;
        }

        return array(
            'id'         => $product->get_id(),
            'name'       => $product->get_name(),
            'price'      => $product->get_price(),
            'image'      => '',
            'url'        => urldecode( $product->get_permalink() ),
            'in_stock'   => $product->is_in_stock(),
            'on_sale'    => $product->is_on_sale(),
            'product_type' => $product->get_type(),
            'categories' => $this->get_product_categories( $product ),
        );
    }

    /**
     * Get product categories.
     *
     * @since 1.0.0
     * @param WC_Product $product Product object.
     * @return array Category names.
     */
    private function get_product_categories( $product ): array {
        $category_ids = $product->get_category_ids();
        $categories = array();

        foreach ( $category_ids as $cat_id ) {
            $term = get_term( $cat_id, 'product_cat' );
            if ( $term && ! is_wp_error( $term ) ) {
                $categories[] = $term->name;
            }
        }

        return $categories;
    }

    /**
     * Get products by category.
     *
     * @since 1.0.0
     * @param string $category Category slug or ID.
     * @param int    $limit    Number of products.
     * @return array Products.
     */
    private function get_products_by_category( string $category, int $limit = 5 ): array {
        $args = array(
            'limit'    => $limit,
            'status'   => 'publish',
            'category' => array( $category ),
        );

        $products = wc_get_products( $args );
        $formatted = array();

        foreach ( $products as $product ) {
            $formatted[] = $this->format_product( $product );
        }

        return $formatted;
    }

    /**
     * Search products.
     *
     * @since 1.0.0
     * @param string $query Search query.
     * @param int    $limit Number of products.
     * @return array Products.
     */
    private function search_products( string $query, int $limit = 5 ): array {
        $args = array(
            'limit'  => $limit,
            'status' => 'publish',
            's'      => sanitize_text_field( $query ),
        );

        $products = wc_get_products( $args );
        $formatted = array();

        foreach ( $products as $product ) {
            $formatted[] = $this->format_product( $product );
        }

        return $formatted;
    }

    /**
     * Get featured products.
     *
     * @since 1.0.0
     * @param int $limit Number of products.
     * @return array Products.
     */
    private function get_featured_products( int $limit = 5 ): array {
        $args = array(
            'limit'    => $limit,
            'status'   => 'publish',
            'featured' => true,
        );

        $products = wc_get_products( $args );

        // If no featured, get recent
        if ( empty( $products ) ) {
            $args = array(
                'limit'   => $limit,
                'status'  => 'publish',
                'orderby' => 'date',
                'order'   => 'DESC',
            );
            $products = wc_get_products( $args );
        }

        $formatted = array();
        foreach ( $products as $product ) {
            $formatted[] = $this->format_product( $product );
        }

        return $formatted;
    }

    /**
     * Validate submitted data.
     *
     * @since 1.0.0
     * @param array $data Submitted data.
     * @return array Validation result.
     */
    public function validate( array $data ): array {
        $errors = array();

        // For add to cart action
        if ( isset( $data['action'] ) && $data['action'] === 'add_to_cart' ) {
            if ( empty( $data['product_id'] ) ) {
                $errors['product_id'] = __( 'Product ID is required', 'boostbot' );
            }

            $product_id = absint( $data['product_id'] );
            $product = wc_get_product( $product_id );
            $quantity = absint( $data['quantity'] ?? 1 );
            $variation_id = absint( $data['variation_id'] ?? 0 );
            $cart_product = $variation_id ? wc_get_product( $variation_id ) : $product;

            if ( ! $product ) {
                $errors['product_id'] = __( 'Product not found', 'boostbot' );
            } elseif ( $quantity < 1 ) {
                $errors['quantity'] = __( 'Quantity must be at least 1', 'boostbot' );
            } elseif ( $product->is_type( 'variable' ) && $variation_id <= 0 ) {
                $errors['variation_id'] = __( 'Please select a product option', 'boostbot' );
            } elseif ( ! $cart_product ) {
                $errors['variation_id'] = __( 'Product option not found', 'boostbot' );
            } elseif ( ! $cart_product->is_purchasable() ) {
                $errors['purchasable'] = __( 'This product cannot be purchased right now', 'boostbot' );
            } elseif ( ! $cart_product->is_in_stock() ) {
                $errors['stock'] = __( 'Product is out of stock', 'boostbot' );
            } else {
                $max_quantity = (int) $cart_product->get_max_purchase_quantity();
                if ( $max_quantity > 0 && $quantity > $max_quantity ) {
                    $errors['quantity'] = sprintf(
                        /* translators: %d: Available quantity */
                        __( 'Only %d units are available right now', 'boostbot' ),
                        $max_quantity
                    );
                }
            }
        }

        return array(
            'valid'  => empty( $errors ),
            'errors' => $errors,
        );
    }

    /**
     * Process submitted data.
     *
     * @since 1.0.0
     * @param array $data    Submitted data.
     * @param array $context Submission context.
     * @return array Processing result.
     */
    public function process( array $data, array $context = array() ): array {
        $action = $data['action'] ?? 'view';

        switch ( $action ) {
            case 'add_to_cart':
                return $this->add_to_cart( $data );

            case 'view':
            default:
                return $this->track_product_view( $data, $context );
        }
    }

    /**
     * Add product to cart.
     *
     * @since 1.0.0
     * @param array $data Cart data.
     * @return array Result.
     */
    private function add_to_cart( array $data ): array {
        if ( ! class_exists( 'WooCommerce' ) ) {
            throw new Exception( esc_html( __( 'WooCommerce is not installed', 'boostbot' ) ) );
        }

        $product_id = absint( $data['product_id'] );
        $quantity = absint( $data['quantity'] ?? 1 );
        $variation_id = absint( $data['variation_id'] ?? 0 );
        $variation = $data['variation'] ?? array();
        $session_cookie_name = 'wp_woocommerce_session_' . COOKIEHASH;
        $cart_count_before   = ( function_exists( 'WC' ) && WC()->cart ) ? count( WC()->cart->get_cart() ) : null;

        BoostBot_Logger::debug(
            '[Cart] add_to_cart called',
            array(
                'product_id'                      => $product_id,
                'quantity'                        => $quantity,
                'variation_id'                    => $variation_id,
                'wc_cart_initialized'             => function_exists( 'WC' ) && null !== WC()->cart,
                'cart_count_before'               => $cart_count_before,
                'has_woocommerce_cart_hash_cookie'=> isset( $_COOKIE['woocommerce_cart_hash'] ),
                'has_wp_session_cookie'           => isset( $_COOKIE[ $session_cookie_name ] ),
            )
        );

        $wc_service = new BoostBot_WooCommerce_Service();
        $language   = sanitize_text_field( $data['language'] ?? $data['lang'] ?? '' );
        $result     = $wc_service->add_to_cart(
            $product_id,
            max( 1, $quantity ),
            $variation_id,
            is_array( $variation ) ? $variation : array(),
            $language
        );

        BoostBot_Logger::debug(
            '[Cart] add_to_cart result',
            array(
                'product_id'                      => $product_id,
                'success'                         => ! empty( $result['success'] ),
                'response_cart_count'             => $result['cart_count'] ?? null,
                'response_has_cart_payload'       => ! empty( $result['cart'] ),
                'cart_count_after'                => ( function_exists( 'WC' ) && WC()->cart ) ? count( WC()->cart->get_cart() ) : null,
                'cart_hash'                       => ( function_exists( 'WC' ) && WC()->cart ) ? WC()->cart->get_cart_hash() : null,
                'has_woocommerce_cart_hash_cookie'=> isset( $_COOKIE['woocommerce_cart_hash'] ),
                'has_wp_session_cookie'           => isset( $_COOKIE[ $session_cookie_name ] ),
            )
        );

        if ( empty( $result['success'] ) ) {
            throw new Exception( esc_html( $result['message'] ?? __( 'Error adding to cart', 'boostbot' ) ) );
        }

        $product = wc_get_product( $product_id );

        BoostBot_Logger::info( 'Product added to cart from widget', array(
            'product_id' => $product_id,
            'quantity'   => $quantity,
        ) );

        // Fire hook
        $this->do_action( 'added_to_cart', $product_id, $quantity );

        return array(
            'success'       => true,
            'message'       => $result['message'] ?? sprintf(
                /* translators: %s: Product name */
                __( '%s added to cart!', 'boostbot' ),
                $product ? $product->get_name() : __( 'Product', 'boostbot' )
            ),
            'cart_url'      => $result['cart_url'] ?? wc_get_cart_url(),
            'checkout_url'  => $result['checkout_url'] ?? wc_get_checkout_url(),
            'cart_count'    => $result['cart_count'] ?? ( WC()->cart ? WC()->cart->get_cart_contents_count() : 0 ),
            'cart_total'    => $result['cart_total'] ?? ( WC()->cart ? WC()->cart->get_cart_total() : '' ),
            'cart'          => $result['cart'] ?? null,
        );
    }

    /**
     * Track product view.
     *
     * @since 1.0.0
     * @param array $data    View data.
     * @param array $context Context.
     * @return array Result.
     */
    private function track_product_view( array $data, array $context ): array {
        $product_id = absint( $data['product_id'] ?? 0 );

        if ( $product_id ) {
            // Track view if conversation exists
            if ( ! empty( $context['conversation_id'] ) ) {
                $conversation_model = new BoostBot_Conversation_Model();
                $conversation = $conversation_model->get_by_conversation_id( $context['conversation_id'] );

                if ( $conversation ) {
                    $products_viewed = json_decode( $conversation->products_viewed ?? '[]', true ) ?: array();
                    if ( ! in_array( $product_id, $products_viewed, true ) ) {
                        $products_viewed[] = $product_id;
                        $conversation_model->update( $conversation->id, array(
                            'products_viewed' => $products_viewed,
                        ) );
                    }
                }
            }

            $this->do_action( 'product_viewed', $product_id, $context );
        }

        return array(
            'tracked' => true,
        );
    }
}
