<?php

namespace Pagup\MassPingTool\Controllers;

use Pagup\MassPingTool\Traits\Helpers;
class PingController {
    use Helpers;
    public $log = [];

    public $post_title;

    public $post_url;

    /**
     * Modified version of WordPress "generic_ping" function.
     * @param int $post_id The post ID.
     */
    public function send_ping( int $post_id = 0 ) {
        if ( $post_id == 0 ) {
            return;
        }
        $post = get_post( $post_id );
        $mass_ping_log = get_option( 'mass_ping_log' );
        $log = ( !empty( $mass_ping_log ) ? $mass_ping_log : [] );
        if ( isset( $post ) ) {
            // Perform pingback
            delete_post_meta( $post_id, '_pingme' );
            pingback( $post->post_content, $post_id );
            // Perform enclosure
            delete_post_meta( $post_id, '_encloseme' );
            do_enclose( $post->post_content, $post_id );
            // Perform trackback
            delete_post_meta( $post_id, '_trackbackme' );
            do_trackbacks( $post_id );
            $services = $this->services();
            foreach ( $services as $service ) {
                $service = trim( $service );
                if ( '' !== $service ) {
                    $this->weblog_ping( $post_id, $service );
                    $this->save_log( $post_id, $this->log );
                }
            }
        }
        return $post_id;
    }

    /**
     * Modified version of WordPress weblog_ping function.
     * @param string $server Host of blog to connect to.
     * @param string $path Path to send the ping.
     */
    public function weblog_ping( $post_id, $server = '', $path = '' ) {
        include_once ABSPATH . WPINC . '/class-IXR.php';
        include_once ABSPATH . WPINC . '/class-wp-http-ixr-client.php';
        // Using a timeout of 3 seconds should be enough to cover slow servers.
        $client = new \WP_HTTP_IXR_Client($server, ( !strlen( trim( $path ) ) || '/' === $path ? false : $path ));
        $client->timeout = 3;
        $client->useragent .= ' -- WordPress/' . get_bloginfo( 'version' );
        // When set to true, this outputs debug messages by itself.
        $client->debug = false;
        // Data for $client->query
        $post_title = get_the_title( $post_id );
        $post_title = ( $post_title != "" ? $post_title : get_option( 'blogname' ) );
        $home = trailingslashit( home_url() );
        $post_url = get_permalink( $post_id );
        $post_url = ( $post_url != false ? $post_url : $home );
        $rss_url = get_bloginfo( 'rss2_url' );
        if ( $client->query(
            'weblogUpdates.extendedPing',
            $post_title,
            $post_url,
            $rss_url
        ) ) {
            $this->log = [
                'server'  => $server,
                'message' => "Successfully pinged",
                'time'    => time(),
                'status'  => 'success',
            ];
        } elseif ( $client->query( 'weblogUpdates.ping', $post_title, $post_url ) ) {
            $this->log = [
                'server'  => $server,
                'message' => "Successfully pinged",
                'time'    => time(),
                'status'  => 'success',
            ];
        } else {
            $this->log = [
                'server'  => $server,
                'message' => "Ping failed. Error: {$client->error->message}",
                'time'    => time(),
                'status'  => 'failed',
            ];
        }
    }

    public function api( $url ) {
        $args = array(
            'timeout'     => 30,
            'redirection' => 5,
            'httpversion' => '1.1',
            'user-agent'  => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
            'headers'     => array(
                'Accept'           => 'application/json, text/plain, */*',
                'Accept-Language'  => 'en-US,en;q=0.9',
                'Accept-Encoding'  => 'gzip, deflate, br',
                'Cache-Control'    => 'no-cache',
                'Pragma'           => 'no-cache',
                'Sec-Fetch-Dest'   => 'empty',
                'Sec-Fetch-Mode'   => 'cors',
                'Sec-Fetch-Site'   => 'cross-site',
                'X-Requested-With' => 'XMLHttpRequest',
            ),
            'sslverify'   => true,
            'blocking'    => true,
        );
        $response = wp_remote_get( $url, $args );
        if ( is_wp_error( $response ) ) {
            error_log( "MPT API Error: " . $response->get_error_message() );
            return false;
        }
        $response_code = wp_remote_retrieve_response_code( $response );
        $response_body = wp_remote_retrieve_body( $response );
        // Log for debugging
        error_log( "MPT API Response Code: {$response_code}" );
        error_log( "MPT API Response Length: " . strlen( $response_body ) );
        if ( $response_code !== 200 ) {
            error_log( "MPT API Non-200 Response: Code {$response_code}" );
            error_log( "MPT API Response Body: " . substr( $response_body, 0, 500 ) );
            return false;
        }
        $json_data = json_decode( $response_body );
        if ( json_last_error() !== JSON_ERROR_NONE ) {
            error_log( "MPT API JSON Error: " . json_last_error_msg() );
            error_log( "MPT API Raw Response: " . substr( $response_body, 0, 200 ) );
            return false;
        }
        return $json_data;
    }

    /**
     * Checks if there are any new services available from the API
     *
     * If there are new services, it will update the options
     *
     * @return void
     */
    public function check_services() {
        $api = $this->api( 'https://agenceseo.ca/wp-json/mass-ping/v1/services' );
        $last_synced = get_option( 'mpt-last-update' );
        if ( isset( $last_synced ) && !empty( $last_synced ) ) {
            if ( $api->updated_at > $last_synced ) {
                update_option( 'mpt-update-require', true );
            }
        } else {
            update_option( 'mpt-ping-services', $api );
            update_option( "mpt-last-update", time() );
            update_option( 'mpt-update-require', false );
        }
    }

}
