<?php
/**
 * Plugin Name: Managed Automatic Updates Monitor
 * Description: Enables automatic plugin/theme updates, self-registers securely with a central monitor, and reports update failures/heartbeats.
 * Version: 3.3.0
 * LWD Type: mu-plugin
 * LWD Install: existing-only
 * LWD File: lwd-update-monitor.php
 * Requires PHP: 7.4.0
 * Requires at least: 6.0

 */

defined( 'ABSPATH' ) || exit;

const MAUM_PLUGIN_VERSION = '3.3.0';
const MAUM_SCHEMA_VERSION = 6;
const MAUM_CREDENTIALS_OPTION = 'maum_credentials_v2';
const MAUM_QUEUE_OPTION = 'maum_pending_events_v2';
const MAUM_STATUS_OPTION = 'maum_status_v2';
const MAUM_HEARTBEAT_HOOK = 'maum_daily_heartbeat_v2';
const MAUM_RETRY_HOOK = 'maum_retry_pending_events_v2';
const MAUM_INVENTORY_HOOK = 'maum_weekly_inventory_v3';
const MAUM_LAST_INVENTORY_OPTION = 'maum_last_inventory_v3';
const MAUM_MAX_QUEUE_SIZE = 25;
const MAUM_REQUEST_TIMEOUT = 12;
const MAUM_MAX_RESPONSE_BYTES = 8192;

/*
 * EDIT THESE TWO URLS ONCE before deploying this same MU-plugin to your sites.
 * They must be the final canonical HTTPS URLs and must not redirect.
 */
if ( ! defined( 'MAUM_REGISTER_ENDPOINT' ) ) {
    define( 'MAUM_REGISTER_ENDPOINT', 'https://hub.linkweb.ca/wp-monitor/register.php' );
}
if ( ! defined( 'MAUM_RECEIVER_ENDPOINT' ) ) {
    define( 'MAUM_RECEIVER_ENDPOINT', 'https://hub.linkweb.ca/wp-monitor/receiver.php' );
}

add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );

add_action( 'init', static function (): void {
    if ( ! wp_next_scheduled( MAUM_HEARTBEAT_HOOK ) ) {
        wp_schedule_event( time() + 300, 'daily', MAUM_HEARTBEAT_HOOK );
    }
    if ( ! wp_next_scheduled( MAUM_RETRY_HOOK ) ) {
        wp_schedule_event( time() + 600, 'hourly', MAUM_RETRY_HOOK );
    }
    if ( ! wp_next_scheduled( MAUM_INVENTORY_HOOK ) ) {
        wp_schedule_event( time() + wp_rand( 600, 7200 ), 'daily', MAUM_INVENTORY_HOOK );
    }
} );

add_action( MAUM_HEARTBEAT_HOOK, static function (): void {
    if ( maum_is_registered() ) {
        maum_enqueue_and_send( array(
            'event_type' => 'heartbeat',
            'summary' => array( 'message' => 'Scheduled monitor heartbeat.' ),
        ) );
    }
} );
add_action( MAUM_RETRY_HOOK, 'maum_flush_queue' );
add_action( MAUM_INVENTORY_HOOK, static function (): void {
    if ( ! maum_is_registered() ) return;
    $last = (int) get_option( MAUM_LAST_INVENTORY_OPTION, 0 );
    if ( $last > 0 && ( time() - $last ) < ( 6 * DAY_IN_SECONDS ) ) return;
    if ( maum_send_inventory() ) update_option( MAUM_LAST_INVENTORY_OPTION, time(), false );
} );

function maum_build_inventory(): array {
    if ( ! function_exists( 'get_plugins' ) ) require_once ABSPATH . 'wp-admin/includes/plugin.php';
    $items = array();
    $active_plugins = array_flip( (array) get_option( 'active_plugins', array() ) );
    if ( is_multisite() ) {
        foreach ( array_keys( (array) get_site_option( 'active_sitewide_plugins', array() ) ) as $network_file ) $active_plugins[ $network_file ] = true;
    }
    foreach ( get_plugins() as $file => $data ) {
        $items[] = array(
            'type' => 'plugin', 'key' => strtolower( sanitize_text_field( $file ) ),
            'name' => sanitize_text_field( (string) ( $data['Name'] ?? $file ) ),
            'version' => sanitize_text_field( (string) ( $data['Version'] ?? '' ) ),
            'active' => isset( $active_plugins[ $file ] ), 'auto_update' => true,
        );
    }
    $active_theme = get_stylesheet();
    foreach ( wp_get_themes() as $slug => $theme ) {
        $items[] = array(
            'type' => 'theme', 'key' => strtolower( sanitize_text_field( (string) $slug ) ),
            'name' => sanitize_text_field( (string) $theme->get( 'Name' ) ),
            'version' => sanitize_text_field( (string) $theme->get( 'Version' ) ),
            'active' => (string) $slug === (string) $active_theme, 'auto_update' => true,
        );
    }
    return $items;
}
function maum_send_inventory(): bool {
    return maum_enqueue_and_send( array(
        'event_type' => 'inventory',
        'summary' => array( 'message' => 'Installed plugin/theme inventory snapshot.' ),
        'inventory' => maum_build_inventory(),
    ) );
}

add_action( 'automatic_updates_complete', static function ( $update_results ): void {
    if ( ! maum_is_registered() || ! is_array( $update_results ) ) {
        return;
    }
    $attempted = array( 'plugin' => 0, 'theme' => 0 );
    $failures = array();
    $outcomes = array();
    foreach ( array( 'plugin', 'theme' ) as $type ) {
        if ( empty( $update_results[ $type ] ) || ! is_array( $update_results[ $type ] ) ) continue;
        foreach ( $update_results[ $type ] as $update ) {
            $attempted[ $type ]++;
            $success = is_object( $update ) && isset( $update->result ) && true === $update->result;
            if ( $success ) {
                $outcomes[] = maum_normalize_outcome( $type, $update, 'success' );
                continue;
            }
            $failure = maum_normalize_failure( $type, $update );
            $failures[] = $failure;
            $outcomes[] = array(
                'type' => $failure['type'],
                'name' => $failure['name'],
                'slug' => $failure['slug'],
                'from_version' => $failure['from_version'],
                'to_version' => $failure['to_version'],
                'status' => 'failure',
            );
        }
    }
    if ( 0 === $attempted['plugin'] && 0 === $attempted['theme'] ) return;
    $summary = array(
        'attempted_plugins' => $attempted['plugin'],
        'attempted_themes' => $attempted['theme'],
        'failure_count' => count( $failures ),
        'status' => empty( $failures ) ? 'success' : 'failure',
    );
    maum_update_status( array( 'last_update_run' => gmdate( 'c' ), 'last_update_summary' => $summary ) );
    maum_enqueue_and_send( array( 'event_type' => 'update_run', 'summary' => $summary, 'failures' => $failures, 'outcomes' => $outcomes ) );
}, 10, 1 );

function maum_normalize_failure( string $type, $update ): array {
    $failure = array(
        'type' => $type, 'name' => '', 'slug' => '', 'from_version' => '', 'to_version' => '',
        'error_codes' => array(), 'error_messages' => array(),
    );
    if ( is_object( $update ) ) {
        if ( isset( $update->name ) && is_scalar( $update->name ) ) $failure['name'] = sanitize_text_field( (string) $update->name );
        if ( isset( $update->item ) && is_object( $update->item ) ) {
            $item = $update->item;
            foreach ( array( 'slug', 'plugin', 'theme' ) as $key ) {
                if ( empty( $failure['slug'] ) && isset( $item->{$key} ) && is_scalar( $item->{$key} ) ) $failure['slug'] = sanitize_text_field( (string) $item->{$key} );
            }
            if ( isset( $item->version ) && is_scalar( $item->version ) ) $failure['from_version'] = sanitize_text_field( (string) $item->version );
            if ( isset( $item->new_version ) && is_scalar( $item->new_version ) ) $failure['to_version'] = sanitize_text_field( (string) $item->new_version );
        }
        if ( isset( $update->result ) && is_wp_error( $update->result ) ) {
            $failure['error_codes'] = array_values( array_map( 'sanitize_key', $update->result->get_error_codes() ) );
            foreach ( $update->result->get_error_messages() as $message ) {
                $failure['error_messages'][] = mb_substr( wp_strip_all_tags( (string) $message ), 0, 1000 );
            }
        } else {
            $failure['error_codes'][] = 'unknown_failure';
            $failure['error_messages'][] = 'Automatic update did not return a successful result.';
        }
    } else {
        $failure['error_codes'][] = 'invalid_result';
        $failure['error_messages'][] = 'WordPress returned an unexpected update result value.';
    }

    // Some premium updaters omit the currently installed version from the automatic-update result.
    // Resolve it locally without changing the update operation itself.
    if ( '' === $failure['from_version'] ) {
        $failure['from_version'] = maum_resolve_installed_version( $type, $failure['slug'], $failure['name'] );
    }
    return $failure;
}

function maum_normalize_outcome( string $type, $update, string $status ): array {
    $outcome = array(
        'type' => $type,
        'name' => '',
        'slug' => '',
        'from_version' => '',
        'to_version' => '',
        'status' => $status,
    );
    if ( is_object( $update ) ) {
        if ( isset( $update->name ) && is_scalar( $update->name ) ) {
            $outcome['name'] = sanitize_text_field( (string) $update->name );
        }
        if ( isset( $update->item ) && is_object( $update->item ) ) {
            $item = $update->item;
            foreach ( array( 'slug', 'plugin', 'theme' ) as $key ) {
                if ( '' === $outcome['slug'] && isset( $item->{$key} ) && is_scalar( $item->{$key} ) ) {
                    $outcome['slug'] = sanitize_text_field( (string) $item->{$key} );
                }
            }
            if ( isset( $item->version ) && is_scalar( $item->version ) ) {
                $outcome['from_version'] = sanitize_text_field( (string) $item->version );
            }
            if ( isset( $item->new_version ) && is_scalar( $item->new_version ) ) {
                $outcome['to_version'] = sanitize_text_field( (string) $item->new_version );
            }
        }
    }
    if ( '' === $outcome['from_version'] ) {
        $outcome['from_version'] = maum_resolve_installed_version( $type, $outcome['slug'], $outcome['name'] );
    }
    return $outcome;
}

function maum_resolve_installed_version( string $type, string $slug, string $name ): string {
    if ( 'theme' === $type ) {
        $theme_slug = trim( $slug );
        if ( '' !== $theme_slug ) {
            $theme = wp_get_theme( $theme_slug );
            if ( $theme->exists() ) {
                return sanitize_text_field( (string) $theme->get( 'Version' ) );
            }
        }
        return '';
    }

    if ( 'plugin' !== $type ) {
        return '';
    }
    if ( ! function_exists( 'get_plugins' ) ) {
        require_once ABSPATH . 'wp-admin/includes/plugin.php';
    }
    $plugins = get_plugins();
    $slug = trim( $slug );
    $name = trim( $name );

    if ( '' !== $slug && isset( $plugins[ $slug ]['Version'] ) ) {
        return sanitize_text_field( (string) $plugins[ $slug ]['Version'] );
    }
    $folder = '' !== $slug ? strtok( $slug, '/' ) : '';
    foreach ( $plugins as $plugin_file => $headers ) {
        if ( '' !== $folder && ( $plugin_file === $folder || 0 === strpos( $plugin_file, $folder . '/' ) ) ) {
            return sanitize_text_field( (string) ( $headers['Version'] ?? '' ) );
        }
        if ( '' !== $name && isset( $headers['Name'] ) && 0 === strcasecmp( trim( (string) $headers['Name'] ), $name ) ) {
            return sanitize_text_field( (string) ( $headers['Version'] ?? '' ) );
        }
    }
    return '';
}

function maum_credentials(): array {
    $value = get_option( MAUM_CREDENTIALS_OPTION, array() );
    return is_array( $value ) ? $value : array();
}
function maum_is_registered(): bool {
    $c = maum_credentials();
    return ! empty( $c['site_id'] ) && is_string( $c['site_id'] ) && ! empty( $c['shared_secret'] ) && is_string( $c['shared_secret'] ) && strlen( $c['shared_secret'] ) >= 64;
}
function maum_update_status( array $changes ): void {
    $status = get_option( MAUM_STATUS_OPTION, array() );
    $status = is_array( $status ) ? $status : array();
    update_option( MAUM_STATUS_OPTION, array_merge( $status, $changes ), false );
}
function maum_status(): array {
    $value = get_option( MAUM_STATUS_OPTION, array() );
    return is_array( $value ) ? $value : array();
}

function maum_register_site( string $code, string $display_name ): array {
    $code = trim( $code );
    $display_name = sanitize_text_field( $display_name );
    if ( '' === $code || '' === $display_name ) return array( false, 'Registration code and display name are required.' );
    if ( maum_is_registered() ) return array( false, 'This site is already registered.' );
    if ( 0 !== strpos( MAUM_REGISTER_ENDPOINT, 'https://' ) ) return array( false, 'Registration endpoint must use HTTPS.' );

    $body = wp_json_encode( array(
        'registration_code' => $code,
        'display_name' => mb_substr( $display_name, 0, 120 ),
        'site_url' => home_url( '/' ),
        'wordpress_version' => get_bloginfo( 'version' ),
        'php_version' => PHP_VERSION,
        'monitor_version' => MAUM_PLUGIN_VERSION,
    ), JSON_UNESCAPED_SLASHES );
    if ( false === $body ) return array( false, 'Could not encode registration request.' );

    $response = wp_safe_remote_post( MAUM_REGISTER_ENDPOINT, array(
        'timeout' => MAUM_REQUEST_TIMEOUT,
        'redirection' => 0,
        'sslverify' => true,
        'limit_response_size' => MAUM_MAX_RESPONSE_BYTES,
        'headers' => array( 'Content-Type' => 'application/json', 'Accept' => 'application/json' ),
        'body' => $body,
    ) );
    if ( is_wp_error( $response ) ) return array( false, 'Registration request failed: ' . $response->get_error_message() );
    $status = (int) wp_remote_retrieve_response_code( $response );
    $data = json_decode( wp_remote_retrieve_body( $response ), true );
    if ( 201 !== $status || ! is_array( $data ) || true !== ( $data['ok'] ?? false ) ) {
        $reason = is_array( $data ) && ! empty( $data['error'] ) ? sanitize_text_field( (string) $data['error'] ) : 'HTTP ' . $status;
        return array( false, 'Registration rejected: ' . $reason );
    }
    $site_id = sanitize_key( (string) ( $data['site_id'] ?? '' ) );
    $secret = (string) ( $data['shared_secret'] ?? '' );
    if ( '' === $site_id || ! preg_match( '/^[a-f0-9]{64}$/i', $secret ) ) return array( false, 'Registration response was invalid.' );

    update_option( MAUM_CREDENTIALS_OPTION, array(
        'site_id' => $site_id,
        'shared_secret' => $secret,
        'display_name' => sanitize_text_field( (string) ( $data['display_name'] ?? $display_name ) ),
        'registered_at' => sanitize_text_field( (string) ( $data['registered_at'] ?? gmdate( 'c' ) ) ),
        'registered_site_url' => home_url( '/' ),
    ), false );
    maum_update_status( array( 'last_success' => gmdate( 'c' ), 'last_success_detail' => 'Registration accepted.' , 'last_error' => '' ) );
    return array( true, 'Registration successful.' );
}

function maum_enqueue_and_send( array $event ): bool {
    if ( ! maum_is_registered() ) return false;
    $c = maum_credentials();
    $event = array_merge( array(
        'schema_version' => MAUM_SCHEMA_VERSION,
        'event_id' => wp_generate_uuid4(),
        'created_at' => gmdate( 'c' ),
        'site_id' => $c['site_id'],
        'site_url' => home_url( '/' ),
        'wordpress_version' => get_bloginfo( 'version' ),
        'php_version' => PHP_VERSION,
        'monitor_version' => MAUM_PLUGIN_VERSION,
    ), $event );
    $queue = get_option( MAUM_QUEUE_OPTION, array() );
    $queue = is_array( $queue ) ? $queue : array();
    $queue[] = $event;
    if ( count( $queue ) > MAUM_MAX_QUEUE_SIZE ) $queue = array_slice( $queue, -MAUM_MAX_QUEUE_SIZE );
    update_option( MAUM_QUEUE_OPTION, $queue, false );
    maum_flush_queue();
    $after = get_option( MAUM_QUEUE_OPTION, array() );
    return is_array( $after ) && empty( $after );
}

function maum_flush_queue(): void {
    if ( ! maum_is_registered() ) return;
    $queue = get_option( MAUM_QUEUE_OPTION, array() );
    if ( ! is_array( $queue ) || empty( $queue ) ) return;
    $remaining = $queue;
    foreach ( $queue as $index => $event ) {
        if ( ! is_array( $event ) || ! maum_send_event( $event ) ) break;
        unset( $remaining[ $index ] );
    }
    update_option( MAUM_QUEUE_OPTION, array_values( $remaining ), false );
}

function maum_send_event( array $event ): bool {
    $c = maum_credentials();
    if ( empty( $c['site_id'] ) || empty( $c['shared_secret'] ) ) return false;
    $body = wp_json_encode( $event, JSON_UNESCAPED_SLASHES );
    if ( false === $body ) { maum_update_status( array( 'last_error' => gmdate( 'c' ) . ' — Could not encode event.' ) ); return false; }
    try { $nonce = bin2hex( random_bytes( 16 ) ); } catch ( Exception $e ) { maum_update_status( array( 'last_error' => gmdate( 'c' ) . ' — Could not generate nonce.' ) ); return false; }
    $timestamp = (string) time();
    $signature = hash_hmac( 'sha256', $c['site_id'] . "\n" . $timestamp . "\n" . $nonce . "\n" . $body, $c['shared_secret'] );
    $response = wp_safe_remote_post( MAUM_RECEIVER_ENDPOINT, array(
        'timeout' => MAUM_REQUEST_TIMEOUT, 'redirection' => 0, 'sslverify' => true,
        'limit_response_size' => MAUM_MAX_RESPONSE_BYTES,
        'headers' => array(
            'Content-Type' => 'application/json', 'Accept' => 'application/json',
            'X-MAUM-Site-ID' => $c['site_id'], 'X-MAUM-Timestamp' => $timestamp,
            'X-MAUM-Nonce' => $nonce, 'X-MAUM-Signature' => $signature,
        ),
        'body' => $body,
    ) );
    if ( is_wp_error( $response ) ) {
        maum_update_status( array( 'last_error' => gmdate( 'c' ) . ' — ' . mb_substr( $response->get_error_message(), 0, 500 ) ) );
        return false;
    }
    $status = (int) wp_remote_retrieve_response_code( $response );
    $data = json_decode( wp_remote_retrieve_body( $response ), true );
    if ( 202 !== $status || ! is_array( $data ) || true !== ( $data['ok'] ?? false ) ) {
        $error = is_array( $data ) && ! empty( $data['error'] ) ? sanitize_text_field( (string) $data['error'] ) : 'Receiver returned HTTP ' . $status . '.';
        maum_update_status( array( 'last_error' => gmdate( 'c' ) . ' — ' . $error ) );
        return false;
    }
    maum_update_status( array(
        'last_success' => gmdate( 'c' ),
        'last_success_detail' => 'HTTP 202 — ' . sanitize_key( (string) ( $event['event_type'] ?? 'event' ) ),
        'last_error' => '',
    ) );
    return true;
}

add_action( 'admin_menu', static function (): void {
    add_management_page( 'Update Monitor', 'Update Monitor', 'manage_options', 'maum-update-monitor', 'maum_render_admin_page' );
} );

add_action( 'admin_post_maum_action', static function (): void {
    if ( ! current_user_can( 'manage_options' ) ) wp_die( 'Unauthorized.' );
    check_admin_referer( 'maum_action' );
    $action = sanitize_key( (string) ( $_POST['maum_do'] ?? '' ) );
    $message = '';
    $type = 'success';
    if ( 'register' === $action ) {
        list( $ok, $message ) = maum_register_site( sanitize_text_field( wp_unslash( (string) ( $_POST['registration_code'] ?? '' ) ) ), sanitize_text_field( wp_unslash( (string) ( $_POST['display_name'] ?? '' ) ) ) );
        $type = $ok ? 'success' : 'error';
    } elseif ( ! maum_is_registered() ) {
        $message = 'Register this site first.'; $type = 'error';
    } elseif ( 'test' === $action ) {
        $ok = maum_enqueue_and_send( array( 'event_type' => 'test', 'summary' => array( 'message' => 'Manual WordPress Admin test.' ) ) );
        $message = $ok ? 'Test event accepted by receiver.' : 'Test event queued because it could not be delivered.'; $type = $ok ? 'success' : 'error';
    } elseif ( 'heartbeat' === $action ) {
        $ok = maum_enqueue_and_send( array( 'event_type' => 'heartbeat', 'summary' => array( 'message' => 'Manual WordPress Admin heartbeat.' ) ) );
        $message = $ok ? 'Heartbeat accepted by receiver.' : 'Heartbeat queued because it could not be delivered.'; $type = $ok ? 'success' : 'error';
    } elseif ( 'inventory' === $action ) {
        $ok = maum_send_inventory();
        if ( $ok ) update_option( MAUM_LAST_INVENTORY_OPTION, time(), false );
        $message = $ok ? 'Inventory accepted by receiver.' : 'Inventory queued because it could not be delivered.'; $type = $ok ? 'success' : 'error';
    } elseif ( 'synthetic_failure' === $action ) {
        $ok = maum_enqueue_and_send( array(
            'event_type' => 'test', 'synthetic_failure' => true,
            'summary' => array( 'message' => 'Synthetic failure test.', 'status' => 'failure', 'failure_count' => 1 ),
            'failures' => array( array(
                'type' => 'plugin', 'name' => 'Synthetic Test Plugin', 'slug' => 'synthetic-test-plugin',
                'from_version' => '1.0.0', 'to_version' => '1.0.1',
                'error_codes' => array( 'synthetic_test' ),
                'error_messages' => array( 'This is a synthetic monitor test; no real update failed.' ),
            ) ),
        ) );
        $message = $ok ? 'Synthetic failure accepted; Slack should receive an alert.' : 'Synthetic failure queued because it could not be delivered.'; $type = $ok ? 'success' : 'error';
    } elseif ( 'retry' === $action ) {
        maum_flush_queue(); $message = 'Pending-event retry completed.';
    }
    set_transient( 'maum_admin_notice_' . get_current_user_id(), array( 'message' => $message, 'type' => $type ), 60 );
    wp_safe_redirect( admin_url( 'tools.php?page=maum-update-monitor' ) ); exit;
} );

function maum_render_admin_page(): void {
    if ( ! current_user_can( 'manage_options' ) ) return;
    $notice = get_transient( 'maum_admin_notice_' . get_current_user_id() );
    if ( $notice ) delete_transient( 'maum_admin_notice_' . get_current_user_id() );
    $c = maum_credentials(); $s = maum_status(); $queue = get_option( MAUM_QUEUE_OPTION, array() ); $queue_count = is_array( $queue ) ? count( $queue ) : 0;
    ?>
    <div class="wrap"><h1>Update Monitor</h1>
    <?php if ( is_array( $notice ) && ! empty( $notice['message'] ) ) : ?><div class="notice notice-<?php echo esc_attr( $notice['type'] ?? 'info' ); ?> is-dismissible"><p><?php echo esc_html( $notice['message'] ); ?></p></div><?php endif; ?>
    <?php if ( ! maum_is_registered() ) : ?>
        <div class="notice notice-warning"><p>This site is not yet registered with the central monitor.</p></div>
        <h2>Register this site</h2><p>Create a one-time registration code in the central monitor, then paste it here. The code is exchanged once for this site's unique permanent credentials.</p>
        <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
            <input type="hidden" name="action" value="maum_action"><input type="hidden" name="maum_do" value="register"><?php wp_nonce_field( 'maum_action' ); ?>
            <table class="form-table"><tr><th><label for="display_name">Display name</label></th><td><input class="regular-text" id="display_name" name="display_name" maxlength="120" value="<?php echo esc_attr( get_bloginfo( 'name' ) ); ?>" required><p class="description">Used prominently in Slack alerts. You can change it later on the central monitor.</p></td></tr>
            <tr><th><label for="registration_code">Registration code</label></th><td><input class="regular-text code" id="registration_code" name="registration_code" autocomplete="off" required></td></tr></table>
            <?php submit_button( 'Register Site' ); ?>
        </form>
        <p><strong>Registration endpoint:</strong> <code><?php echo esc_html( MAUM_REGISTER_ENDPOINT ); ?></code></p>
    <?php else : ?>
        <?php $registered_host = ! empty( $c['registered_site_url'] ) ? wp_parse_url( (string) $c['registered_site_url'], PHP_URL_HOST ) : ''; $current_host = wp_parse_url( home_url( '/' ), PHP_URL_HOST ); ?>
        <?php if ( $registered_host && $current_host && strtolower( (string) $registered_host ) !== strtolower( (string) $current_host ) ) : ?><div class="notice notice-warning"><p><strong>Site hostname changed.</strong> The central monitor may reject events until the new URL is approved there.</p></div><?php endif; ?>
        <table class="widefat striped" style="max-width:900px"><tbody>
        <tr><th>Monitor version</th><td><?php echo esc_html( MAUM_PLUGIN_VERSION ); ?></td></tr>
        <tr><th>Site ID</th><td><code><?php echo esc_html( $c['site_id'] ?? '' ); ?></code></td></tr>
        <tr><th>Display name</th><td><?php echo esc_html( $c['display_name'] ?? '' ); ?></td></tr>
        <tr><th>Queued events</th><td><?php echo (int) $queue_count; ?></td></tr>
        <tr><th>Last successful contact</th><td><?php echo esc_html( ( $s['last_success'] ?? 'Never' ) . ( ! empty( $s['last_success_detail'] ) ? ' — ' . $s['last_success_detail'] : '' ) ); ?></td></tr>
        <tr><th>Last error</th><td><?php echo esc_html( $s['last_error'] ?? 'None' ); ?></td></tr>
        <tr><th>Last automatic update run</th><td><?php echo esc_html( $s['last_update_run'] ?? 'Not recorded yet' ); ?></td></tr>
        </tbody></table>
        <h2>Tests & diagnostics</h2>
        <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" style="display:flex;gap:8px;flex-wrap:wrap">
            <input type="hidden" name="action" value="maum_action"><?php wp_nonce_field( 'maum_action' ); ?>
            <button class="button button-primary" name="maum_do" value="test">Send Test Event</button>
            <button class="button" name="maum_do" value="heartbeat">Send Heartbeat</button>
            <button class="button" name="maum_do" value="inventory">Send Inventory</button>
            <button class="button" name="maum_do" value="synthetic_failure">Send Synthetic Failure</button>
            <button class="button" name="maum_do" value="retry">Retry Pending Events</button>
        </form>
        <p class="description">Synthetic Failure does not modify any plugin or theme. It only tests the failure/Slack alert path.</p>
    <?php endif; ?></div><?php
}
