<?php

declare(strict_types=1);

namespace Instinctor\Services;

use Instinctor\Core\Config;
use Instinctor\Core\DB;

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


/**
 * Upsell Service - handles checkout upsell offers
 * @since 1.9.83
 */
class UpsellService
{
    private static ?self $instance = null;
    
    public static function instance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public function __construct()
    {
        // Register AJAX handlers
        $this->registerAjax('instinctor_accept_upsell', [$this, 'ajaxAcceptUpsell']);
        add_action('wp_ajax_nopriv_instinctor_accept_upsell', [$this, 'ajaxAcceptUpsell']);
        $this->registerAjax('instinctor_track_upsell', [$this, 'ajaxTrackUpsell']);
        add_action('wp_ajax_nopriv_instinctor_track_upsell', [$this, 'ajaxTrackUpsell']);
    }
    
    /**
     * Check if addon is active
     */
    public function isActive(): bool
    {
        return \instinctor_has_pro();
    }
    
    /**
     * Get settings
     */
    public function getSettings(): array
    {
        return Config::get('instinctor_checkout_upsell_settings', [
            'enabled' => true,
            'display_position' => 'before_payment',
            'max_offers' => 2,
            'show_discount' => true,
        ]);
    }
    
    /**
     * Get all offers
     */
    public function getOffers(): array
    {
        return Config::get('instinctor_checkout_upsells', []);
    }
    
    /**
     * Get applicable offers for current cart
     */
    public function getApplicableOffers(array $cart): array
    {
        if (!$this->isActive()) {
            return [];
        }
        
        $settings = $this->getSettings();
        if (empty($settings['enabled'])) {
            return [];
        }
        
        $offers = $this->getOffers();
        $applicable = [];
        
        $cartTotal = $cart['totals']['subtotal'] ?? 0;
        $cartProductIds = array_map(fn($item) => $item['product_id'], $cart['items'] ?? []);
        
        foreach ($offers as $offer) {
            if (empty($offer['enabled'])) {
                continue;
            }
            
            // Skip if product already in cart
            if (in_array($offer['product_id'], $cartProductIds)) {
                continue;
            }
            
            // Check conditions
            $conditions = $offer['conditions'] ?? [];
            
            // Min cart total
            if (!empty($conditions['min_cart_total']) && $cartTotal < $conditions['min_cart_total']) {
                continue;
            }
            
            // Max cart total
            if (!empty($conditions['max_cart_total']) && $cartTotal > $conditions['max_cart_total']) {
                continue;
            }
            
            // Cart must contain specific products
            if (!empty($conditions['cart_contains'])) {
                $hasRequired = false;
                foreach ($conditions['cart_contains'] as $reqId) {
                    if (in_array($reqId, $cartProductIds)) {
                        $hasRequired = true;
                        break;
                    }
                }
                if (!$hasRequired) {
                    continue;
                }
            }
            
            // Cart must not contain specific products
            if (!empty($conditions['cart_excludes'])) {
                $hasExcluded = false;
                foreach ($conditions['cart_excludes'] as $exclId) {
                    if (in_array($exclId, $cartProductIds)) {
                        $hasExcluded = true;
                        break;
                    }
                }
                if ($hasExcluded) {
                    continue;
                }
            }
            
            // Get product details
            $product = $this->getProduct($offer['product_id']);
            if (!$product) {
                continue;
            }
            
            // Calculate discounted price
            $originalPrice = floatval($product->price);
            $discountedPrice = $this->calculateDiscountedPrice(
                $originalPrice,
                $offer['discount_type'] ?? 'percent',
                floatval($offer['discount_value'] ?? 0)
            );
            
            $applicable[] = [
                'id' => $offer['id'],
                'product_id' => $offer['product_id'],
                'product_name' => $product->name,
                'product_image' => $this->getProductImage($product),
                'original_price' => $originalPrice,
                'discounted_price' => $discountedPrice,
                'discount_percent' => $originalPrice > 0 ? round((1 - $discountedPrice / $originalPrice) * 100) : 0,
                'headline' => $offer['headline'] ?? '',
                'description' => $offer['description'] ?? '',
                'button_text' => $offer['button_text'] ?? 'Add to Order',
                'priority' => $offer['priority'] ?? 10,
            ];
        }
        
        // Sort by priority
        usort($applicable, fn($a, $b) => $a['priority'] - $b['priority']);
        
        // Limit to max offers
        $maxOffers = intval($settings['max_offers'] ?? 2);
        return array_slice($applicable, 0, $maxOffers);
    }
    
    /**
     * Calculate discounted price
     */
    private function calculateDiscountedPrice(float $price, string $type, float $value): float
    {
        if ($type === 'percent') {
            return $price * (1 - $value / 100);
        } elseif ($type === 'fixed') {
            return max(0, $price - $value);
        }
        return $price;
    }
    
    /**
     * Get product by ID
     */
    private function getProduct(int $productId): ?object
    {
        $p = DB::prefix();
        return DB::get_row(DB::prepare(
            "SELECT * FROM {$p}instinctor_products WHERE id = %d",
            $productId
        ));
    }
    
    /**
     * Get product image URL
     */
    private function getProductImage(object $product): string
    {
        if (!empty($product->images)) {
            $images = json_decode($product->images, true);
            if (!empty($images[0])) {
                return $images[0];
            }
        }
        return '';
    }
    
    /**
     * AJAX: Accept upsell offer
     */
    public function ajaxAcceptUpsell(): void
    {
        check_ajax_referer('instinctor_frontend', 'nonce');
        // phpcs:disable WordPress.Security.NonceVerification -- request authenticated via the plugin's check_ajax_referer()/verify() HMAC nonce (standalone auth lifecycle; WPCS does not recognise Session::check as a nonce function); all inputs are sanitize_*'d + wp_unslash'd.
        $offerId = isset($_POST['offer_id']) ? sanitize_text_field(wp_unslash($_POST['offer_id'])) : '';
        // phpcs:enable WordPress.Security.NonceVerification
        // phpcs:disable WordPress.Security.NonceVerification -- request authenticated via the plugin's check_ajax_referer()/verify() HMAC nonce (standalone auth lifecycle; WPCS does not recognise Session::check as a nonce function); all inputs are sanitize_*'d + wp_unslash'd.
        $productId = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0;
        // phpcs:enable WordPress.Security.NonceVerification
        
        if (empty($offerId) || empty($productId)) {
            wp_send_json_error('Invalid request');
        }
        
        // Get offer to apply discount
        $offers = $this->getOffers();
        $offer = null;
        foreach ($offers as $o) {
            if ($o['id'] == $offerId) {
                $offer = $o;
                break;
            }
        }
        
        if (!$offer) {
            wp_send_json_error('Offer not found');
        }
        
        // Get product
        $product = $this->getProduct($productId);
        if (!$product) {
            wp_send_json_error('Product not found');
        }
        
        // Calculate price
        $price = $this->calculateDiscountedPrice(
            floatval($product->price),
            $offer['discount_type'] ?? 'percent',
            floatval($offer['discount_value'] ?? 0)
        );
        
        // Add to cart via CartService
        $cartService = new CartService();
        $result = $cartService->addItem($productId, 1, [], $price);
        
        if ($result) {
            // Track acceptance
            $this->trackAction($offerId, 'accept');
            
            wp_send_json_success([
                'cart' => $cartService->getCart(),
                'message' => 'Added to order!'
            ]);
        } else {
            wp_send_json_error('Failed to add to cart');
        }
    }
    
    /**
     * AJAX: Track upsell view/click
     */
    public function ajaxTrackUpsell(): void
    {
        check_ajax_referer('instinctor_frontend', 'nonce');
        // phpcs:disable WordPress.Security.NonceVerification -- request authenticated via the plugin's check_ajax_referer()/verify() HMAC nonce (standalone auth lifecycle; WPCS does not recognise Session::check as a nonce function); all inputs are sanitize_*'d + wp_unslash'd.
        $offerId = isset($_POST['offer_id']) ? sanitize_text_field(wp_unslash($_POST['offer_id'])) : '';
        // phpcs:enable WordPress.Security.NonceVerification
        // phpcs:disable WordPress.Security.NonceVerification -- request authenticated via the plugin's check_ajax_referer()/verify() HMAC nonce (standalone auth lifecycle; WPCS does not recognise Session::check as a nonce function); all inputs are sanitize_*'d + wp_unslash'd.
        $action = isset($_POST['track_action']) ? sanitize_text_field(wp_unslash($_POST['track_action'])) : 'view';
        // phpcs:enable WordPress.Security.NonceVerification
        
        if (empty($offerId)) {
            wp_send_json_error('Invalid request');
        }
        
        $this->trackAction($offerId, $action);
        wp_send_json_success();
    }
    
    /**
     * Track upsell action
     */
    private function trackAction(string $offerId, string $action): void
    {
        $table = DB::prefix() . 'instinctor_upsell_stats';
        
        // Create table if not exists
        DB::query("CREATE TABLE IF NOT EXISTS $table (
            id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
            offer_id VARCHAR(50),
            action VARCHAR(20),
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            INDEX idx_offer (offer_id),
            INDEX idx_action (action)
        )");
        
        DB::insert($table, [
            'offer_id' => $offerId,
            'action' => $action,
        ]);
    }
    
    /**
     * Render upsell offers HTML
     */
    public function renderOffers(array $cart): string
    {
        $offers = $this->getApplicableOffers($cart);
        
        if (empty($offers)) {
            return '';
        }
        
        $settings = $this->getSettings();
        $showDiscount = $settings['show_discount'] ?? true;
        
        ob_start();
        ?>
        <div class="instinctor-checkout-upsells" data-position="<?php echo esc_attr($settings['display_position'] ?? 'before_payment'); ?>">
            <?php foreach ($offers as $offer): ?>
            <div class="instinctor-upsell-offer" data-offer-id="<?php echo esc_attr($offer['id']); ?>" data-product-id="<?php echo esc_attr($offer['product_id']); ?>">
                <?php if (!empty($offer['product_image'])): ?>
                <div class="instinctor-upsell-image">
                    <img src="<?php echo esc_url($offer['product_image']); ?>" alt="<?php echo esc_attr($offer['product_name']); ?>">
                    <?php if ($showDiscount && $offer['discount_percent'] > 0): ?>
                    <span class="instinctor-upsell-badge">-<?php echo intval($offer['discount_percent']); ?>%</span>
                    <?php endif; ?>
                </div>
                <?php endif; ?>
                
                <div class="instinctor-upsell-content">
                    <?php if (!empty($offer['headline'])): ?>
                    <div class="instinctor-upsell-headline"><?php echo esc_html($offer['headline']); ?></div>
                    <?php endif; ?>
                    
                    <div class="instinctor-upsell-product"><?php echo esc_html($offer['product_name']); ?></div>
                    
                    <?php if (!empty($offer['description'])): ?>
                    <div class="instinctor-upsell-description"><?php echo esc_html($offer['description']); ?></div>
                    <?php endif; ?>
                    
                    <div class="instinctor-upsell-pricing">
                        <?php if ($offer['discounted_price'] < $offer['original_price']): ?>
                        <span class="instinctor-upsell-original"><?php echo wp_kses_post( \Instinctor\Services\CurrencyService::format( (float) $offer['original_price'] ) ); ?></span>
                        <?php endif; ?>
                        <span class="instinctor-upsell-price"><?php echo wp_kses_post( \Instinctor\Services\CurrencyService::format( (float) $offer['discounted_price'] ) ); ?></span>
                    </div>
                </div>
                
                <button type="button" class="instinctor-upsell-accept" data-offer-id="<?php echo esc_attr($offer['id']); ?>" data-product-id="<?php echo esc_attr($offer['product_id']); ?>">
                    <?php echo esc_html($offer['button_text']); ?>
                </button>
            </div>
            <?php endforeach; ?>
        </div>
        <?php
        wp_add_inline_style('instinctor-page-inline', '
        .instinctor-checkout-upsells { margin: 20px 0; }
        .instinctor-upsell-offer {
            display: flex;
            align-items: center;
            gap: 16px;
            padding: 16px;
            background: linear-gradient(135deg, #f8f9fa 0%, #fff 100%);
            border: 2px solid #e8e8ed;
            border-radius: 12px;
            margin-bottom: 12px;
        }
        .instinctor-upsell-offer:hover { border-color: #000; }
        .instinctor-upsell-image {
            position: relative;
            flex-shrink: 0;
            width: 80px;
            height: 80px;
        }
        .instinctor-upsell-image img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            border-radius: 8px;
        }
        .instinctor-upsell-badge {
            position: absolute;
            top: -6px;
            right: -6px;
            background: #ef4444;
            color: #fff;
            font-size: 11px;
            font-weight: 700;
            padding: 2px 6px;
            border-radius: 4px;
        }
        .instinctor-upsell-content { flex: 1; min-width: 0; }
        .instinctor-upsell-headline {
            font-size: 11px;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            color: #ef4444;
            font-weight: 600;
            margin-bottom: 4px;
        }
        .instinctor-upsell-product {
            font-size: 15px;
            font-weight: 600;
            color: #1d1d1f;
            margin-bottom: 4px;
        }
        .instinctor-upsell-description {
            font-size: 13px;
            color: #666;
            margin-bottom: 6px;
        }
        .instinctor-upsell-pricing { display: flex; align-items: center; gap: 8px; }
        .instinctor-upsell-original {
            font-size: 13px;
            color: #999;
            text-decoration: line-through;
        }
        .instinctor-upsell-price {
            font-size: 16px;
            font-weight: 700;
            color: #1d1d1f;
        }
        .instinctor-upsell-accept {
            flex-shrink: 0;
            background: #000;
            color: #fff;
            border: none;
            padding: 10px 20px;
            border-radius: 8px;
            font-size: 14px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s;
        }
        .instinctor-upsell-accept:hover {
            background: #333;
            transform: scale(1.02);
        }
        .instinctor-upsell-accept.loading {
            opacity: 0.7;
            pointer-events: none;
        }
        .instinctor-upsell-accept.added {
            background: #22863a;
        }
        @media (max-width: 600px) {
            .instinctor-upsell-offer { flex-wrap: wrap; }
            .instinctor-upsell-accept { width: 100%; }
        }
        ');
        ob_start();
        ?>
        (function() {
            document.querySelectorAll('.instinctor-upsell-accept').forEach(function(btn) {
                btn.addEventListener('click', function() {
                    var offerId = this.dataset.offerId;
                    var productId = this.dataset.productId;
                    var button = this;
                    
                    button.classList.add('loading');
                    button.textContent = 'Adding...';
                    
                    fetch(instinctorCheckout.ajaxUrl, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                        body: 'action=instinctor_accept_upsell&offer_id=' + offerId + '&product_id=' + productId
                    })
                    .then(function(r) { return r.json(); })
                    .then(function(data) {
                        button.classList.remove('loading');
                        if (data.success) {
                            button.classList.add('added');
                            button.textContent = 'Added!';
                            button.disabled = true;
                            // Update cart display if function exists
                            if (typeof window.instinctorUpdateCart === 'function') {
                                window.instinctorUpdateCart(data.data.cart);
                            }
                            // Refresh order summary
                            if (typeof window.instinctorRefreshOrderSummary === 'function') {
                                window.instinctorRefreshOrderSummary();
                            }
                        } else {
                            button.textContent = 'Error';
                            setTimeout(function() {
                                button.textContent = '<?php echo esc_js($offers[0]['button_text'] ?? 'Add to Order'); ?>';
                            }, 2000);
                        }
                    })
                    .catch(function() {
                        button.classList.remove('loading');
                        button.textContent = 'Error';
                    });
                });
            });
            
            // Track views
            document.querySelectorAll('.instinctor-upsell-offer').forEach(function(offer) {
                fetch(instinctorCheckout.ajaxUrl, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                    body: 'action=instinctor_track_upsell&offer_id=' + offer.dataset.offerId + '&track_action=view'
                });
            });
        })();
        <?php
        $_upsellJs = ob_get_clean();
        wp_add_inline_script('instinctor-frontend-js', $_upsellJs, 'after');
        return ob_get_clean();
    }

    /**
     * Register an AJAX handler for both WordPress and standalone modes.
     * On WordPress: add_action('wp_ajax_' . $action)
     * On standalone: AjaxDispatcher::register($action)
     */
    private function registerAjax(string $action, callable $handler): void
    {
        if (!defined('INSTINCTOR_ENV') || INSTINCTOR_ENV === 'wordpress') {
            add_action('wp_ajax_' . $action, $handler);
        } else {
            \Instinctor\Core\AjaxDispatcher::register($action, $handler);
        }
    }

}
