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

namespace SAAI\AI_Agents;

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

/**
 * Review_Summaries_AI class.
 *
 * @since 1.0.0
 */
class Review_Summaries_AI extends Abstract_AI_Agent implements Bulk_Run_Agent_Interface {

    use Singleton_Trait;
    use Template_Loader;

    /**
     * Holds the class instance object
     *
     * @since 1.0.0
     * @var Review_Summaries_AI $instance object
     */
    protected static $instance;

    /**
     * Generate review summaries hook.
     */
    public const GENERATE_REVIEW_SUMMARIES_HOOK = 'saai_generate_review_summaries';

    /**
     * Low rating threshold for triggering notifications.
     *
     * @var float
     */
    public const LOW_RATING_THRESHOLD = 2.5;

    /**
     * Constructor.
     *
     * @param mixed $data The prompt.
     */
    public function __construct( $data = null ) {
        $this->endpoint = 'review-summaries';
        $this->ai_id    = "$this->endpoint-ai";
        $this->data     = $data;
    }

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

        $review_summary = new Review_Summary( $product->get_id() );
        $total_reviews  = $review_summary->get_total_reviews_count();

        if ( $total_reviews < $this->get_settings( 'minReviews' ) ) {
            return new \WP_Error(
                'saai_insufficient_reviews',
                sprintf(
                    // translators: %1$s: product name, %2$d: minimum reviews.
                    __( 'Product "%1$s" is skipped: Please ensure that the product has at least %2$d reviews so the AI can generate a review summary.', 'storeagent-ai-for-woocommerce' ),
                    $product->get_name(),
                    $this->get_settings( 'minReviews' )
                )
            );
        }

        $result = $review_summary->generate_product_review_summary();

        // If the summary was successfully generated, trigger the automation for rating check.
        if ( ! is_wp_error( $result ) ) {
            do_action( 'saai_after_review_summary_generation', $result, $product->get_name(), $product->get_id() );
        }

        return $result;
    }

    /**
     * Save the object data.
     *
     * @param int   $product_id The product ID.
     * @param array $data The data to save.
     * @return bool|\WP_Error
     */
    public function save_object_data( $product_id, $data ) {
        // NOTE: we don't need to save anything here as it's already been done in `generate_product_review_summary` function.
        return true;
    }

    /**
     * Maybe enable the AI agent by default.
     *
     * @since 1.0.4
     * @return string
     */
    public function maybe_enable_by_default() {
        // Get approved reviews count.
        $review_count = get_comments(
            array(
                'type'   => 'review',
                'status' => 'approve',
                'count'  => true,
            )
        );

        return $review_count > $this->default_settings['minReviews'] ? 'yes' : 'no';
    }

    /**
     * Set language from settings.
     */
    public function set_language_from_settings() {
        $this->data['language'] = Helper::resolve_default_language( $this->get_settings( 'language' ) );
    }

    /**
     * Generate review summaries on approval.
     *
     * @param int   $comment_id The comment ID.
     * @param mixed $data       Comment object, status or data array.
     *
     * @return void
     */
    public function maybe_regenerate_review_summary( $comment_id, $data ) {
        // If the update frequency is not on-review, then skip.
        if ( $this->get_settings( 'updateFrequency' ) !== 'on-review' ) {
            return;
        }

        // Get the status of the comment.
        if ( $data instanceof \WP_Comment ) {
            $status = $data->comment_approved;
        } elseif ( is_string( $data ) || is_numeric( $data ) ) {
            $status = $data;
        } else {
            $status = $data['comment_approved'];
        }

        $approved_status = array( 'approve', 'approved', '1', 1, 'trash' ); // NOTE: we are including trash status here as it's the status of a review when it's permanently deleted.
        if ( ! in_array( $status, $approved_status, true ) ) {
            return;
        }

        $comment    = $data instanceof \WP_Comment ? $data : get_comment( $comment_id );
        $product_id = $comment->comment_post_ID;

        if ( 'product' === get_post_type( $product_id ) ) {
            $reviews = wp_count_comments( $product_id );
            if ( $reviews && isset( $reviews->approved ) && $reviews->approved < intval( $this->get_settings( 'minReviews' ) ) ) {
                return;
            }
            $review_summary = new Review_Summary( $product_id );
            $result         = $review_summary->generate_product_review_summary();

            if ( is_wp_error( $result ) ) {
                wc_get_logger()->error(
                    'Failed to generate review summary.',
                    array(
                        'product_id' => $product_id,
                        'error'      => $result,
                    )
                );
            } else {
                // Trigger automation for the review summary.
                $product = wc_get_product( $product_id );
                do_action( 'saai_after_review_summary_generation', $result, $product->get_name(), $product_id );
            }
        }
    }

    /**
     * Generate review summaries for all products.
     *
     * @return void
     */
    public function generate_review_summaries() {

        global $wpdb;

        $minimum_reviews = $this->get_settings( 'minReviews' );
        $sql             = "
SELECT comment_post_ID as product_id, COUNT(comment_ID) as total_reviews
FROM $wpdb->comments
WHERE comment_approved = 1
  AND comment_type = 'review'
GROUP BY comment_post_ID
HAVING total_reviews > %d
";
        $product_ids     = $wpdb->get_col( $wpdb->prepare( $sql, $minimum_reviews ) ); // phpcs:ignore
        if ( ! empty( $product_ids ) ) {
            foreach ( $product_ids as $product_id ) {
                $review_summary = new Review_Summary( $product_id );
                $result         = $review_summary->generate_product_review_summary();
                if ( is_wp_error( $result ) ) {
                    wc_get_logger()->error(
                        'Failed to generate review summary.',
                        array(
                            'product_id' => $product_id,
                            'error'      => $result,
                        )
                    );
                } else {
                    // Trigger automation for the review summary.
                    $product = wc_get_product( $product_id );
                    do_action( 'saai_after_review_summary_generation', $result, $product->get_name(), $product_id );
                }
            }
        }
    }

    /**
     * Enqueue scripts and styles for the front end.
     *
     * @return void
     */
    public function wp_enqueue_scripts() {

        if ( is_singular( 'product' ) && comments_open() ) {
            if ( $this->get_settings( 'showDisclaimer' ) === 'yes' ) {
                $tooltip = new Vite_App(
                    'saai-review-summary',
                    'src/vanilla/single/product/review-summaries.ts',
                    array( 'jquery', 'wp-i18n' ),
                    array(),
                    'saaiObj',
                    array( 'storeagent-fonts' )
                );
                $tooltip->enqueue();
            } else {
                wp_enqueue_style(
                    'saai-review-summary',
                    plugins_url( 'dist/css/saai-review-summary.css', SAAI_PLUGIN_FILE ),
                    array( 'storeagent-fonts' ),
                    filemtime( SAAI_PLUGIN_DIR_PATH . 'dist/css/saai-review-summary.css' )
                );
            }
        }
    }

    /**
     * Render the review summary on the frontend single product page.
     *
     * @since 1.0.0
     * @return void
     */
    public function render_review_summary() {
        global $product;

        $this->load_template(
            'frontend/review-summary.php',
            array(
                'product' => $product,
            )
        );

        comments_template();
    }

    /**
     * Add the questions tab to the product page.
     *
     * @param array $tabs The tabs.
     *
     * @since 1.0.0
     * @return array
     */
    public function product_tabs( $tabs ) {

        if ( comments_open() && ! empty( $tabs['reviews'] ) ) {
            $tabs['reviews']['callback'] = array( $this, 'render_review_summary' );
        }

        return $tabs;
    }

    /**
     * Register the review summary metabox.
     *
     * @param string   $post_type The post type.
     * @param \WP_Post $post The post object.
     *
     * @return void
     */
    public function register_review_summary_metabox( $post_type, $post ) {
        if ( 'product' !== $post_type ) {
            return;
        }

        add_meta_box(
            'saai-review-summary',
            __( 'AI Generated Reviews Summary', 'storeagent-ai-for-woocommerce' ),
            array( $this, 'display_review_summary_metabox' ),
            'product',
            'normal',
            'low'
        );
    }

    /**
     * Display the review summary metabox.
     *
     * @param \WP_Post $post The post object.
     *
     * @return void
     */
    public function display_review_summary_metabox( $post ) {
        $product               = wc_get_product( $post );
        $review_summary_object = new Review_Summary( $product->get_id() );
        $review_summary        = $review_summary_object->get_saved_review_summary();
        $total_reviews_count   = $review_summary_object->get_total_reviews_count();

        include_once SAAI_PLUGIN_DIR_PATH . 'templates/admin/review-summary-metabox.php';
    }

    /**
     * Enqueue the review summary admin scripts.
     *
     * @since 1.0.1
     * @return void
     */
    public function enqueue_review_summary_admin_scripts() {
        $screen = get_current_screen();

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

        $review_summary = new Vite_App(
            'saai-review-summary',
            'src/vanilla/admin/review-summaries/index.ts',
            array( 'jquery', 'wp-i18n' ),
            array_merge(
                array( 'nonce' => wp_create_nonce( 'saai_regenerate_review_summary' ) ),
                Plan_Manager::get_credit_usage_l10n()
            ),
            'saaiObj',
            array()
        );
        $review_summary->enqueue();
    }

    /**
     * AJAX handler for regenerating the review summary.
     *
     * @return void
     */
    public function ajax_regenerate_review_summary() {

        $post_data = wp_unslash( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing

        if ( ! wp_verify_nonce( sanitize_key( $post_data['nonce'] ), 'saai_regenerate_review_summary' ) ) {
            wp_send_json_error( __( 'Invalid nonce.', 'storeagent-ai-for-woocommerce' ) );
        }

        $product_id = absint( $post_data['product_id'] ?? 0 );

        if ( ! $product_id || ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( __( 'You are not allowed to regenerate the review summary.', 'storeagent-ai-for-woocommerce' ) );
        }

        // Delete the thread ID and last updated date to ensure we generate a new summary.
        $product = wc_get_product( $product_id );
        $product->delete_meta_data( Review_Summary::THREAD_ID_META_KEY );
        $product->delete_meta_data( Review_Summary::LAST_UPDATED_META_KEY );
        $product->delete_meta_data( Review_Summary::SUMMARY_META_KEY );
        $product->save_meta_data();

        // Generate the new summary.
        $review_summary = new Review_Summary( $product_id );
        $result         = $review_summary->generate_product_review_summary();

        if ( is_wp_error( $result ) ) {
            wp_send_json_error( $result->get_error_message() );
        } else {
            // Trigger automation for the review summary.
            do_action( 'saai_after_review_summary_generation', $result, $product->get_name(), $product_id );
        }

        wp_send_json_success( Plan_Manager::instance()->append_usage_data( $result ) );
    }

    /**
     * Save the review summary metabox.
     *
     * @param int      $post_id The post ID.
     * @param \WP_Post $post The post object.
     *
     * @return void
     */
    public function save_review_summary_metabox( $post_id, $post ) {
        if ( ! isset( $_POST['saai_review_summary_metabox_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['saai_review_summary_metabox_nonce'] ), 'saai_review_summary_metabox' ) ) {
            return;
        }

        if ( 'product' !== $post->post_type || ! current_user_can( 'manage_woocommerce' ) || ! isset( $_POST['saai_review'] ) ) {
            return;
        }

        $product                         = wc_get_product( $post_id );
        $review_summary                  = (array) $product->get_meta( Review_Summary::SUMMARY_META_KEY );
        $review_summary['summary']       = ! empty( $_POST['saai_review']['summary'] ) ? wp_kses_post( stripslashes( $_POST['saai_review']['summary'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
        $review_summary['key_takeaways'] = ! empty( $_POST['saai_review']['key_takeaways'] ) ? Review_Summary::sanitize_key_takeaways( $_POST['saai_review']['key_takeaways'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput

        $product->update_meta_data( Review_Summary::SUMMARY_META_KEY, $review_summary );
        $product->save_meta_data();
    }

    /**
     * Run hooks related to the AI agent.
     *
     * @return void
     */
    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' ) );

        // Runs when review's status is changed e.g. moderation screen.
        add_action( 'wp_set_comment_status', array( $this, 'maybe_regenerate_review_summary' ), 10, 2 );
        // Runs when a user review is approved automatically.
        add_action( 'comment_post', array( $this, 'maybe_regenerate_review_summary' ), 10, 2 );
        // Runs when a user review is edited.
        add_action( 'edit_comment', array( $this, 'maybe_regenerate_review_summary' ), 10, 2 );
        // Runs when a user review is deleted. NOTE: trash status is not supported as it runs multiple times (when trashing and when deleting).
        add_action( 'deleted_comment', array( $this, 'maybe_regenerate_review_summary' ), 10, 2 );

        add_action( self::GENERATE_REVIEW_SUMMARIES_HOOK, array( $this, 'generate_review_summaries' ) );
        add_action( 'wp_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ) );
        add_filter( 'woocommerce_product_tabs', array( $this, 'product_tabs' ) );

        // Admin.
        add_action( 'add_meta_boxes', array( $this, 'register_review_summary_metabox' ), 10, 2 );
        add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_review_summary_admin_scripts' ) );
        add_action( 'save_post', array( $this, 'save_review_summary_metabox' ), 10, 2 );
        add_action( 'wp_ajax_saai_regenerate_review_summary', array( $this, 'ajax_regenerate_review_summary' ) );
    }

    /**
     * Initialize settings for the Review Summaries AI.
     *
     * @return void
     */
    public function init_settings() {
        // Initialize settings that need to be translated or registered with WordPress.
        $this->default_settings            = array(
            'minReviews'      => 3,
            'updateFrequency' => 'on-review',
            'showDisclaimer'  => 'no',
            'disclaimerText'  => __( 'This AI-generated content may contain errors or fabrications. We recommend verifying important details independently before purchase.', 'storeagent-ai-for-woocommerce' ),
            'language'        => 'default',
        );
        $this->default_settings['enabled'] = $this->maybe_enable_by_default();
    }
}
