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

namespace SAAI\REST;

use SAAI\Abstracts\Abstract_REST;
use SAAI\Classes\Plan_Manager;
use SAAI\Helpers\Connect as Connect_Class;
use SAAI\Helpers\Helper;
use SAAI\Traits\Singleton_Trait;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

defined( 'ABSPATH' ) || exit;

/**
 * Class REST
 *
 * @since   1.0.0
 * @package SAAI
 */
class Connect extends Abstract_REST {

    use Singleton_Trait;

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

    /**
     * Auth nonce.
     *
     * @since 1.0.0
     * @var string
     */
    private $auth_token;

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

    /**
     * Works as constructor for this class.
     *
     * @since 1.0.0
     * @return void
     */
    public function register_plugin_routes() {

        $this->auth_token = Helper::create_token( 'storeagent-auth' );

        $this->rest_base = 'connect';
        parent::register_plugin_routes();
    }

    /**
     * Register the routes for the objects of the controller.
     *
     * @since 1.0.0
     */
    public function register_routes() {

        register_rest_route(
            $this->namespace,
            "/$this->rest_base/auth/disconnect",
            array(
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => array( $this, 'disconnect_user_initiated' ),
                'permission_callback' => array( $this, 'update_item_permissions_check' ),
            )
        );

        register_rest_route(
            $this->namespace,
            "/$this->rest_base/auth/disconnect/webhook",
            array(
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => array( $this, 'disconnect_webhook' ),
                'permission_callback' => array( $this, 'disconnect_webhook_check' ),
            )
        );
    }

    /**
     * Check if a given request is a valid disconnect webhook request.
     *
     * @param WP_REST_Request $request REST request object.
     *
     * @return bool
     */
    public function disconnect_webhook_check( $request ) {

        [
            'domain'        => $host,
            'truncated_key' => $truncated_key,
        ] = $request->get_params();

        $parsed_host = wp_parse_url( get_home_url(), PHP_URL_HOST );

        return $parsed_host === $host && Connect_Class::get_truncated_key() === $truncated_key;
    }

    /**
     * Check if a given request has access to get items.
     *
     * @param WP_REST_Request $request REST request object.
     *
     * @return bool
     */
    public function auth_permission( $request ) {

        $nonce = $request->get_param( 'auth_token' );

        return Helper::verify_token( $nonce, 'storeagent-auth' );
    }

    /**
     * Checks if a given request has access to update a specific item.
     *
     * @param WP_REST_Request $request Full data about the request.
     *
     * @since 1.0.0
     * @return WP_Error|bool True if the request has access to update the item, WP_Error object otherwise.
     */
    public function update_item_permissions_check( $request ) {

        return current_user_can( 'manage_woocommerce' );
    }

    /**
     * Disconnect handler for user-initiated disconnections.
     *
     * @param WP_REST_Request $request REST request object.
     *
     * @since 1.1.3 Notify the auth server about the disconnection.
     *
     * @return WP_REST_Response REST response object.
     */
    public function disconnect_user_initiated( $request ) {

        return $this->disconnect( $request, true );
    }

    /**
     * Disconnect the auth data.
     *
     * @param WP_REST_Request $request REST request object.
     * @param bool            $notify_auth_server Whether to notify the auth server about the disconnection. Defaults to false to preserve existing behavior.
     *
     * @since 1.1.3 Added $notify_auth_server parameter to allow for user-initiated disconnections.
     *
     * @return WP_REST_Response REST response object.
     */
    public function disconnect( $request, $notify_auth_server = false ) {

        // Notify the auth server about the disconnection (only when explicitly requested, e.g., user-initiated disconnect).
        if ( $notify_auth_server ) {
            $this->notify_auth_server_disconnect();
        }

        // Clear plan data and unschedule plan fetch tasks.
        $plan_manager = Plan_Manager::instance();
        $plan_manager->clear_plan_data();
        $plan_manager->unschedule_tasks();

        // Clear agents cache.
        delete_transient( 'storeagent_ai_agents' );

        Connect_Class::update_consumer_secret( null );
        Connect_Class::update_consumer_key( null );
        Connect_Class::update_consumer_key_id( 0 );

        return $this->rest_response( array( 'message' => esc_html__( 'StoreAgent disconnected!', 'storeagent-ai-for-woocommerce' ) ), $request );
    }

    /**
     * Notify the auth server about the disconnection.
     *
     * @since 1.0.0
     * @return void
     */
    private function notify_auth_server_disconnect() {

        $consumer_key    = Connect_Class::get_consumer_key();
        $consumer_secret = Connect_Class::get_consumer_secret();
        $domain          = wp_parse_url( get_home_url(), PHP_URL_HOST );

        // Skip if we don't have the necessary data to notify the auth server.
        if ( empty( $consumer_key ) || empty( $consumer_secret ) || empty( $domain ) ) {
            return;
        }

        // Use the same pattern as the auth token endpoint: get_storeagent_base_url( 'api' ) . '/storeagent/v1/...'.
        $auth_server_url = Helper::get_storeagent_base_url( 'api' ) . '/storeagent/v1/auth/disconnect';

        $params = array(
            'body'    => wp_json_encode(
                array(
                    'site_domain' => $domain,
                )
            ),
            'timeout' => 30,
            'headers' => array(
                'Content-Type'  => 'application/json;charset=' . get_bloginfo( 'charset' ),
                'Authorization' => 'Basic ' . base64_encode( $consumer_key . ':' . $consumer_secret ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
            ),
        );

        $response = wp_remote_post( esc_url_raw( $auth_server_url ), $params );

        // Log errors but don't fail the disconnect if the auth server call fails.
        if ( is_wp_error( $response ) ) {
            wc_get_logger()->debug(
                sprintf(
                    'StoreAgent Auth Disconnect Notification Error: %s',
                    $response->get_error_message()
                ),
                array( 'source' => 'storeagent-ai-for-woocommerce' )
            );
        } else {
            $response_code = wp_remote_retrieve_response_code( $response );
            if ( $response_code < 200 || $response_code >= 300 ) {
                $response_body = wp_remote_retrieve_body( $response );
                wc_get_logger()->debug(
                    sprintf(
                        'StoreAgent Auth Disconnect Notification Warning: Response code %d. Response: %s',
                        $response_code,
                        $response_body
                    ),
                    array( 'source' => 'storeagent-ai-for-woocommerce' )
                );
            }
        }
    }

    /**
     * Webhook handler.
     *
     * @param WP_REST_Request $request REST request object.
     *
     * @return WP_REST_Response
     */
    public function disconnect_webhook( $request ) {

        // Don't notify the auth server since this webhook is called by the auth server itself.
        // Using default false preserves existing behavior.
        return $this->disconnect( $request );
    }
}
