<?php
/**
 * Author: Rymera Web Co.
 *
 * @package SAAI\Automations
 */

namespace SAAI\Automations;

use SAAI\Traits\Singleton_Trait;
use SAAI\AI_Agents\Product_Upsells_AI;
use SAAI\Classes\Notification;

/**
 * Product_Upsells_Automations class.
 *
 * Handles automated scanning for products missing upsells/cross-sells
 * and creates decision notifications for store owners.
 *
 * @since 1.2.0
 */
class Product_Upsells_Automations {

    use Singleton_Trait;

    /**
     * Holds the class instance object.
     *
     * @since 1.2.0
     * @var Product_Upsells_Automations $instance
     */
    protected static $instance;

    /**
     * Action hook for the upsell/cross-sell scan.
     */
    const UPSELL_SCAN_ACTION = 'saai_check_product_upsells_crosssells';

    /**
     * Batch size for processing products.
     */
    const BATCH_SIZE = 50;

    /**
     * Maximum notifications to create per batch run.
     */
    const MAX_NOTIFICATIONS_PER_RUN = 5;

    /**
     * Setup action hooks when class is initialized.
     *
     * @since 1.2.0
     */
    public function __construct() {
        // Register Action Scheduler hooks.
        add_action( self::UPSELL_SCAN_ACTION, array( $this, 'handle_upsell_scan' ) );
    }

    /**
     * Schedule the upsell/cross-sell scan.
     *
     * @param array $settings The settings to use for scheduling.
     *
     * @since 1.2.0
     * @return void
     */
    public function schedule_upsell_scan( $settings ) {
        // Only schedule if the product upsells AI is enabled.
        $upsells_ai = Product_Upsells_AI::instance();
        if ( ! $upsells_ai->is_enabled() ) {
            return;
        }

        // Only schedule if the scan check is enabled.
        if ( 'yes' !== ( $settings['scan_check'] ?? 'no' ) ) {
            $this->unschedule_upsell_scan();
            return;
        }

        // Get frequency setting (hours).
        $frequency = intval( $settings['scan_frequency'] ?? 24 );
        if ( $frequency < 1 ) {
            $frequency = 24;
        }

        // If the action is already scheduled, don't schedule it again.
        if ( as_next_scheduled_action( self::UPSELL_SCAN_ACTION ) ) {
            return;
        } else {
            as_schedule_recurring_action(
                time(),
                $frequency * HOUR_IN_SECONDS,
                self::UPSELL_SCAN_ACTION
            );
        }
    }

    /**
     * Unschedule the upsell/cross-sell scan.
     *
     * @since 1.2.0
     * @return void
     */
    public function unschedule_upsell_scan() {
        as_unschedule_all_actions( self::UPSELL_SCAN_ACTION );
    }

    /**
     * Handle the scheduled upsell/cross-sell scan.
     *
     * Scans products for missing upsells/cross-sells and creates
     * decision notifications for the store owner.
     *
     * @since 1.2.0
     * @return void
     */
    public function handle_upsell_scan() {
        $upsells_ai = Product_Upsells_AI::instance();
        $settings   = $upsells_ai->get_settings();

        // Only proceed if scan check is enabled.
        if ( 'yes' !== ( $settings['scan_check'] ?? 'no' ) ) {
            return;
        }

        $recommendation_type = $settings['recommendation_type'] ?? 'both';

        // Get random published products (exclude variations).
        $products = wc_get_products(
            array(
                'status'  => 'publish',
                'limit'   => self::BATCH_SIZE,
                'orderby' => 'rand',
                'type'    => array( 'simple', 'variable', 'grouped', 'external' ),
            )
        );

        if ( empty( $products ) ) {
            return;
        }

        $notification_count = 0;

        foreach ( $products as $product ) {
            if ( $notification_count >= self::MAX_NOTIFICATIONS_PER_RUN ) {
                break;
            }

            $product_id   = $product->get_id();
            $missing_type = $this->get_missing_recommendation_type( $product, $recommendation_type );

            // Skip if product already has the required recommendations.
            if ( empty( $missing_type ) ) {
                continue;
            }

            // Check if we already have a pending notification for this product.
            $existing_notification = Notification::instance()->get_all(
                array(
                    'product_id'        => $product_id,
                    'notification_type' => 'upsell_crosssell_recommendation',
                    'status'            => array( 'pending' ),
                    'agent'             => 'Product_Upsells_AI',
                )
            );

            if ( ! empty( $existing_notification ) ) {
                continue;
            }

            // Create decision notification.
            $notification_id = Notification::instance()->create_decision_notification(
                __( 'Product upsell/cross-sell recommendations', 'storeagent-ai-for-woocommerce' ),
                sprintf(
                    /* translators: 1: Product name, 2: Missing recommendation type. */
                    __( 'The product "%1$s" has no %2$s configured. Click Accept to let StoreAgent AI analyze your catalog and suggest the best products.', 'storeagent-ai-for-woocommerce' ),
                    $product->get_name(),
                    $missing_type
                ),
                'Product_Upsells_AI',
                array(
                    'class'  => 'SAAI\AI_Agents\Product_Upsells_AI',
                    'method' => 'generate_and_apply_recommendations',
                    'args'   => array(
                        'product_id' => $product_id,
                    ),
                ),
                array(
                    'class'  => 'SAAI\AI_Agents\Product_Upsells_AI',
                    'method' => 'discard_recommendations',
                    'args'   => array(
                        'product_id' => $product_id,
                    ),
                ),
                $product_id,
                array( 'notification_type' => 'upsell_crosssell_recommendation' )
            );

            if ( $notification_id ) {
                ++$notification_count;
            }
        }
    }

    /**
     * Determine what type of recommendations are missing for a product.
     *
     * @param \WC_Product $product             The product object.
     * @param string      $recommendation_type The configured recommendation type (both/upsells/cross_sells).
     *
     * @since 1.2.0
     * @return string The missing type description, or empty string if nothing is missing.
     */
    private function get_missing_recommendation_type( $product, $recommendation_type ) {
        $missing_upsells     = empty( $product->get_upsell_ids() );
        $missing_cross_sells = empty( $product->get_cross_sell_ids() );

        switch ( $recommendation_type ) {
            case 'upsells':
                return $missing_upsells ? __( 'upsells', 'storeagent-ai-for-woocommerce' ) : '';

            case 'cross_sells':
                return $missing_cross_sells ? __( 'cross-sells', 'storeagent-ai-for-woocommerce' ) : '';

            case 'both':
            default:
                if ( $missing_upsells && $missing_cross_sells ) {
                    return __( 'upsells or cross-sells', 'storeagent-ai-for-woocommerce' );
                } elseif ( $missing_upsells ) {
                    return __( 'upsells', 'storeagent-ai-for-woocommerce' );
                } elseif ( $missing_cross_sells ) {
                    return __( 'cross-sells', 'storeagent-ai-for-woocommerce' );
                }

                return '';
        }
    }

    /**
     * Handle settings saved via REST API.
     *
     * @param array            $response     The response data.
     * @param array            $settings     The new settings.
     * @param array            $old_settings The old settings.
     * @param \WP_REST_Request $request      The request object.
     *
     * @since 1.2.0
     * @return array The response data.
     */
    public function handle_rest_settings_save( $response, $settings, $old_settings, $request ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
        // Always unschedule first to ensure any frequency changes take effect.
        $this->unschedule_upsell_scan();

        // Reschedule with new settings.
        $this->schedule_upsell_scan( $settings );

        return $response;
    }

    /**
     * Run the automation setup.
     *
     * @since 1.2.0
     * @return void
     */
    public function run() {
        $upsells_ai = Product_Upsells_AI::instance();

        // Only run automations if the AI agent is enabled.
        if ( ! $upsells_ai->is_enabled() ) {
            return;
        }

        // Hook into REST API settings save response.
        add_filter( 'saai_rest_product-upsells-ai_settings_save_response', array( $this, 'handle_rest_settings_save' ), 10, 4 );
    }
}
