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

namespace SAAI\AI_Agents;

use SAAI\Abstracts\Abstract_AI_Agent;
use SAAI\Factories\Vite_App;
use SAAI\Traits\Singleton_Trait;
use SAAI\Traits\AI_Tool_Token_Trait;
use SAAI\Traits\Template_Loader;
use SAAI\Interfaces\Bulk_Run_Agent_Interface;
use SAAI\REST\Product_Upsells_AI as Product_Upsells_AI_REST;
use SAAI\Helpers\Helper;
use WP_Error;

/**
 * Product_Upsells_AI class.
 *
 * Handles AI-powered product upsell and cross-sell recommendations.
 *
 * @since 1.2.0
 */
class Product_Upsells_AI extends Abstract_AI_Agent implements Bulk_Run_Agent_Interface {

    use Singleton_Trait;
    use AI_Tool_Token_Trait;
    use Template_Loader;

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

    /**
     * Class constructor.
     *
     * @param null|array $data The data to be used for the AI agent.
     *
     * @since 1.2.0
     */
    public function __construct( $data = null ) {

        $this->endpoint         = 'product-upsells';
        $this->ai_id            = "$this->endpoint-ai";
        $this->data             = $data;
        $this->default_settings = array(
            'enabled'             => 'no',
            'recommendation_type' => 'both',
            'max_recommendations' => 5,
            'scan_check'          => 'yes',
            'scan_frequency'      => 24,
            'language'            => 'default',
        );
    }

    /**
     * Run the agent query.
     *
     * @param array $params The parameters for the agent query.
     *
     * @since 1.2.0
     * @return array|WP_Error
     */
    public function run_agent_query( $params = array() ) {
        $product_id = (int) ( $params['product_id'] ?? 0 );
        $product    = wc_get_product( $product_id );

        if ( ! $product ) {
            return new WP_Error(
                'saai_invalid_product_id',
                // translators: %s: product ID.
                sprintf( __( 'Invalid product ID: %s', 'storeagent-ai-for-woocommerce' ), $product_id )
            );
        }

        // Prepare product data.
        $product_data = $this->get_product_data( $product );

        // Passthrough data: token-related data for n8n to access store data.
        $passthrough = array(
            'restUrl'     => get_rest_url(),
            'aiToolToken' => $this->generate_ai_tool_token(),
            'siteDomain'  => wp_parse_url( get_home_url(), PHP_URL_HOST ),
        );

        $data = array(
            'product_data'        => wp_json_encode( $product_data ),
            'recommendation_type' => $this->get_settings( 'recommendation_type' ),
            'max_recommendations' => $this->get_settings( 'max_recommendations' ),
            'passthrough'         => $passthrough,
        );

        $this->set_data( $data );
        $response = $this->send_prompt();

        if ( is_wp_error( $response ) ) {
            return $response;
        }

        return $response;
    }

    /**
     * Save the object data.
     *
     * @param int|\WC_Product $product The product ID or the product object.
     * @param array           $data    The data to save (upsell_ids, cross_sell_ids).
     *
     * @since 1.2.0
     * @return bool|WP_Error
     */
    public function save_object_data( $product, $data ) {
        $product = $product instanceof \WC_Product ? $product : wc_get_product( $product );

        if ( ! $product ) {
            return new WP_Error( 'invalid_product', __( 'Invalid product ID.', 'storeagent-ai-for-woocommerce' ) );
        }

        $recommendation_type = $this->get_settings( 'recommendation_type' );

        // Apply upsell IDs.
        if ( in_array( $recommendation_type, array( 'both', 'upsells' ), true ) && ! empty( $data['upsell_ids'] ) ) {
            $valid_upsell_ids = $this->validate_product_ids( $data['upsell_ids'], $product->get_id() );
            $product->set_upsell_ids( $valid_upsell_ids );
        }

        // Apply cross-sell IDs.
        if ( in_array( $recommendation_type, array( 'both', 'cross_sells' ), true ) && ! empty( $data['cross_sell_ids'] ) ) {
            $valid_cross_sell_ids = $this->validate_product_ids( $data['cross_sell_ids'], $product->get_id() );
            $product->set_cross_sell_ids( $valid_cross_sell_ids );
        }

        $product->save();

        return true;
    }

    /**
     * Generate and apply upsell/cross-sell recommendations for a product.
     *
     * This is the accept callback for decision notifications.
     *
     * @param array $args Arguments containing the product_id.
     *
     * @since 1.2.0
     * @return bool|WP_Error True on success, WP_Error on failure.
     */
    public function generate_and_apply_recommendations( $args ) {
        if ( empty( $args['product_id'] ) ) {
            return new WP_Error( 'missing_product_id', __( 'Product ID is required.', 'storeagent-ai-for-woocommerce' ) );
        }

        $product_id = absint( $args['product_id'] );
        $product    = wc_get_product( $product_id );

        if ( ! $product ) {
            return new WP_Error( 'invalid_product', __( 'Invalid product.', 'storeagent-ai-for-woocommerce' ) );
        }

        // Run the agent to generate recommendations.
        $response = $this->run_agent_query( array( 'product_id' => $product_id ) );

        if ( is_wp_error( $response ) ) {
            return $response;
        }

        // Extract recommendations from the response.
        $completion = $response['completion'] ?? array();

        $upsell_ids     = $completion['upsell_ids'] ?? array();
        $cross_sell_ids = $completion['cross_sell_ids'] ?? array();

        if ( empty( $upsell_ids ) && empty( $cross_sell_ids ) ) {
            return new WP_Error( 'no_recommendations', __( 'No suitable recommendations were found for this product.', 'storeagent-ai-for-woocommerce' ) );
        }

        // Apply the recommendations.
        $this->save_object_data(
            $product,
            array(
                'upsell_ids'     => $upsell_ids,
                'cross_sell_ids' => $cross_sell_ids,
            )
        );

        return true;
    }

    /**
     * Discard upsell/cross-sell recommendations.
     *
     * This is the reject callback for decision notifications.
     *
     * @param array $args Arguments containing the product_id.
     *
     * @since 1.2.0
     * @return bool
     */
    public function discard_recommendations( $args ) {
        // No-op. The notification will be automatically archived.
        return true;
    }

    /**
     * Get product data for the AI prompt.
     *
     * @param \WC_Product $product The product object.
     *
     * @since 1.2.0
     * @return array
     */
    private function get_product_data( $product ) {
        $categories  = get_the_terms( $product->get_id(), 'product_cat' );
        $cat_names   = ( $categories && ! is_wp_error( $categories ) ) ? wp_list_pluck( $categories, 'name' ) : array();
        $attributes  = $product->get_attributes();
        $attr_values = array();

        foreach ( $attributes as $attribute ) {
            if ( is_a( $attribute, 'WC_Product_Attribute' ) ) {
                $attr_values[ $attribute->get_name() ] = $attribute->get_options();
            }
        }

        return array(
            'id'                => $product->get_id(),
            'name'              => $product->get_name(),
            'description'       => $product->get_description(),
            'short_description' => $product->get_short_description(),
            'regular_price'     => $product->get_regular_price(),
            'sale_price'        => $product->get_sale_price(),
            'categories'        => $cat_names,
            'attributes'        => $attr_values,
            'type'              => $product->get_type(),
        );
    }

    /**
     * Validate product IDs are real published products.
     *
     * @param array $ids        The product IDs to validate.
     * @param int   $exclude_id Product ID to exclude (the target product itself).
     *
     * @since 1.2.0
     * @return array Valid product IDs.
     */
    private function validate_product_ids( $ids, $exclude_id = 0 ) {
        if ( ! is_array( $ids ) ) {
            return array();
        }

        $valid_ids = array();

        foreach ( $ids as $id ) {
            $id = absint( $id );

            if ( 0 === $id || $id === $exclude_id ) {
                continue;
            }

            $product = wc_get_product( $id );

            if ( $product && 'publish' === $product->get_status() ) {
                $valid_ids[] = $id;
            }
        }

        return $valid_ids;
    }

    /**
     * Add the AI generate button to the linked products panel.
     *
     * @since 1.3.0
     * @return void
     */
    public function add_generate_button_to_linked_products() {
        global $post;

        if ( ! $post || get_post_type( $post ) !== 'product' ) {
            return;
        }

        $this->load_template(
            'admin/product-upsells-button.php',
            array(
                'product_id' => $post->ID,
            )
        );
    }

    /**
     * Enqueue scripts for the linked products panel.
     *
     * @since 1.3.0
     * @return void
     */
    public function enqueue_linked_products_scripts() {
        $screen = get_current_screen();

        if ( ! $screen || 'product' !== $screen->id || 'product' !== $screen->post_type ) {
            return;
        }

        // Enqueue dashicons if not already included.
        wp_enqueue_style( 'dashicons' );

        // Initialize Vite_App for the product upsells script.
        $product_upsells_app = new Vite_App(
            'saai-product-upsells-admin',
            'src/vanilla/admin/product-upsells/index.ts',
            array( 'jquery' ),
            array(
                'productUpsellsRestUrl' => Product_Upsells_AI_REST::instance()->api_url,
                'wpNonce'               => wp_create_nonce( 'wp_rest' ),
            ),
        );

        // Enqueue the script.
        $product_upsells_app->enqueue();

        // Localize script with parameters.
        wp_localize_script(
            'saai-product-upsells-admin',
            'saaiProductUpsellsParams',
            array(
                'generating'         => __( 'Generating recommendations...', 'storeagent-ai-for-woocommerce' ),
                'success'            => __( 'Recommendations generated successfully!', 'storeagent-ai-for-woocommerce' ),
                'error'              => __( 'Error generating recommendations.', 'storeagent-ai-for-woocommerce' ),
                'buttonText'         => __( 'Generate with AI', 'storeagent-ai-for-woocommerce' ),
                'confirmSaveChanges' => __( 'For better results, please save any changes made to the product first. Do you want to proceed?', 'storeagent-ai-for-woocommerce' ),
            )
        );
    }

    /**
     * Run AI agent hooks.
     *
     * @since 1.2.0
     * @return void
     */
    public function run() {
        if ( ! $this->is_enabled() ) {
            return;
        }

        // Admin functionality.
        add_action( 'admin_footer', array( $this, 'add_generate_button_to_linked_products' ) );
        add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_linked_products_scripts' ) );
    }
}
