<?php
/**
 * ms-chat agent REST API routes and authentication.
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class Rank_Ms_Chat_Agent {

    const NAMESPACE = 'rank-ai/v1';

    /**
     * Initialize REST routes.
     */
    public static function init() {
        add_action( 'rest_api_init', array( __CLASS__, 'register_routes' ) );
    }

    /**
     * Register agent routes.
     */
    public static function register_routes() {
        $routes = array(
            array(
                'route'    => '/agent/connection/status',
                'methods'  => 'GET',
                'callback' => array( __CLASS__, 'connection_status' ),
            ),
            array(
                'route'    => '/agent/health/job-status',
                'methods'  => 'GET',
                'callback' => array( __CLASS__, 'health_job_status' ),
            ),
            array(
                'route'    => '/agent/health/fix/start',
                'methods'  => 'POST',
                'callback' => array( __CLASS__, 'health_fix_start' ),
            ),
            array(
                'route'    => '/agent/health/fix/cancel',
                'methods'  => 'POST',
                'callback' => array( __CLASS__, 'health_fix_cancel' ),
            ),
            array(
                'route'    => '/agent/page-booster/status',
                'methods'  => 'GET',
                'callback' => array( __CLASS__, 'booster_status' ),
            ),
            array(
                'route'    => '/agent/page-booster/start',
                'methods'  => 'POST',
                'callback' => array( __CLASS__, 'booster_start' ),
            ),
            array(
                'route'    => '/agent/page-booster/push-live',
                'methods'  => 'POST',
                'callback' => array( __CLASS__, 'booster_push_live' ),
            ),
            array(
                'route'    => '/agent/writer/upload',
                'methods'  => 'POST',
                'callback' => array( __CLASS__, 'writer_upload' ),
            ),
        );

        foreach ( $routes as $route ) {
            register_rest_route(
                self::NAMESPACE,
                $route['route'],
                array(
                    'methods'             => $route['methods'],
                    'callback'            => $route['callback'],
                    'permission_callback' => array( __CLASS__, 'verify_agent_request' ),
                )
            );
        }
    }

    /**
     * Agent service secret (provisioned on Connect; optional wp-config override).
     *
     * @return string
     */
    public static function get_agent_secret() {
        return Rank_Ms_Chat::get_agent_service_secret();
    }

    /**
     * Verify agent request headers and HMAC signature.
     *
     * @param WP_REST_Request $request Request object.
     * @return true|WP_Error
     */
    public static function verify_agent_request( WP_REST_Request $request ) {
        if ( ! Rank_Ms_Chat::is_connected() ) {
            return new WP_Error( 'not_connected', 'Site is not connected to ms-chat.', array( 'status' => 403 ) );
        }

        $secret = self::get_agent_secret();
        if ( empty( $secret ) ) {
            return new WP_Error(
                'not_provisioned',
                'Agent service secret was not provisioned. Disconnect and connect ms-chat again.',
                array( 'status' => 403 )
            );
        }

        $header_secret = (string) $request->get_header( 'X-MS-Agent-Secret' );
        if ( ! hash_equals( $secret, $header_secret ) ) {
            return new WP_Error( 'unauthorized', 'Invalid agent secret.', array( 'status' => 401 ) );
        }

        $site_token   = (string) get_option( Rank_Ms_Chat::OPTION_AGENT_TOKEN, '' );
        $header_token = (string) $request->get_header( 'X-MS-Site-Token' );
        if ( empty( $site_token ) || ! hash_equals( $site_token, $header_token ) ) {
            return new WP_Error( 'unauthorized', 'Invalid site token.', array( 'status' => 401 ) );
        }

        $resource_id     = (string) get_option( Rank_Ms_Chat::OPTION_RESOURCE_ID, '' );
        $header_resource = (string) $request->get_header( 'X-MS-Resource-Id' );
        if ( empty( $resource_id ) || ! hash_equals( $resource_id, $header_resource ) ) {
            return new WP_Error( 'unauthorized', 'Invalid resource ID.', array( 'status' => 401 ) );
        }

        $timestamp = (int) $request->get_header( 'X-MS-Timestamp' );
        if ( empty( $timestamp ) || abs( time() - $timestamp ) > 5 * MINUTE_IN_SECONDS ) {
            return new WP_Error( 'unauthorized', 'Invalid or expired timestamp.', array( 'status' => 401 ) );
        }

        $signature = (string) $request->get_header( 'X-MS-Signature' );
        $route     = $request->get_route();
        $method    = strtoupper( $request->get_method() );
        $expected  = hash_hmac( 'sha256', $timestamp . $method . $route, $site_token );

        if ( ! hash_equals( $expected, $signature ) ) {
            return new WP_Error( 'unauthorized', 'Invalid signature.', array( 'status' => 401 ) );
        }

        return true;
    }

    /**
     * GET /agent/connection/status
     *
     * @return WP_REST_Response
     */
    public static function connection_status() {
        return new WP_REST_Response(
            array(
                'confirmed'           => Rank_Ms_Chat::is_connected(),
                'plugin_version'      => rank_get_plugin_version(),
                'resource_id'         => get_option( Rank_Ms_Chat::OPTION_RESOURCE_ID, '' ),
                'linked_at'           => (int) get_option( Rank_Ms_Chat::OPTION_LINKED_AT, 0 ),
                'site_url'            => home_url(),
                // Issue types this plugin build can auto-fix — the agent checks
                // this before offering or starting a health fix.
                'fixable_issue_types' => function_exists( 'rank_get_fixable_issue_types' )
                    ? rank_get_fixable_issue_types()
                    : array(),
            ),
            200
        );
    }

    /**
     * GET /agent/health/job-status
     *
     * @param WP_REST_Request $request Request.
     * @return WP_REST_Response|WP_Error
     */
    public static function health_job_status( WP_REST_Request $request ) {
        $batch_id = sanitize_text_field( (string) $request->get_param( 'batch_id' ) );
        $result   = Rank_Ms_Chat_Services::health_job_status( $batch_id );

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

        return new WP_REST_Response( $result, 200 );
    }

    /**
     * POST /agent/health/fix/start
     *
     * @param WP_REST_Request $request Request.
     * @return WP_REST_Response|WP_Error
     */
    public static function health_fix_start( WP_REST_Request $request ) {
        $batch_id   = sanitize_key( (string) $request->get_param( 'batch_id' ) );
        $issue_type = sanitize_key( (string) $request->get_param( 'issue_type' ) );
        $result     = Rank_Ms_Chat_Services::health_fix_start( $batch_id, $issue_type );

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

        return new WP_REST_Response( $result, 200 );
    }

    /**
     * POST /agent/health/fix/cancel
     *
     * @param WP_REST_Request $request Request.
     * @return WP_REST_Response|WP_Error
     */
    public static function health_fix_cancel( WP_REST_Request $request ) {
        $batch_id = sanitize_key( (string) $request->get_param( 'batch_id' ) );
        $result   = Rank_Ms_Chat_Services::health_fix_cancel( $batch_id );

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

        return new WP_REST_Response( $result, 200 );
    }

    /**
     * GET /agent/page-booster/status
     *
     * @param WP_REST_Request $request Request.
     * @return WP_REST_Response|WP_Error
     */
    public static function booster_status( WP_REST_Request $request ) {
        $session_id = sanitize_text_field( (string) $request->get_param( 'session_id' ) );
        $result     = Rank_Ms_Chat_Services::booster_status( $session_id );

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

        return new WP_REST_Response( $result, 200 );
    }

    /**
     * POST /agent/page-booster/start
     *
     * @param WP_REST_Request $request Request.
     * @return WP_REST_Response|WP_Error
     */
    public static function booster_start( WP_REST_Request $request ) {
        $rows = $request->get_param( 'rows' );
        if ( ! is_array( $rows ) ) {
            return new WP_Error( 'invalid_rows', 'rows must be an array.', array( 'status' => 400 ) );
        }

        $result = Rank_Ms_Chat_Services::booster_start( $rows );

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

        return new WP_REST_Response( $result, 200 );
    }

    /**
     * POST /agent/page-booster/push-live
     *
     * @param WP_REST_Request $request Request.
     * @return WP_REST_Response|WP_Error
     */
    public static function booster_push_live( WP_REST_Request $request ) {
        $job_id = absint( $request->get_param( 'job_id' ) );
        $result = Rank_Ms_Chat_Services::booster_push_live( $job_id );

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

        return new WP_REST_Response( $result, 200 );
    }

    /**
     * POST /agent/writer/upload
     *
     * @param WP_REST_Request $request Request.
     * @return WP_REST_Response|WP_Error
     */
    public static function writer_upload( WP_REST_Request $request ) {
        $article_ids = $request->get_param( 'article_ids' );
        if ( ! is_array( $article_ids ) ) {
            $article_ids = $request->get_param( 'articleIds' );
        }

        $result = Rank_Ms_Chat_Services::writer_upload( is_array( $article_ids ) ? $article_ids : array() );

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

        return new WP_REST_Response( $result, 200 );
    }
}
