<?php
/**
 * Chat Escalation REST Controller
 *
 * Handles the send-escalation-email chat tool endpoint called by n8n.
 *
 * @package SAAI\REST\Chat
 */

namespace SAAI\REST\Chat;

use SAAI\Abstracts\Abstract_REST;
use SAAI\Traits\Singleton_Trait;
use SAAI\Classes\Chat\Chat_Feedback;
use WC_Email;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

defined( 'ABSPATH' ) || exit;

/**
 * Chat_Escalation REST API controller class.
 *
 * @since 1.2.0
 */
class Chat_Escalation extends Abstract_REST {

    use Singleton_Trait;

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

    /**
     * Maximum escalation emails per session per hour.
     *
     * @since 1.2.0
     * @var int
     */
    const RATE_LIMIT_MAX = 3;

    /**
     * Rate limit window in seconds (1 hour).
     *
     * @since 1.2.0
     * @var int
     */
    const RATE_LIMIT_WINDOW = 3600;

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

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

    /**
     * Register the routes for Chat Escalation.
     *
     * @since 1.2.0
     * @return void
     */
    public function register_routes() {
        register_rest_route(
            $this->namespace,
            "/$this->rest_base/send-escalation-email",
            array(
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => array( $this, 'send_escalation_email' ),
                'permission_callback' => array( $this, 'validate_temp_token_permissions' ),
                'args'                => array(
                    'token'          => array(
                        'required'          => true,
                        'type'              => 'string',
                        'description'       => 'Temporary authentication token with session ID.',
                        'sanitize_callback' => 'sanitize_text_field',
                    ),
                    'customer_email' => array(
                        'required'          => false,
                        'type'              => 'string',
                        'default'           => '',
                        'description'       => 'Customer email address. Only required for guest users; logged-in user email is resolved server-side.',
                        'sanitize_callback' => 'sanitize_email',
                    ),
                    'customer_name'  => array(
                        'required'          => false,
                        'type'              => 'string',
                        'default'           => '',
                        'description'       => 'Customer display name. Only used for guest users; logged-in user name is resolved server-side.',
                        'sanitize_callback' => 'sanitize_text_field',
                    ),
                    'summary'        => array(
                        'required'          => true,
                        'type'              => 'string',
                        'description'       => 'AI-generated conversation summary text.',
                        'sanitize_callback' => 'sanitize_textarea_field',
                    ),
                    'trigger'        => array(
                        'required'          => false,
                        'type'              => 'string',
                        'default'           => 'explicit',
                        'description'       => 'Escalation trigger type.',
                        'sanitize_callback' => 'sanitize_text_field',
                    ),
                ),
            )
        );
    }

    /**
     * Validate temporary token permissions.
     *
     * Follows the same pattern as Chat_Tools::validate_temp_token_permissions().
     *
     * @since 1.2.0
     * @param WP_REST_Request $request The request object.
     * @return bool|WP_Error True if valid token, error otherwise.
     */
    public function validate_temp_token_permissions( $request ) {
        // Allow access to the endpoint for admins.
        if ( current_user_can( 'manage_options' ) ) {
            return true;
        }

        $token_parts = explode( ':::', $request->get_param( 'token' ) );

        if ( count( $token_parts ) < 2 ) {
            return new WP_Error(
                'missing_token',
                __( 'Temporary token is required.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 401 )
            );
        }

        list( $session_id, $token ) = $token_parts;

        if ( empty( $session_id ) || empty( $token ) ) {
            return new WP_Error(
                'missing_token',
                __( 'Temporary token is required.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 401 )
            );
        }

        $session_data = get_transient( "saai_session_$session_id" );

        if ( false === $session_data || ! is_array( $session_data ) || ! isset( $session_data['token'] ) ) {
            return new WP_Error(
                'invalid_token',
                __( 'Invalid or expired temporary token.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 401 )
            );
        }

        // Check if the provided token matches the session token.
        if ( $session_data['token'] !== $token ) {
            return new WP_Error(
                'token_mismatch',
                __( 'Token does not match current session.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 401 )
            );
        }

        // Restore the original user context.
        $user_id = absint( $session_data['user_id'] );

        if ( $user_id > 0 ) {
            wp_set_current_user( $user_id );
        }

        return true;
    }

    /**
     * Send escalation email callback.
     *
     * @since 1.2.0
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error The response object or error.
     */
    public function send_escalation_email( $request ) {
        // Check if escalation email is enabled.
        $feedback_settings = Chat_Feedback::get_feedback_settings();

        if ( empty( $feedback_settings['escalation_email_enabled'] ) ) {
            return new WP_Error(
                'escalation_email_disabled',
                __( 'Email escalation is not enabled.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 403 )
            );
        }

        // Check plan availability.
        if ( ! Chat_Feedback::is_escalation_available() ) {
            return new WP_Error(
                'escalation_not_available',
                __( 'Email escalation is not available on your current plan.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 403 )
            );
        }

        // Resolve customer email and name from session or request params.
        $token_parts  = explode( ':::', $request->get_param( 'token' ) );
        $session_id   = $token_parts[0];
        $session_data = get_transient( "saai_session_$session_id" );
        $user_id      = $session_data ? absint( $session_data['user_id'] ) : 0;

        if ( $user_id > 0 ) {
            // Logged-in user: resolve email and name server-side.
            $user           = get_userdata( $user_id );
            $customer_email = $user ? $user->user_email : '';
            $customer_name  = $user ? $user->display_name : '';
        } else {
            // Guest user: use email/name provided by the AI via n8n.
            $customer_email = $request->get_param( 'customer_email' );
            $customer_name  = $request->get_param( 'customer_name' );
        }

        if ( ! is_email( $customer_email ) ) {
            return new WP_Error(
                'invalid_customer_email',
                __( 'A valid customer email address is required.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 400 )
            );
        }

        // Rate limit check.
        $rate_key    = 'saai_escalation_rate_' . md5( $session_id );
        $rate_count  = (int) get_transient( $rate_key );

        if ( $rate_count >= self::RATE_LIMIT_MAX ) {
            return new WP_Error(
                'rate_limit_exceeded',
                __( 'Too many escalation requests. Please try again later.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 429 )
            );
        }

        // Determine recipient.
        $recipient = ! empty( $feedback_settings['escalation_email_recipient'] )
            ? $feedback_settings['escalation_email_recipient']
            : get_option( 'admin_email' );

        if ( ! is_email( $recipient ) ) {
            return new WP_Error(
                'invalid_recipient',
                __( 'No valid recipient email configured.', 'storeagent-ai-for-woocommerce' ),
                array( 'status' => 500 )
            );
        }

        // Gather email data.
        $summary    = $request->get_param( 'summary' );
        $trigger    = $request->get_param( 'trigger' );
        $store_name = get_bloginfo( 'name' );
        $intro      = ! empty( $feedback_settings['escalation_email_intro'] )
            ? $feedback_settings['escalation_email_intro']
            : __( 'A customer has requested support escalation from the AI chat.', 'storeagent-ai-for-woocommerce' );

        if ( empty( $customer_name ) ) {
            $customer_name = __( 'Guest Customer', 'storeagent-ai-for-woocommerce' );
        }

        // Compose email subject.
        $subject = sprintf(
            /* translators: 1: Store name, 2: Customer name. */
            __( '[%1$s] Chat Escalation from %2$s', 'storeagent-ai-for-woocommerce' ),
            $store_name,
            $customer_name
        );

        /**
         * Filter the escalation email subject.
         *
         * @since 1.2.0
         * @param string $subject        The email subject.
         * @param string $customer_name  The customer name.
         * @param string $customer_email The customer email.
         * @param string $store_name     The store name.
         */
        $subject = apply_filters( 'storeagent_escalation_email_subject', $subject, $customer_name, $customer_email, $store_name );

        // Build email body using template.
        $email_heading = __( 'Chat Support Escalation', 'storeagent-ai-for-woocommerce' );

        // Initialize WC mailer.
        WC()->mailer();

        ob_start();
        include SAAI_TEMPLATES_DIR . 'emails/escalation-email.php';
        $message = ob_get_clean();

        /**
         * Filter the escalation email content.
         *
         * @since 1.2.0
         * @param string $message        The email HTML content.
         * @param string $customer_name  The customer name.
         * @param string $customer_email The customer email.
         * @param string $summary        The conversation summary.
         * @param string $trigger        The escalation trigger type.
         */
        $message = apply_filters( 'storeagent_escalation_email_content', $message, $customer_name, $customer_email, $summary, $trigger );

        // Set headers with Reply-To.
        $headers = array(
            'Content-Type: text/html; charset=UTF-8',
            'From: ' . $store_name . ' <' . get_option( 'admin_email' ) . '>',
            'Reply-To: ' . $customer_name . ' <' . $customer_email . '>',
        );

        // Send via WC_Email.
        $email = new WC_Email();
        $sent  = $email->send( $recipient, $subject, $message, $headers, array() );

        if ( $sent ) {
            // Increment rate limit counter.
            if ( $rate_count > 0 ) {
                set_transient( $rate_key, $rate_count + 1, self::RATE_LIMIT_WINDOW );
            } else {
                set_transient( $rate_key, 1, self::RATE_LIMIT_WINDOW );
            }

            /**
             * Fires after a successful escalation email is sent.
             *
             * @since 1.2.0
             * @param string $recipient      The email recipient.
             * @param string $customer_email The customer email.
             * @param string $customer_name  The customer name.
             * @param string $summary        The conversation summary.
             * @param string $trigger        The escalation trigger type.
             */
            do_action( 'storeagent_escalation_email_sent', $recipient, $customer_email, $customer_name, $summary, $trigger );

            return new WP_REST_Response(
                array(
                    'success' => true,
                    'message' => __( 'Escalation email sent successfully.', 'storeagent-ai-for-woocommerce' ),
                ),
                200
            );
        }

        return new WP_REST_Response(
            array(
                'success' => false,
                'message' => __( 'Failed to send escalation email. Please try again later.', 'storeagent-ai-for-woocommerce' ),
            ),
            500
        );
    }
}
