<?php
/**
 * Bundle Coupon Service
 * 
 * Handles coupon integration for bundles:
 * - Auto-apply best coupon
 * - Generate unique bundle coupons
 * - Apply coupon on add-to-cart
 *
 * @package BoostBot
 * @since 1.2.0
 */

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

class BoostBot_Bundle_Coupon_Service {

    /**
     * Coupon settings
     *
     * @var array
     */
    private $settings;

    /**
     * Constructor
     *
     * @param array $settings Coupon settings
     */
    public function __construct( array $settings = array() ) {
        $this->settings = wp_parse_args( $settings, $this->get_default_settings() );
    }

    /**
     * Get default coupon settings
     *
     * @return array
     */
    private function get_default_settings(): array {
        return array(
            'enabled'              => false,

            // Mode: auto | select | generate | none
            'mode'                 => 'none',

            // Auto mode
            'auto_coupon_id'       => null,
            'auto_select_best'     => false,

            // Select mode
            'available_coupon_ids' => array(),

            // Generate mode
            'generate_unique'      => false,
            'generated_prefix'     => 'BUNDLE-',
            'generated_discount'   => 10,
            'generated_expiry_days' => 7,

            // Display
            'show_coupon_code'     => true,
            'show_coupon_value'    => true,
            'highlight_savings'    => true,
        );
    }

    /**
     * Get coupon for bundle
     *
     * @param array $bundle Bundle data
     * @param int $chatbot_id Chatbot ID
     * @return array|null Coupon data or null
     */
    public function get_coupon_for_bundle( array $bundle, int $chatbot_id ): ?array {
        if ( ! $this->settings['enabled'] ) {
            return null;
        }

        if ( ! function_exists( 'WC' ) ) {
            return null;
        }

        $language = $this->resolve_coupon_language( $bundle, $chatbot_id );

        switch ( $this->settings['mode'] ) {
            case 'auto':
                return $this->get_auto_coupon( $bundle, $chatbot_id, $language );

            case 'select':
                return $this->get_selectable_coupons( $chatbot_id, $language );

            case 'generate':
                return $this->generate_bundle_coupon( $bundle, $language );

            default:
                return null;
        }
    }

    /**
     * Get auto-applied coupon
     *
     * @param array $bundle Bundle data
     * @param int $chatbot_id Chatbot ID
     * @return array|null
     */
    private function get_auto_coupon( array $bundle, int $chatbot_id, string $language = '' ): ?array {
        // Specific coupon defined?
        if ( ! empty( $this->settings['auto_coupon_id'] ) ) {
            $coupon = new WC_Coupon( intval( $this->settings['auto_coupon_id'] ) );
            if ( $coupon->get_id() && $this->is_valid_for_bundle( $coupon, $bundle ) ) {
                return $this->format_coupon( $coupon, $language );
            }
        }

        // Find best from bot's enabled coupons
        if ( $this->settings['auto_select_best'] ) {
            return $this->find_best_coupon( $bundle, $chatbot_id, $language );
        }

        return null;
    }

    /**
     * Find best matching coupon for bundle
     *
     * @param array $bundle Bundle data
     * @param int $chatbot_id Chatbot ID
     * @return array|null
     */
    private function find_best_coupon( array $bundle, int $chatbot_id, string $language = '' ): ?array {
        // Get bot's enabled coupons
        $chatbot_model = new BoostBot_Bot_Model();
        $bot = $chatbot_model->get( $chatbot_id );

        if ( ! $bot ) {
            return null;
        }

        $enabled_coupons = array();
        if ( isset( $bot->enabled_coupons ) ) {
            $enabled_coupons = is_string( $bot->enabled_coupons ) 
                ? json_decode( $bot->enabled_coupons, true ) 
                : (array) $bot->enabled_coupons;
        }

        if ( empty( $enabled_coupons ) ) {
            return null;
        }

        $best = null;
        $best_value = 0;

        foreach ( $enabled_coupons as $coupon_id ) {
            $coupon = new WC_Coupon( intval( $coupon_id ) );

            if ( ! $coupon->get_id() || ! $this->is_valid_for_bundle( $coupon, $bundle ) ) {
                continue;
            }

            $value = $this->calculate_coupon_value( $coupon, $bundle );

            if ( $value > $best_value ) {
                $best = $coupon;
                $best_value = $value;
            }
        }

        return $best ? $this->format_coupon( $best, $language ) : null;
    }

    /**
     * Get selectable coupons for display
     *
     * @param int $chatbot_id Chatbot ID
     * @return array|null Array of coupons or null
     */
    private function get_selectable_coupons( int $chatbot_id, string $language = '' ): ?array {
        $coupon_ids = $this->settings['available_coupon_ids'];

        // If not specified, use bot's enabled coupons
        if ( empty( $coupon_ids ) ) {
            $chatbot_model = new BoostBot_Bot_Model();
            $bot = $chatbot_model->get( $chatbot_id );

            if ( $bot && isset( $bot->enabled_coupons ) ) {
                $coupon_ids = is_string( $bot->enabled_coupons )
                    ? json_decode( $bot->enabled_coupons, true )
                    : (array) $bot->enabled_coupons;
            }
        }

        if ( empty( $coupon_ids ) ) {
            return null;
        }

        $coupons = array();
        foreach ( $coupon_ids as $coupon_id ) {
            $coupon = new WC_Coupon( intval( $coupon_id ) );
            if ( $coupon->get_id() ) {
                $coupons[] = $this->format_coupon( $coupon, $language );
            }
        }

        return ! empty( $coupons ) ? $coupons : null;
    }

    /**
     * Check if coupon is valid for bundle
     *
     * @param WC_Coupon $coupon
     * @param array $bundle
     * @return bool
     */
    private function is_valid_for_bundle( WC_Coupon $coupon, array $bundle ): bool {
        // Check minimum amount
        $min = $coupon->get_minimum_amount();
        if ( $min > 0 && ( $bundle['total_price'] ?? 0 ) < $min ) {
            return false;
        }

        // Check maximum amount
        $max = $coupon->get_maximum_amount();
        if ( $max > 0 && ( $bundle['total_price'] ?? 0 ) > $max ) {
            return false;
        }

        // Check expiry
        $expiry = $coupon->get_date_expires();
        if ( $expiry && $expiry->getTimestamp() < time() ) {
            return false;
        }

        // Check usage limit
        $limit = $coupon->get_usage_limit();
        if ( $limit > 0 && $coupon->get_usage_count() >= $limit ) {
            return false;
        }

        return true;
    }

    /**
     * Calculate coupon value for bundle
     *
     * @param WC_Coupon $coupon
     * @param array $bundle
     * @return float
     */
    private function calculate_coupon_value( WC_Coupon $coupon, array $bundle ): float {
        $type = $coupon->get_discount_type();
        $amount = floatval( $coupon->get_amount() );
        $bundle_total = floatval( $bundle['total_price'] ?? 0 );

        switch ( $type ) {
            case 'percent':
                return $bundle_total * ( $amount / 100 );

            case 'fixed_cart':
                return min( $amount, $bundle_total );

            case 'fixed_product':
                $product_count = count( $bundle['products'] ?? array() );
                return min( $amount * $product_count, $bundle_total );

            default:
                return $amount;
        }
    }

    /**
     * Generate unique coupon for bundle
     *
     * @param array $bundle Bundle data
     * @return array|null Coupon data or null
     */
    private function generate_bundle_coupon( array $bundle, string $language = '' ): ?array {
        if ( ! $this->settings['generate_unique'] ) {
            return null;
        }

        $prefix = sanitize_text_field( $this->settings['generated_prefix'] );
        $discount = floatval( $this->settings['generated_discount'] );
        $expiry_days = intval( $this->settings['generated_expiry_days'] );

        // Generate unique code
        $code = $prefix . strtoupper( wp_generate_password( 6, false ) );

        try {
            $coupon = new WC_Coupon();
            $coupon->set_code( $code );
            $coupon->set_discount_type( 'percent' );
            $coupon->set_amount( $discount );
            $coupon->set_individual_use( true );
            $coupon->set_usage_limit( 1 );
            $coupon->set_usage_limit_per_user( 1 );

            // Set expiry
            $expiry_date = new DateTime();
            $expiry_date->modify( "+{$expiry_days} days" );
            $coupon->set_date_expires( $expiry_date->getTimestamp() );

            // Add bundle metadata
            $coupon->update_meta_data( '_boostbot_bundle', true );
            $coupon->update_meta_data( '_boostbot_bundle_products', array_column( $bundle['products'] ?? array(), 'id' ) );
            $coupon->update_meta_data( '_boostbot_generated', current_time( 'mysql' ) );

            $coupon->save();

            return $this->format_coupon( $coupon, $language );

        } catch ( Exception $e ) {
            BoostBot_Logger::error( 'Failed to generate bundle coupon', array(
                'error' => $e->getMessage(),
            ) );
            return null;
        }
    }

    /**
     * Format coupon for response
     *
     * @param WC_Coupon $coupon
     * @return array
     */
    private function format_coupon( WC_Coupon $coupon, string $language = '' ): array {
        $type = $coupon->get_discount_type();
        $amount = floatval( $coupon->get_amount() );

        // Format discount text
        switch ( $type ) {
            case 'percent':
                $discount_text = $amount . '%';
                break;
            case 'fixed_cart':
            case 'fixed_product':
                $currency = class_exists( 'BoostBot_Polylang_Context' )
                    ? BoostBot_Polylang_Context::get_currency_for_language( $language ?: BoostBot_Language::get_primary() )
                    : array( 'symbol' => '₪' );
                $symbol = $currency['symbol'] ?? '₪';
                $discount_text = $symbol . number_format( $amount, 0 );
                break;
            default:
                $discount_text = $amount;
        }

        return array(
            'id'              => $coupon->get_id(),
            'code'            => $coupon->get_code(),
            'discount_type'   => $type,
            'discount_amount' => $amount,
            'discount_text'   => $discount_text,
            'description'     => $coupon->get_description(),
            'expires'         => $coupon->get_date_expires()
                ? $coupon->get_date_expires()->format( 'd/m/Y' )
                : null,
            'min_amount'      => floatval( $coupon->get_minimum_amount() ),
            'max_amount'      => floatval( $coupon->get_maximum_amount() ),
        );
    }

    /**
     * Resolve the language that should be used for coupon formatting.
     *
     * @param array $bundle Bundle payload.
     * @param int   $chatbot_id Chatbot ID.
     * @return string
     */
    private function resolve_coupon_language( array $bundle, int $chatbot_id ): string {
        if ( ! empty( $bundle['language'] ) && is_string( $bundle['language'] ) ) {
            return sanitize_text_field( $bundle['language'] );
        }

        if ( $chatbot_id > 0 ) {
            $chatbot_model = new BoostBot_Bot_Model();
            $bot           = $chatbot_model->get( $chatbot_id );
            if ( $bot && ! empty( $bot->language ) ) {
                return sanitize_text_field( $bot->language );
            }
        }

        return BoostBot_Language::get_primary();
    }

    /**
     * Build add-to-cart URL with coupon
     *
     * @param array $bundle Bundle data
     * @param array|null $coupon Coupon data
     * @return string Cart URL
     */
    public function build_cart_url_with_coupon( array $bundle, ?array $coupon = null ): string {
        if ( ! function_exists( 'wc_get_cart_url' ) ) {
            return home_url( '/cart/' );
        }

        $wc_service = class_exists( 'BoostBot_WooCommerce_Service' ) ? new BoostBot_WooCommerce_Service() : null;
        $url        = $wc_service instanceof BoostBot_WooCommerce_Service
            ? $wc_service->get_store_page_url( 'cart', (string) ( $bundle['language'] ?? '' ) )
            : wc_get_cart_url();

        // Build query params
        $params = array();

        // Add products
        $products = $bundle['products'] ?? array();
        foreach ( $products as $product ) {
            $product_id = intval( $product['id'] ?? 0 );
            if ( $product_id > 0 ) {
                $params['add-to-cart'][] = $product_id;
            }
        }

        // Add coupon code
        if ( $coupon && ! empty( $coupon['code'] ) ) {
            $params['coupon_code'] = $coupon['code'];
        }

        // Build URL
        if ( ! empty( $params['add-to-cart'] ) ) {
            // For multiple products, we need a different approach
            // WooCommerce doesn't support adding multiple products in one URL by default
            // We'll add the first product and include bundle data
            $url = add_query_arg( array(
                'add-to-cart'     => $params['add-to-cart'][0],
                'boostbot_bundle' => base64_encode( wp_json_encode( $params['add-to-cart'] ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- encoding product IDs for URL parameter
            ), $url );

            if ( ! empty( $params['coupon_code'] ) ) {
                $url = add_query_arg( 'coupon_code', $params['coupon_code'], $url );
            }
        }

        return $url;
    }

    /**
     * Apply bundle products and coupon to cart (AJAX handler)
     *
     * @param array $product_ids Product IDs to add
     * @param string|null $coupon_code Coupon code to apply
     * @return array Result
     */
    public function apply_to_cart( array $product_ids, ?string $coupon_code = null ): array {
        if ( ! function_exists( 'WC' ) || ! WC()->cart ) {
            return array(
                'success' => false,
                'error'   => 'WooCommerce not available',
            );
        }

        $added = array();
        $failed = array();

        // Add products to cart
        foreach ( $product_ids as $product_id ) {
            $product_id = intval( $product_id );
            $result = WC()->cart->add_to_cart( $product_id );

            if ( $result ) {
                $added[] = $product_id;
            } else {
                $failed[] = $product_id;
            }
        }

        // Apply coupon
        $coupon_applied = false;
        if ( $coupon_code && ! empty( $added ) ) {
            $coupon_applied = WC()->cart->apply_coupon( $coupon_code );
        }

        return array(
            'success'        => ! empty( $added ),
            'added'          => $added,
            'failed'         => $failed,
            'coupon_applied' => $coupon_applied,
            'cart_url'       => wc_get_cart_url(),
            'cart_total'     => WC()->cart->get_cart_total(),
        );
    }
}





