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

namespace SAAI\REST\Chat;

use SAAI\Abstracts\Abstract_REST;
use SAAI\Classes\Chat\Chat_Session;
use SAAI\Helpers\Connect;
use SAAI\Helpers\Helper;
use SAAI\Traits\AI_Tool_Token_Trait;
use SAAI\Traits\Singleton_Trait;
use WC_Product;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

defined( 'ABSPATH' ) || exit;

/**
 * Chat REST API controller class.
 *
 * @since 1.0.8
 */
class Chat extends Abstract_REST {

    use AI_Tool_Token_Trait;
    use Singleton_Trait;

    /**
     * Get the chat message endpoint.
     *
     * @since 1.0.8
     * @return string
     */
    private function get_chat_message_endpoint() {
        return Helper::get_storeagent_base_url( 'api' ) . '/storeagent/v2/chat/message';
    }

    /**
     * Get the chat history endpoint.
     *
     * @since 1.0.8
     * @return string
     */
    private function get_chat_history_endpoint() {
        return Helper::get_storeagent_base_url() . 'wp-json/storeagent/v1/chat/history';
    }

    /**
     * Holds the class instance object.
     *
     * @since 1.0.8
     * @var Chat $instance object
     */
    protected static $instance;

    /**
     * REST constructor.
     *
     * @since 1.0.8
     */
    public function __construct() {
    }

    /**
     * Works as constructor for this class.
     *
     * @since 1.0.8
     * @return void
     */
    public function register_plugin_routes() {
        $this->rest_base = 'chat';
        parent::register_plugin_routes();
    }

    /**
     * Register the routes for Chat.
     *
     * @since 1.0.8
     * @return void
     */
    public function register_routes() {
        // Chat message endpoint.
        register_rest_route(
            $this->namespace,
            "/$this->rest_base/message",
            array(
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => array( $this, 'handle_chat_message' ),
                'permission_callback' => array( $this, 'get_item_permissions_check' ),
                'args'                => array(
                    'message'   => array(
                        'required'          => true,
                        'type'              => 'string',
                        'sanitize_callback' => 'sanitize_textarea_field',
                    ),
                    'sessionId' => array(
                        'required'          => false,
                        'type'              => 'string',
                        'sanitize_callback' => 'sanitize_text_field',
                    ),
                    'context'   => array(
                        'required'          => false,
                        'type'              => 'object',
                        'sanitize_callback' => array( $this, 'sanitize_context_data' ),
                    ),
                ),
            )
        );

        // Chat history endpoint.
        register_rest_route(
            $this->namespace,
            "/$this->rest_base/history",
            array(
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => array( $this, 'get_chat_history' ),
                'permission_callback' => array( $this, 'get_item_permissions_check' ),
                'args'                => array(
                    'from'   => array(
                        'required'          => false,
                        'type'              => 'string',
                        'sanitize_callback' => 'sanitize_text_field',
                    ),
                    'to'     => array(
                        'required'          => false,
                        'type'              => 'string',
                        'sanitize_callback' => 'sanitize_text_field',
                    ),
                    'order'  => array(
                        'required'          => false,
                        'type'              => 'string',
                        'default'           => 'DESC',
                        'sanitize_callback' => 'sanitize_text_field',
                    ),
                    'limit'  => array(
                        'required'          => false,
                        'type'              => 'integer',
                        'default'           => 10,
                        'sanitize_callback' => 'absint',
                    ),
                    'offset' => array(
                        'required'          => false,
                        'type'              => 'integer',
                        'default'           => 0,
                        'sanitize_callback' => 'absint',
                    ),
                ),
            )
        );
    }

    /**
     * Sanitize context data.
     *
     * @since 1.0.8
     * @param array $context The context data to sanitize.
     * @return array Sanitized context data.
     */
    public function sanitize_context_data( $context ) {
        if ( ! is_array( $context ) ) {
            return array();
        }

        $sanitized = array();

        // Sanitize title.
        if ( isset( $context['title'] ) ) {
            $sanitized['title'] = sanitize_text_field( $context['title'] );
        }

        // Sanitize type.
        if ( isset( $context['type'] ) ) {
            $sanitized['type'] = sanitize_text_field( $context['type'] );
        }

        // Sanitize URL.
        if ( isset( $context['url'] ) ) {
            $sanitized['url'] = esc_url_raw( $context['url'] );
        }

        return $sanitized;
    }

    /**
     * Handle chat message request.
     *
     * @since 1.0.8
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error The response object or error.
     */
    public function handle_chat_message( $request ) {
        // Check if we're connected to StoreAgent.
        if ( ! Connect::is_connected() ) {
            return new WP_Error(
                'not_connected',
                __( 'StoreAgent is not connected.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 401 )
            );
        }

        // Prepare request data.
        $request_data = array(
            'message'   => $request->get_param( 'message' ),
            'accountId' => get_current_user_id(),
        );

        // Add sessionId if provided.
        if ( $request->get_param( 'sessionId' ) ) {
            $request_data['sessionId'] = $request->get_param( 'sessionId' );
        }

        // Add context data if provided.
        if ( $request->get_param( 'context' ) ) {
            $request_data['context'] = $request->get_param( 'context' );
        }

        // add site domain to the request data.
        $request_data['siteDomain'] = wp_parse_url( get_home_url(), PHP_URL_HOST );

        // Add rest URL to the request data.
        $request_data['restUrl'] = get_rest_url();

        // Generate and add temporary token for AI tool access.
        $request_data['aiToolToken'] = $this->generate_ai_tool_token();

        // Add tone settings.
        $chat_settings = Chat_Widget_Settings::get_chat_widget_settings();
        if ( ! empty( $chat_settings['tones'] ) && is_array( $chat_settings['tones'] ) ) {
            $request_data['tones'] = $chat_settings['tones'];
        }

        // Prepare headers.
        $headers = array(
            'Content-Type'  => 'application/json',
            'X-Origin'      => wp_parse_url( get_home_url(), PHP_URL_HOST ),
            'Authorization' => 'Basic ' . base64_encode( Connect::get_consumer_key() . ':' . Connect::get_consumer_secret() ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
        );

        // Make request to storeagent-worker.
        $response = wp_remote_post(
            $this->get_chat_message_endpoint(),
            array(
                'headers' => $headers,
                'body'    => wp_json_encode( $request_data ),
                'timeout' => 30,
            )
        );

        // Handle response.
        if ( is_wp_error( $response ) ) {
            return new WP_Error(
                'chat_message_error',
                /* translators: %s is the error message */
                sprintf( __( 'Failed to process chat message. Error: %s', 'storeagent-ai-for-woocommerce' ), $response->get_error_message() ),
                array( 'status' => 500 )
            );
        }

        $status_code = wp_remote_retrieve_response_code( $response );
        $body        = wp_remote_retrieve_body( $response );

        if ( $status_code >= 400 ) {
            $error_data = json_decode( $body, true );
            return new WP_Error(
                'chat_message_error',
                isset( $error_data['message'] ) ? $error_data['message'] : __( 'Failed to process chat message.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => $status_code )
            );
        }

        $response_data = json_decode( $body, true );

        // Trigger action to increment response count for the current session after successful response.
        do_action( 'saai_increment_response_count', get_current_user_id() );

        return new WP_REST_Response( $response_data, $status_code );
    }

    /**
     * Get chat history.
     *
     * @since 1.0.8
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error The response object or error.
     */
    public function get_chat_history( $request ) {
        // Check if we're connected to StoreAgent.
        if ( ! Connect::is_connected() ) {
            return new WP_Error(
                'not_connected',
                __( 'StoreAgent is not connected.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 401 )
            );
        }

        // Prepare query parameters.
        $query_params = array(
            'sessionId' => $request->get_param( 'sessionId' ),
            'from'      => $request->get_param( 'from' ),
            'to'        => $request->get_param( 'to' ),
            'order'     => $request->get_param( 'order' ) ?? 'DESC',
            'limit'     => $request->get_param( 'limit' ) ?? 10,
            'offset'    => $request->get_param( 'offset' ) ?? 0,
        );

        // Remove empty parameters.
        $query_params = array_filter(
            $query_params,
            function ( $value ) {
                return ! empty( $value ) || 0 === $value;
            }
        );

        $endpoint = esc_url_raw(
            add_query_arg(
                $query_params,
                $this->get_chat_history_endpoint()
            )
        );

        // Prepare headers.
        $headers = array(
            'Content-Type'  => 'application/json',
            'X-Origin'      => wp_parse_url( get_home_url(), PHP_URL_HOST ),
            'Authorization' => 'Basic ' . base64_encode( Connect::get_consumer_key() . ':' . Connect::get_consumer_secret() ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
        );

        // Make request to storeagent-worker.
        $response = wp_remote_get(
            $endpoint,
            array(
                'headers' => $headers,
                'timeout' => 30,
            )
        );

        // Handle response.
        if ( is_wp_error( $response ) ) {
            return new WP_Error(
                'chat_history_error',
                __( 'Failed to retrieve chat history.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 500 )
            );
        }

        $status_code = wp_remote_retrieve_response_code( $response );
        $body        = wp_remote_retrieve_body( $response );

        if ( $status_code >= 400 ) {
            $error_data = json_decode( $body, true );
            return new WP_Error(
                'chat_history_error',
                isset( $error_data['message'] ) ? $error_data['message'] : __( 'Failed to retrieve chat history.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => $status_code )
            );
        }

        $response_data = json_decode( $body, true );

        return new WP_REST_Response( $response_data, $status_code );
    }
}
