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

namespace SAAI\AI_Agents;

use SAAI\Traits\Singleton_Trait;
use SAAI\Abstracts\Abstract_AI_Agent;
use SAAI\Classes\Plan_Manager;
use SAAI\Factories\Vite_App;
use SAAI\Helpers\Helper;
use SAAI\Helpers\Product;
use SAAI\Interfaces\Bulk_Run_Agent_Interface;

/**
 * Product_Summaries_AI class.
 *
 * @since 1.0.2
 */
class Product_Summaries_AI extends Abstract_AI_Agent implements Bulk_Run_Agent_Interface {


    use Singleton_Trait;

    const PRODUCT_SUMMARY_META_KEY = 'saai_product_summary';

    /**
     * Holds the class instance object
     *
     * @since 1.0.2
     * @var   Product_Summaries_AI $instance
     */
    protected static $instance;

    /**
     * Holds the settings data.
     *
     * @since 1.0.2
     * @var array Settings data.
     */
    protected $settings;

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

        $this->endpoint         = 'product-summaries';
        $this->ai_id            = "$this->endpoint-ai";
        $this->data             = $data;
        $this->default_settings = array(
            'enabled'                => $this->maybe_enable_by_default(),
            'includeFeaturesNum'     => 3,
            'language'               => 'default',
            'missing_desc_check'     => 'yes',  // Enable missing short description checks by default.
            'missing_desc_frequency' => 12,     // Default check every 12 hours.
            'missing_desc_limit'     => 5,      // Default notification limit per run.
        );

        // Initialize settings.
        $this->settings = $this->get_settings();
    }

    /**
     * Run the agent query.
     *
     * @param  array $params The parameters for the agent query.
     * @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 )
            );
        }

        if ( empty( $product->get_description() ) ) {
            return new \WP_Error(
                'saai_invalid_product_description',
                // translators: %s: product ID.
                sprintf( __( 'Product "%s" is skipped: please ensure that your product has an existing description so the AI can process it via bulk action.', 'storeagent-ai-for-woocommerce' ), $product->get_name() )
            );
        }

        $data = array(
            'product_url'  => 'product_url: ' . get_permalink( $product_id ),
            'product_info' => 'product_info: ' . wp_json_encode( Product::get_product_info( $product_id ) ),
        );

        if ( ! empty( $params['include_product_features'] ) ) {
            $data['include_product_features'] = 'include_product_features: ' . $params['include_product_features'];
        }

        // Set language into the data array.
        $data['language'] = Helper::resolve_default_language( $this->get_settings( 'language' ) );

        $data = apply_filters( 'saai_product_summaries_ai_data', $data );

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

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

        return $ai_response;
    }

    /**
     * Save the object data.
     *
     * @param  int|\WC_Product $product The product ID or the product object.
     * @param  array           $data    The data to save.
     * @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_id', __( 'Invalid product ID.', 'storeagent-ai-for-woocommerce' ) );
        }

        $data = wp_parse_args(
            $data,
            array(
                'summary'  => '',
                'features' => '',
            )
        );

        $summary = self::append_features_to_summary( $data['summary'], $data['features'] );

        // update product short description.
        $product->set_short_description( $summary );
        $product->update_meta_data( self::PRODUCT_SUMMARY_META_KEY, $summary );
        $product->save();

        return true;
    }

    /**
     * Append features to the summary.
     *
     * @param  string $summary  The summary.
     * @param  array  $features The features.
     * @return string
     */
    public static function append_features_to_summary( $summary, $features ) {
        if ( empty( $features ) ) {
            return $summary;
        }

        $summary .= '<ul class="saai-product-features">';
        foreach ( $features as $feature ) {
            $summary .= sprintf( '<li>%s</li>', $feature );
        }
        $summary .= '</ul>';

        return $summary;
    }

    /**
     * Add Generate Summary button to the product short description editor.
     *
     * @since  1.0.2
     * @return void
     */
    public function add_generate_summary_button() {

        $screen = get_current_screen();

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

        $script = new Vite_App(
            'saai-generate-summary',
            'src/vanilla/admin/product-summaries/index.ts',
            array(
                'wp-i18n',
                'wp-url',
            ),
            array_merge(
                array(
                    'restUrl' => \SAAI\REST\Product_Summaries_AI::instance()->api_url,
                    'wpNonce' => wp_create_nonce( 'wp_rest' ),
                ),
                Plan_Manager::get_credit_usage_l10n()
            ),
            'saaiObj'
        );
        $script->enqueue();
    }

    /**
     * Generate a short description for a product directly via callback.
     *
     * @param array $args Arguments containing the product_id.
     * @return bool|WP_Error True on success, WP_Error on failure.
     */
    public function generate_product_short_description( $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 a summary.
        $response = $this->run_agent_query( array( 'product_id' => $product_id ) );

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

        // Extract the summary from the response.
        if ( empty( $response['completion']['summary'] ) ) {
            return new \WP_Error( 'no_summary', __( 'No summary was generated.', 'storeagent-ai-for-woocommerce' ) );
        }

        /***************************************************************************
         * Process the summary from the AI response
         ***************************************************************************
         * Replicate the same flow that happens in the REST endpoint and JS.
         */
        [
            'summary'  => $summary,
            'features' => $features,
        ] = wp_parse_args(
            $response['completion'],
            array(
                'summary'  => '',
                'features' => '',
            )
        );

        // Apply any filters that might be in place for the summary.
        $filtered_summary = apply_filters( 'saai_product_summaries_ai_summary', null, $response );
        if ( ! empty( $filtered_summary ) ) {
            $summary = $filtered_summary;
        }

        // Also save the data to the product meta for consistency.
        $this->save_object_data(
            $product,
            array(
                'summary'  => $summary,
                'features' => $features,
            )
        );

        return true;
    }

    /**
     * Dismiss a missing description notification.
     *
     * @param array $args Arguments containing the product_id.
     * @return bool|WP_Error True on success, WP_Error on failure.
     */
    public function dismiss_missing_description_notification( $args ) {
        // This method is just used as a callback for rejecting the notification.
        // The notification will be automatically archived, so we just return true.
        return true;
    }

    /**
     * Maybe enable the AI agent by default.
     *
     * @since  1.0.4
     * @return string
     */
    public function maybe_enable_by_default() {
        return 'yes';
    }

    /**
     * Run AI agent hooks.
     *
     * @since 1.0.2
     */
    public function run() {

        if ( ! $this->is_enabled() ) {
            return;
        }

        // Register init_settings on init hook to ensure textdomain is loaded.
        add_action( 'init', array( $this, 'init_settings' ) );

        add_action( 'admin_enqueue_scripts', array( $this, 'add_generate_summary_button' ) );

        // Handle notification action URL.
        add_filter( 'saai_notification_custom_action_url', array( $this, 'handle_notification_action_url' ), 10, 3 );
    }

    /**
     * Initialize settings for the AI agent.
     *
     * @return void
     */
    public function init_settings() {
        // Add a settings section for missing short description checks.
        add_filter( 'saai_agent_settings_' . $this->ai_id, array( $this, 'add_missing_short_description_check_settings' ), 10, 1 );
    }

    /**
     * Add settings for missing short description checks.
     *
     * @param array $settings The existing settings.
     * @return array Modified settings.
     */
    public function add_missing_short_description_check_settings( $settings ) {
        // Add to the settings array.
        $settings['missing_desc_check'] = array(
            'type'        => 'toggle',
            'id'          => 'missing_desc_check',
            'name'        => __( 'Missing Short Description Checks', 'storeagent-ai-for-woocommerce' ),
            'description' => __( 'Automatically check for products with missing short descriptions and notify store owner.', 'storeagent-ai-for-woocommerce' ),
            'default'     => $this->default_settings['missing_desc_check'],
        );

        $settings['missing_desc_frequency'] = array(
            'type'        => 'select',
            'id'          => 'missing_desc_frequency',
            'name'        => __( 'Check Frequency', 'storeagent-ai-for-woocommerce' ),
            'description' => __( 'How often to check for missing product short descriptions.', 'storeagent-ai-for-woocommerce' ),
            'default'     => $this->default_settings['missing_desc_frequency'],
            'options'     => array(
                '6'  => __( 'Every 6 hours', 'storeagent-ai-for-woocommerce' ),
                '12' => __( 'Every 12 hours', 'storeagent-ai-for-woocommerce' ),
                '24' => __( 'Every 24 hours', 'storeagent-ai-for-woocommerce' ),
                '48' => __( 'Every 2 days', 'storeagent-ai-for-woocommerce' ),
                '72' => __( 'Every 3 days', 'storeagent-ai-for-woocommerce' ),
            ),
            'conditions'  => array(
                array(
                    'id'    => 'missing_desc_check',
                    'value' => 'yes',
                ),
            ),
        );

        return $settings;
    }

    /**
     * Handle the notification action URL.
     *
     * @param string $url    The URL.
     * @param string $action The action.
     * @param array  $data   The notification data.
     * @return string The URL.
     */
    public function handle_notification_action_url( $url, $action, $data ) {
        // Only handle our own notifications.
        if ( empty( $data['agent'] ) || 'Product_Summaries_AI' !== $data['agent'] ) {
            return $url;
        }

        return $url;
    }
}
