<?php
/**
 * ms-chat registration, connect/disconnect, and signed deep-link handling.
 */

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

class Rank_Ms_Chat {

    const OPTION_AGENT_TOKEN          = 'rank_ms_chat_agent_token';
    const OPTION_RESOURCE_ID          = 'rank_ms_chat_resource_id';
    const OPTION_LINKED_AT            = 'rank_ms_chat_linked_at';
    const OPTION_AGENT_SERVICE_SECRET = 'rank_ms_chat_agent_service_secret';
    const OPTION_LAST_REGISTER        = 'rank_ms_chat_last_register';

    /**
     * Initialize hooks.
     */
    public static function init() {
        add_action( 'update_option_rank_api_key', array( __CLASS__, 'on_api_key_updated' ), 20, 3 );
        add_action( 'rank_ms_chat_daily_register', array( __CLASS__, 'register' ) );
        add_action( 'wp_ajax_rank_ms_chat_connect', array( __CLASS__, 'ajax_connect' ) );
        add_action( 'wp_ajax_rank_ms_chat_disconnect', array( __CLASS__, 'ajax_disconnect' ) );
    }

    /**
     * Registry base URL with optional path.
     *
     * @param string $path API path.
     * @return string
     */
    public static function registry_url( $path = '' ) {
        $base = apply_filters( 'rank_ms_chat_registry_url', untrailingslashit( rank_get_api_base_url() ) . '/ms-chat' );
        $base = untrailingslashit( $base );

        if ( empty( $path ) ) {
            return $base;
        }

        return $base . '/' . ltrim( $path, '/' );
    }

    /**
     * Schedule daily registration cron.
     */
    public static function schedule_cron() {
        if ( ! wp_next_scheduled( 'rank_ms_chat_daily_register' ) ) {
            wp_schedule_event( time(), 'daily', 'rank_ms_chat_daily_register' );
        }
    }

    /**
     * Clear daily registration cron.
     */
    public static function clear_cron() {
        wp_clear_scheduled_hook( 'rank_ms_chat_daily_register' );
    }

    /**
     * Register site with jetforce-wp (deduped within 20h when unchanged).
     *
     * @param bool $force Skip dedup fingerprint check.
     */
    public static function register( $force = false ) {
        $api_key = rank_get_api_key();
        if ( empty( $api_key ) ) {
            return;
        }

        $payload = array(
            'site_url'       => home_url(),
            'plugin_version' => rank_get_plugin_version(),
            'wp_version'     => get_bloginfo( 'version' ),
            'php_version'    => PHP_VERSION,
        );

        $fingerprint = md5( wp_json_encode( $payload ) );
        $last        = get_option( self::OPTION_LAST_REGISTER, array() );

        if (
            ! $force
            && ! empty( $last['fingerprint'] )
            && $last['fingerprint'] === $fingerprint
            && ( time() - (int) $last['at'] ) < 20 * HOUR_IN_SECONDS
        ) {
            return;
        }

        $response = wp_remote_post(
            self::registry_url( '/wp/register' ),
            array(
                'headers' => array(
                    'Authorization' => 'Bearer ' . $api_key,
                    'Content-Type'  => 'application/json',
                ),
                'body'    => wp_json_encode( $payload ),
                'timeout' => 15,
            )
        );

        if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) === 200 ) {
            update_option(
                self::OPTION_LAST_REGISTER,
                array(
                    'fingerprint' => $fingerprint,
                    'at'          => time(),
                ),
                false
            );
        }
    }

    /**
     * Unregister site on plugin deactivation.
     */
    public static function unregister() {
        $api_key = rank_get_api_key();
        if ( empty( $api_key ) ) {
            return;
        }

        wp_remote_post(
            self::registry_url( '/wp/unregister' ),
            array(
                'headers' => array(
                    'Authorization' => 'Bearer ' . $api_key,
                    'Content-Type'  => 'application/json',
                ),
                'body'    => wp_json_encode( array( 'site_url' => home_url() ) ),
                'timeout' => 10,
            )
        );

        delete_option( self::OPTION_LAST_REGISTER );
    }

    /**
     * Trigger registration when API key is saved.
     *
     * @param mixed  $old_value Old option value.
     * @param mixed  $value     New option value.
     * @param string $option    Option name.
     */
    public static function on_api_key_updated( $old_value, $value, $option ) {
        unset( $option );
        if ( ! empty( $value ) ) {
            self::register( true );
        }
    }

    /**
     * Service secret for ms-chat → WP agent calls.
     *
     * Provisioned automatically on Connect (from jetforce-wp confirm response).
     * wp-config / env overrides are optional for local or ops use only.
     *
     * @return string
     */
    public static function get_agent_service_secret() {
        if ( defined( 'RANK_MS_CHAT_AGENT_SECRET' ) && RANK_MS_CHAT_AGENT_SECRET ) {
            return RANK_MS_CHAT_AGENT_SECRET;
        }

        $stored = get_option( self::OPTION_AGENT_SERVICE_SECRET, '' );
        if ( is_string( $stored ) && $stored !== '' ) {
            return $stored;
        }

        $env = getenv( 'MS_CHAT_AGENT_SECRET' );
        if ( $env ) {
            return $env;
        }

        return (string) apply_filters( 'rank_ms_chat_agent_secret', '' );
    }

    /**
     * Extract agent service secret from jetforce-wp confirm response.
     *
     * @param array|null $body Decoded JSON body.
     * @return string
     */
    private static function parse_agent_secret_from_confirm( $body ) {
        if ( ! is_array( $body ) ) {
            return '';
        }

        foreach ( array( 'agent_secret', 'ms_chat_agent_secret', 'agent_service_secret' ) as $key ) {
            if ( ! empty( $body[ $key ] ) && is_string( $body[ $key ] ) ) {
                return $body[ $key ];
            }
        }

        return '';
    }

    /**
     * Whether ms-chat is connected for this site.
     *
     * @return bool
     */
    public static function is_connected() {
        return ! empty( get_option( self::OPTION_LINKED_AT ) )
            && ! empty( get_option( self::OPTION_AGENT_TOKEN ) )
            && ! empty( get_option( self::OPTION_RESOURCE_ID ) );
    }

    /**
     * Parse signed deep-link state from the current request.
     *
     * @return array|null Verified state or null.
     */
    public static function parse_state() {
        if ( empty( $_GET['ms_chat_state'] ) ) {
            return null;
        }

        $raw = sanitize_text_field( wp_unslash( $_GET['ms_chat_state'] ) );
        return self::verify_state( $raw );
    }

    /**
     * Verify signed state via jetforce-wp.
     *
     * @param string $raw Raw state token.
     * @return array|null Verified payload or null.
     */
    public static function verify_state( $raw ) {
        if ( empty( $raw ) ) {
            return null;
        }

        $api_key = rank_get_api_key();
        if ( empty( $api_key ) ) {
            return null;
        }

        $response = wp_remote_post(
            self::registry_url( '/verify-state' ),
            array(
                'headers' => array(
                    'Authorization' => 'Bearer ' . $api_key,
                    'Content-Type'  => 'application/json',
                ),
                'body'    => wp_json_encode( array( 'state' => $raw ) ),
                'timeout' => 15,
            )
        );

        if ( is_wp_error( $response ) ) {
            return null;
        }

        $code = wp_remote_retrieve_response_code( $response );
        if ( $code !== 200 ) {
            return null;
        }

        $body = json_decode( wp_remote_retrieve_body( $response ), true );
        if ( ! is_array( $body ) || empty( $body['valid'] ) ) {
            return null;
        }

        $state = isset( $body['state'] ) && is_array( $body['state'] ) ? $body['state'] : $body;

        if ( empty( $state['resourceId'] ) && ! empty( $state['resource_id'] ) ) {
            $state['resourceId'] = $state['resource_id'];
        }
        if ( empty( $state['returnUrl'] ) && ! empty( $state['return_url'] ) ) {
            $state['returnUrl'] = $state['return_url'];
        }

        return $state;
    }

    /**
     * AJAX: connect ms-chat agent.
     */
    public static function ajax_connect() {
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( array( 'message' => 'Permission denied.' ), 403 );
        }

        if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'rank_ajax_nonce' ) ) {
            wp_send_json_error( array( 'message' => 'Security check failed.' ), 403 );
        }

        $api_key = rank_get_api_key();
        if ( empty( $api_key ) ) {
            wp_send_json_error( array( 'message' => 'API key is required before connecting ms-chat.' ), 400 );
        }

        $verified_state = null;
        $raw_state      = isset( $_POST['ms_chat_state'] ) ? sanitize_text_field( wp_unslash( $_POST['ms_chat_state'] ) ) : '';

        if ( ! empty( $raw_state ) ) {
            $verified_state = self::verify_state( $raw_state );
            if ( null === $verified_state ) {
                wp_send_json_error( array( 'message' => 'Invalid or expired connection request. Please try again from ms-chat.' ), 400 );
            }
        }

        $resource_id = '';
        if ( $verified_state && ! empty( $verified_state['resourceId'] ) ) {
            $resource_id = sanitize_text_field( $verified_state['resourceId'] );
        } elseif ( ! empty( $_POST['resource_id'] ) ) {
            $resource_id = sanitize_text_field( wp_unslash( $_POST['resource_id'] ) );
        }

        if ( empty( $resource_id ) ) {
            wp_send_json_error( array( 'message' => 'Resource ID is required.' ), 400 );
        }

        $agent_token      = wp_generate_password( 64, false );
        $agent_token_hash = hash( 'sha256', $agent_token );

        $confirm_body = array(
            'resource_id'      => $resource_id,
            'site_url'         => ( $verified_state && ! empty( $verified_state['siteUrl'] ) )
                ? $verified_state['siteUrl']
                : home_url(),
            'agent_token'      => $agent_token,
            'agent_token_hash' => $agent_token_hash,
        );

        if ( ! empty( $raw_state ) ) {
            $confirm_body['ms_chat_state'] = $raw_state;
        }

        $response = wp_remote_post(
            self::registry_url( '/confirm' ),
            array(
                'headers' => array(
                    'Authorization' => 'Bearer ' . $api_key,
                    'Content-Type'  => 'application/json',
                ),
                'body'    => wp_json_encode( $confirm_body ),
                'timeout' => 15,
            )
        );

        if ( is_wp_error( $response ) ) {
            wp_send_json_error( array( 'message' => $response->get_error_message() ), 500 );
        }

        $code = wp_remote_retrieve_response_code( $response );
        if ( $code < 200 || $code >= 300 ) {
            $body    = json_decode( wp_remote_retrieve_body( $response ), true );
            $message = '';
            if ( is_array( $body ) ) {
                if ( ! empty( $body['message'] ) && is_string( $body['message'] ) ) {
                    $message = $body['message'];
                } elseif ( ! empty( $body['error'] ) && is_string( $body['error'] ) ) {
                    $message = $body['error'];
                }
            }
            if ( $message === '' ) {
                $message = 'Failed to confirm ms-chat connection.';
            }
            wp_send_json_error( array( 'message' => $message ), $code );
        }

        update_option( self::OPTION_AGENT_TOKEN, $agent_token, false );
        update_option( self::OPTION_RESOURCE_ID, $resource_id, false );
        update_option( self::OPTION_LINKED_AT, time(), false );

        $confirm_json         = json_decode( wp_remote_retrieve_body( $response ), true );
        $agent_service_secret = self::parse_agent_secret_from_confirm( $confirm_json );
        if ( $agent_service_secret !== '' ) {
            update_option( self::OPTION_AGENT_SERVICE_SECRET, $agent_service_secret, false );
        } else {
            delete_option( self::OPTION_AGENT_SERVICE_SECRET );
        }

        $response_data = array( 'message' => 'ms-chat connected successfully.' );
        if ( $agent_service_secret === '' ) {
            $response_data['warning'] = 'Connected, but agent write tools need a reconnect after the ms-chat backend is updated.';
        }

        $return_url = '';
        if ( $verified_state && ! empty( $verified_state['returnUrl'] ) ) {
            $return_url = esc_url_raw( $verified_state['returnUrl'] );
        } elseif ( is_array( $confirm_json ) && ! empty( $confirm_json['return_url'] ) ) {
            $return_url = esc_url_raw( $confirm_json['return_url'] );
        }

        if ( ! empty( $return_url ) ) {
            $response_data['redirect_url'] = add_query_arg( 'linked', 'true', $return_url );
        }

        wp_send_json_success( $response_data );
    }

    /**
     * AJAX: disconnect ms-chat agent.
     */
    public static function ajax_disconnect() {
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( array( 'message' => 'Permission denied.' ), 403 );
        }

        if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'rank_ajax_nonce' ) ) {
            wp_send_json_error( array( 'message' => 'Security check failed.' ), 403 );
        }

        $api_key     = rank_get_api_key();
        $resource_id = get_option( self::OPTION_RESOURCE_ID, '' );

        if ( ! empty( $api_key ) && ! empty( $resource_id ) ) {
            wp_remote_post(
                self::registry_url( '/revoke' ),
                array(
                    'headers' => array(
                        'Authorization' => 'Bearer ' . $api_key,
                        'Content-Type'  => 'application/json',
                    ),
                    'body'    => wp_json_encode(
                        array(
                            'resource_id' => $resource_id,
                            'site_url'    => home_url(),
                        )
                    ),
                    'timeout' => 10,
                )
            );
        }

        delete_option( self::OPTION_AGENT_TOKEN );
        delete_option( self::OPTION_RESOURCE_ID );
        delete_option( self::OPTION_LINKED_AT );
        delete_option( self::OPTION_AGENT_SERVICE_SECRET );

        wp_send_json_success( array( 'message' => 'ms-chat disconnected.' ) );
    }

    /**
     * Clear all ms-chat link options (used on disconnect).
     */
    public static function clear_link_options() {
        delete_option( self::OPTION_AGENT_TOKEN );
        delete_option( self::OPTION_RESOURCE_ID );
        delete_option( self::OPTION_LINKED_AT );
        delete_option( self::OPTION_AGENT_SERVICE_SECRET );
    }
}
