<?php
/**
 * Bundle Builder Widget for BoostBot.
 *
 * AI-powered widget for building personalized product bundles.
 *
 * @package BoostBot
 * @since   1.0.0
 */

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

/**
 * Class BoostBot_Bundle_Builder_Widget
 *
 * Interactive widget that helps customers build product bundles
 * based on their budget and preferences.
 *
 * Requires Pro+Bundles plan ($40/month).
 */
class BoostBot_Bundle_Builder_Widget extends BoostBot_Widget_Base {

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

    /**
     * Not available in free version.
     *
     * @var bool
     */
    protected $is_free = false;

    /**
     * Requires Pro+Bundles plan.
     *
     * @var bool
     */
    protected $requires_bundles_plan = true;

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

    /**
     * Get widget description.
     *
     * @since 1.0.0
     * @return string Widget description.
     */
    public function get_description(): string {
        return __( 'AI builds personalized product bundles for customers', 'boostbot' );
    }

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

    /**
     * Get widget schema.
     *
     * @since 1.0.0
     * @return array Widget schema.
     */
    public function get_schema(): array {
        return array(
            'name'               => $this->get_name(),
            'description'        => $this->get_description(),
            'requires_woocommerce' => true,
            'requires_plan'      => 'pro_bundles',

            'settings' => array(
                // Budget ranges remain useful as AI conversation guidance.
                'budget_ranges' => array(
                    array( 'label' => __( 'Up to $50', 'boostbot' ), 'min' => 0, 'max' => 50 ),
                    array( 'label' => __( '$50-150', 'boostbot' ), 'min' => 50, 'max' => 150 ),
                    array( 'label' => __( '$150-300', 'boostbot' ), 'min' => 150, 'max' => 300 ),
                    array( 'label' => __( '$300+', 'boostbot' ), 'min' => 300, 'max' => null ),
                ),

                // === PRODUCT SETTINGS ===
                'product_settings' => array(
                    'mode'                    => 'all', // 'all' | 'categories' | 'specific'
                    'allowed_categories'      => array(),
                    'excluded_categories'     => array(),
                    'specific_product_ids'    => array(),
                    'preferred_product_ids'   => array(),
                    'excluded_product_ids'    => array(),
                    'include_on_sale'         => true,
                    'include_variable'        => true,
                    'include_featured_only'   => false,
                    'min_stock'               => 1,
                    'min_rating'              => 0,
                    'min_products_in_bundle'  => 2,
                    'max_products_in_bundle'  => 5,
                    'max_single_product_percent' => 50,
                ),

                // Legacy product settings (for backwards compatibility)
                'categories'         => array(),
                'exclude_categories' => array(),
                'min_products'       => 2,
                'max_products'       => 5,
                'include_on_sale'    => true,
                'include_variable'   => true,

                // === PRICING & DISCOUNTS ===
                'pricing_settings' => array(
                    'discount_type'          => 'percent',
                    'discount_percent'       => 10,
                    'discount_fixed'         => 50,
                    'discount_tiers'         => array(
                        array( 'min_amount' => 0, 'max_amount' => 50, 'discount' => 5 ),
                        array( 'min_amount' => 50, 'max_amount' => 150, 'discount' => 10 ),
                        array( 'min_amount' => 150, 'max_amount' => 300, 'discount' => 15 ),
                        array( 'min_amount' => 300, 'max_amount' => null, 'discount' => 20 ),
                    ),
                    'max_discount_amount'    => null,
                    'min_order_for_discount' => 0,
                    'show_savings'           => true,
                    'show_original_prices'   => true,
                    'round_prices'           => true,
                    'round_to'               => 0,
                ),

                // Legacy discount setting
                'bundle_discount_percent' => 10,
                'show_savings'            => true,

                // === COUPON INTEGRATION ===
                'coupon_settings' => array(
                    'enabled'              => false,
                    'mode'                 => 'none', // 'auto' | 'select' | 'generate' | 'none'
                    'auto_coupon_id'       => null,
                    'auto_select_best'     => false,
                    'available_coupon_ids' => array(),
                    'generate_unique'      => false,
                    'generated_prefix'     => 'BUNDLE-',
                    'generated_discount'   => 10,
                    'generated_expiry_days' => 7,
                    'show_coupon_code'     => true,
                    'show_coupon_value'    => true,
                ),

                // === UI & MESSAGES ===
                'allow_customization' => true,
                'intro_message'       => __( 'Let\'s build you the perfect bundle! 🎁', 'boostbot' ),
                'loading_message'     => __( 'Finding your perfect bundle... ⏳', 'boostbot' ),
                'success_message'     => __( 'Found you a great bundle! 🎉', 'boostbot' ),
                'empty_message'       => __( 'No matching products found. Try something else?', 'boostbot' ),
                'error_message'       => __( 'Something went wrong. Please try again.', 'boostbot' ),
            ),
        );
    }

    /**
     * Check if widget is enabled.
     *
     * Requires:
     * 1. WooCommerce to be active
     * 2. Pro+Bundles plan
     *
     * @since 1.0.0
     * @return bool True if widget is available.
     */
    public function is_enabled(): bool {
        // Check WooCommerce.
        if ( ! class_exists( 'WooCommerce' ) ) {
            return false;
        }

        // Check license.
        if ( ! class_exists( 'BoostBot_License_Manager' ) ) {
            return false;
        }

        $license = new BoostBot_License_Manager();

        // Requires Pro+Bundles plan ($40/month).
        return $license->has_bundles();
    }

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

        // Add availability info.
        $config['is_available'] = $this->is_enabled();

        if ( ! $this->is_enabled() ) {
            $config['unavailable_reason'] = $this->get_unavailable_reason();
        }

        // Get categories for discovery.
        $service              = new BoostBot_Bundle_Builder_Service();
        $config['categories'] = $service->get_categories( $config['schema']['settings']['categories'] ?? array() );

        return $config;
    }

    /**
     * Get reason why widget is unavailable.
     *
     * @since 1.0.0
     * @return string Reason message.
     */
    private function get_unavailable_reason(): string {
        if ( ! class_exists( 'WooCommerce' ) ) {
            return __( 'WooCommerce is required to use this widget', 'boostbot' );
        }

        return __( 'This feature is available in the Pro+Bundles plan ($40/month)', 'boostbot' );
    }

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

        // Budget is required for building bundle.
        if ( isset( $data['action'] ) && 'build' === $data['action'] ) {
            if ( empty( $data['budget'] ) && $data['budget'] !== 0 ) {
                $errors['budget'] = __( 'Please select a budget', 'boostbot' );
            }
        }

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

    /**
     * Process bundle request.
     *
     * @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 {
        // Check if widget is enabled.
        if ( ! $this->is_enabled() ) {
            return array(
                'success'          => false,
                'error'            => $this->get_unavailable_reason(),
            );
        }

        // Get widget settings.
        $widget_id = $context['widget_id'] ?? null;
        $settings  = $this->get_widget_settings( $widget_id );

        // Handle different actions.
        $action = $data['action'] ?? 'build';

        switch ( $action ) {
            case 'get_config':
                return $this->handle_get_config( $settings );

            case 'build':
                return $this->handle_build_bundle( $data, $context, $settings );

            case 'add_to_cart':
                return $this->handle_add_to_cart( $data, $context );

            case 'update_status':
                return $this->handle_update_status( $data );

            default:
                return array(
                    'success' => false,
                    'error'   => __( 'Unknown action', 'boostbot' ),
                );
        }
    }

    /**
     * Handle get config action.
     *
     * Returns full configuration for the frontend including categories,
     * pricing hints, and UI settings.
     *
     * @since 1.0.0
     * @param array $settings Widget settings.
     * @return array Config data.
     */
    private function handle_get_config( array $settings ): array {
        // Get categories for discovery
        $product_settings = $this->get_product_settings( $settings );
        $selector = new BoostBot_Bundle_Product_Selector( $product_settings );
        $categories = $selector->get_available_categories();

        // Get pricing info for display
        $pricing_settings = $settings['pricing_settings'] ?? array();
        $discount_calc = new BoostBot_Bundle_Discount_Calculator( $pricing_settings );

        return array(
            'success'         => true,
            'budget_ranges'   => $settings['budget_ranges'] ?? array(),
            'categories'      => $categories,
            'discount_info'   => array(
                'type'        => $pricing_settings['discount_type'] ?? 'percent',
                'description' => $discount_calc->get_discount_description(),
            ),
            'coupon_enabled'  => ! empty( $settings['coupon_settings']['enabled'] ),
            'settings'        => array(
                'show_savings'        => $settings['show_savings'] ?? $settings['pricing_settings']['show_savings'] ?? true,
                'allow_customization' => $settings['allow_customization'] ?? true,
                'intro_message'       => $settings['intro_message'] ?? '',
                'loading_message'     => $settings['loading_message'] ?? '',
                'success_message'     => $settings['success_message'] ?? '',
            ),
        );
    }

    /**
     * Handle build bundle action.
     *
     * Uses the enhanced services:
     * - BoostBot_Bundle_Product_Selector for product filtering
     * - BoostBot_Bundle_Discount_Calculator for pricing
     * - BoostBot_Bundle_Coupon_Service for coupon integration
     *
     * @since 1.0.0
     * @param array $data     Request data.
     * @param array $context  Context data.
     * @param array $settings Widget settings.
     * @return array Bundle result.
     */
    private function handle_build_bundle( array $data, array $context, array $settings ): array {
        // Build criteria from data.
        $criteria = $this->build_criteria( $data, $settings );

        // Get product settings (merge legacy and new)
        $product_settings = $this->get_product_settings( $settings );

        // Use Product Selector Service
        $selector = new BoostBot_Bundle_Product_Selector( $product_settings );
        $scored_products = $selector->get_candidates( $criteria );

        if ( empty( $scored_products ) ) {
            return array(
                'success' => false,
                'message' => $settings['empty_message'] ?? __( 'No matching products found. Try something else?', 'boostbot' ),
            );
        }

        // Build optimal bundle
        $bundle = $selector->build_bundle( $scored_products, floatval( $criteria['budget'] ) );

        if ( empty( $bundle['products'] ) ) {
            return array(
                'success' => false,
                'message' => $settings['empty_message'] ?? __( 'No matching products found. Try something else?', 'boostbot' ),
            );
        }

        // Calculate discounts
        $pricing_settings = $settings['pricing_settings'] ?? array();
        // Merge legacy discount_percent if pricing_settings not set
        if ( empty( $pricing_settings ) && isset( $settings['bundle_discount_percent'] ) ) {
            $pricing_settings = array(
                'discount_type'    => 'percent',
                'discount_percent' => $settings['bundle_discount_percent'],
            );
        }

        $discount_calc = new BoostBot_Bundle_Discount_Calculator( $pricing_settings );
        $pricing = $discount_calc->calculate( $bundle );

        // Merge pricing into bundle
        $bundle = array_merge( $bundle, array(
            'total_price'     => $pricing['total_price'],
            'original_price'  => $pricing['original_price'],
            'savings'         => $pricing['total_savings'],
            'savings_percent' => $pricing['total_savings_percent'],
            'discount_amount' => $pricing['discount_amount'],
        ) );

        // Get coupon if enabled
        $coupon = null;
        $coupon_settings = $settings['coupon_settings'] ?? array();
        if ( ! empty( $coupon_settings['enabled'] ) ) {
            $coupon_service = new BoostBot_Bundle_Coupon_Service( $coupon_settings );
            $coupon = $coupon_service->get_coupon_for_bundle( $bundle, intval( $context['chatbot_id'] ?? 0 ) );
        }

        // Build add-to-cart URL
        if ( $coupon ) {
            $coupon_service = new BoostBot_Bundle_Coupon_Service( $coupon_settings );
            $add_to_cart_url = $coupon_service->build_cart_url_with_coupon( $bundle, $coupon );
        } else {
            $service = new BoostBot_Bundle_Builder_Service();
            $add_to_cart_url = $service->get_bundle_cart_url( $bundle );
        }

        // Save bundle to database.
        $bundle_model = new BoostBot_Bundle_Model();
        $bundle_id    = $bundle_model->create(
            array(
                'conversation_id'   => $context['conversation_id'] ?? null,
                'chatbot_id'        => $context['chatbot_id'] ?? null,
                'widget_id'         => $context['widget_id'] ?? null,
                'customer_criteria' => $criteria,
                'products'          => $bundle['products'],
                'total_price'       => $bundle['total_price'],
                'original_price'    => $bundle['original_price'],
                'discount_amount'   => $bundle['savings'],
                'discount_percent'  => $bundle['savings_percent'],
                'coupon_id'         => $coupon ? ( $coupon['id'] ?? null ) : null,
                'status'            => 'suggested',
            )
        );

        // Log bundle creation.
        if ( class_exists( 'BoostBot_Logger' ) ) {
            BoostBot_Logger::info(
                'Bundle created with enhanced services',
                array(
                    'bundle_id'       => $bundle_id,
                    'products_count'  => count( $bundle['products'] ),
                    'total_price'     => $bundle['total_price'],
                    'discount'        => $bundle['discount_amount'],
                    'has_coupon'      => ! empty( $coupon ),
                    'conversation_id' => $context['conversation_id'] ?? '',
                )
            );
        }

        return array(
            'success'         => true,
            'bundle_id'       => $bundle_id,
            'products'        => $bundle['products'],
            'total_price'     => $bundle['total_price'],
            'original_price'  => $bundle['original_price'],
            'savings'         => $bundle['savings'],
            'savings_percent' => $bundle['savings_percent'],
            'coupon'          => $coupon,
            'add_to_cart_url' => $add_to_cart_url,
            'message'         => $settings['success_message'] ?? __( 'Here is your recommended bundle! 🎉', 'boostbot' ),
        );
    }

    /**
     * Get merged product settings (legacy + new format)
     *
     * @since 1.2.0
     * @param array $settings Widget settings.
     * @return array Product settings.
     */
    private function get_product_settings( array $settings ): array {
        // Start with new format if available
        $product_settings = $settings['product_settings'] ?? array();

        // Merge legacy settings
        if ( empty( $product_settings ) ) {
            $product_settings = array(
                'allowed_categories'     => $settings['categories'] ?? array(),
                'excluded_categories'    => $settings['exclude_categories'] ?? array(),
                'include_on_sale'        => $settings['include_on_sale'] ?? true,
                'include_variable'       => $settings['include_variable'] ?? true,
                'min_products_in_bundle' => $settings['min_products'] ?? 2,
                'max_products_in_bundle' => $settings['max_products'] ?? 5,
            );
        }

        return $product_settings;
    }

    /**
     * Handle add to cart action.
     *
     * @since 1.0.0
     * @param array $data    Request data.
     * @param array $context Context data.
     * @return array Result.
     */
    private function handle_add_to_cart( array $data, array $context ): array {
        $bundle_id = $data['bundle_id'] ?? null;

        if ( ! $bundle_id ) {
            return array(
                'success' => false,
                'error'   => __( 'Bundle not found', 'boostbot' ),
            );
        }

        // Get bundle from database.
        $bundle_model = new BoostBot_Bundle_Model();
        $bundle       = $bundle_model->get_with_products( $bundle_id );

        if ( ! $bundle ) {
            return array(
                'success' => false,
                'error'   => __( 'Bundle not found', 'boostbot' ),
            );
        }

        // Add products to cart with bundle pricing.
        $service = new BoostBot_Bundle_Builder_Service();
        $result  = $service->add_bundle_to_cart(
            array(
                'products' => $bundle->products,
            ),
            floatval( $bundle->discount_percent ?? 0 ),
            $bundle_id
        );

        if ( $result['success'] ) {
            // Update bundle status.
            $bundle_model->update_status( $bundle_id, 'accepted' );

            // Fire action hook.
            do_action( 'boostbot_bundle_added_to_cart', $bundle_id, $bundle );
        }

        return $result;
    }

    /**
     * Handle update status action.
     *
     * @since 1.0.0
     * @param array $data Request data.
     * @return array Result.
     */
    private function handle_update_status( array $data ): array {
        $bundle_id = $data['bundle_id'] ?? null;
        $status    = $data['status'] ?? null;

        if ( ! $bundle_id || ! $status ) {
            return array(
                'success' => false,
                'error'   => __( 'Missing parameters', 'boostbot' ),
            );
        }

        $bundle_model = new BoostBot_Bundle_Model();
        $success      = $bundle_model->update_status( $bundle_id, $status );

        return array(
            'success' => $success,
            'message' => $success ? __( 'Status updated', 'boostbot' ) : __( 'Error updating status', 'boostbot' ),
        );
    }

    /**
     * Build criteria from request data.
     *
     * Supports both legacy format and new discovery format.
     *
     * @since 1.0.0
     * @param array $data     Request data.
     * @param array $settings Widget settings.
     * @return array Criteria.
     */
    private function build_criteria( array $data, array $settings ): array {
        // Handle budget - can be single value or range object
        $budget = 500;
        if ( isset( $data['budget'] ) ) {
            if ( is_array( $data['budget'] ) ) {
                // Range format: { min: 200, max: 500 }
                $budget = floatval( $data['budget']['max'] ?? $data['budget']['min'] ?? 500 );
            } else {
                $budget = floatval( $data['budget'] );
            }
        }

        // Handle preferences - can be string or array
        $preferences = array();
        if ( isset( $data['preferences'] ) ) {
            if ( is_string( $data['preferences'] ) && ! empty( $data['preferences'] ) ) {
                // Split by comma or space
                $preferences = preg_split( '/[,،\s]+/', $data['preferences'] );
                $preferences = array_map( 'trim', $preferences );
                $preferences = array_filter( $preferences );
            } elseif ( is_array( $data['preferences'] ) ) {
                $preferences = $data['preferences'];
            }
        }

        // Get product settings for limits
        $product_settings = $settings['product_settings'] ?? array();

        return array(
            'budget'       => $budget,
            'budget_min'   => is_array( $data['budget'] ?? null ) ? floatval( $data['budget']['min'] ?? 0 ) : 0,
            'budget_max'   => $budget,
            'category'     => $data['category'] ?? null,
            'occasion'     => $data['occasion'] ?? null,
            'recipient'    => $data['recipient'] ?? null,
            'preferences'  => $preferences,
            'exclude'      => $data['exclude'] ?? array(),
            'min_products' => intval( $product_settings['min_products_in_bundle'] ?? $settings['min_products'] ?? 2 ),
            'max_products' => intval( $product_settings['max_products_in_bundle'] ?? $settings['max_products'] ?? 5 ),
        );
    }

    /**
     * Get widget settings from database.
     *
     * @since 1.0.0
     * @param int|null $widget_id Widget ID.
     * @return array Widget settings.
     */
    private function get_widget_settings( ?int $widget_id ): array {
        $schema   = $this->get_schema();
        $defaults = $schema['settings'] ?? array();

        if ( ! $widget_id ) {
            return $defaults;
        }

        // Get widget from database.
        $widget_model = new BoostBot_Widget_Model();
        $widget       = $widget_model->get( $widget_id );

        if ( ! $widget || empty( $widget->config ) ) {
            return $defaults;
        }

        $config = json_decode( $widget->config, true );

        return wp_parse_args( $config['settings'] ?? array(), $defaults );
    }

    /**
     * Get upgrade URL for Pro+Bundles plan.
     *
     * @since 1.0.0
     * @return string Upgrade URL.
     */
    private function get_upgrade_url(): string {
        $pricing = BoostBot_License_Manager::get_pricing();
        return BoostBot_License_Manager::$paypal_link . '/' . $pricing['pro_bundles'];
    }
}
