<?php
/**
 * BaseCloud Boost — Webhook Sender
 *
 * Posts a JSON performance-metrics payload to a user-configured webhook URL.
 * Supports optional HMAC-SHA256 signing via a shared secret.
 *
 * Payload shape (all numeric fields are integers/floats):
 * {
 *   "event":             "BCBOOST_metrics",
 *   "plugin_version":    "1.0.0",
 *   "site_url":          "https://example.com",
 *   "site_name":         "My Site",
 *   "timestamp":         "2026-03-19T10:00:00+00:00",
 *   "cache_hit_rate":    95.6,
 *   "cache_hits":        1234,
 *   "cache_misses":      56,
 *   "pages_cached":      89,
 *   "cache_size_bytes":  12345678,
 *   "html_bytes_saved":  234567,
 *   "css_bytes_saved":   123456,
 *   "js_bytes_saved":    98765,
 *   "total_bytes_saved": 456788,
 *   "last_purge":        "2026-03-18T09:00:00+00:00",
 *   "webhook_errors":    0
 * }
 *
 * @package BaseCloud\Boost\Core
 */

declare( strict_types=1 );

namespace BaseCloud\Boost\Core;

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

/**
 * Sends performance-metrics payloads to a webhook URL.
 */
class Webhook_Sender {

	/** @var Metrics_Collector */
	private Metrics_Collector $metrics;

	/** @var Page_Cache */
	private Page_Cache $page_cache;

	public function __construct() {
		$this->metrics    = new Metrics_Collector();
		$this->page_cache = new Page_Cache();
	}

	/**
	 * Send metrics to the configured (or supplied) webhook URL.
	 *
	 * @param string|null $url Override the stored URL (for test sends).
	 * @return array{ success: bool, message: string, payload?: array }
	 */
	public function send( ?string $url = null ): array {
		$url = $url ?? (string) BCBOOST_get_option( 'webhook_url', '' );
		$url = trim( $url );

		if ( empty( $url ) ) {
			return [ 'success' => false, 'message' => __( 'No webhook URL configured.', 'basecloud-boost' ) ];
		}

		if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
			return [ 'success' => false, 'message' => __( 'Invalid webhook URL.', 'basecloud-boost' ) ];
		}

		$payload = $this->build_payload();
		$body    = (string) wp_json_encode( $payload );

		$headers = [
			'Content-Type' => 'application/json',
			'User-Agent'   => 'BaseCloud-Boost/' . BCBOOST_VERSION,
			'X-BCBoost-Event'  => 'metrics',
		];

		// Optional HMAC-SHA256 signature.
		$secret = trim( (string) BCBOOST_get_option( 'webhook_secret', '' ) );
		if ( $secret !== '' ) {
			$headers['X-BCBoost-Signature'] = 'sha256=' . hash_hmac( 'sha256', $body, $secret );
		}

		$response = wp_remote_post( $url, [
			'timeout'     => 10,
			'redirection' => 3,
			'headers'     => $headers,
			'body'        => $body,
		] );

		if ( is_wp_error( $response ) ) {
			$this->metrics->increment( 'webhook_errors' );
			return [
				'success' => false,
				'message' => $response->get_error_message(),
			];
		}

		$code    = (int) wp_remote_retrieve_response_code( $response );
		$success = $code >= 200 && $code < 300;

		if ( $success ) {
			$this->metrics->set( 'last_webhook_sent', time() );
		} else {
			$this->metrics->increment( 'webhook_errors' );
		}

		return [
			'success' => $success,
			/* translators: HTTP status code */
			'message' => $success
				? sprintf( __( 'Metrics sent successfully (HTTP %d).', 'basecloud-boost' ), $code )
				: sprintf( __( 'Webhook failed — server returned HTTP %d.', 'basecloud-boost' ), $code ),
			'payload' => $payload,
		];
	}

	/**
	 * Build the full metrics payload array.
	 *
	 * @return array<string, mixed>
	 */
	public function build_payload(): array {
		$stats       = $this->metrics->get_all();
		$cache_stats = $this->page_cache->get_cache_stats();
		$hit_rate    = $this->metrics->get_hit_rate();
		$last_purge  = $stats['last_purge'] ? gmdate( 'c', (int) $stats['last_purge'] ) : null;

		return [
			'event'             => 'BCBOOST_metrics',
			'plugin_version'    => BCBOOST_VERSION,
			'site_url'          => get_site_url(),
			'site_name'         => get_bloginfo( 'name' ),
			'timestamp'         => gmdate( 'c' ),
			'cache_hit_rate'    => $hit_rate,
			'cache_hits'        => (int) $stats['hits'],
			'cache_misses'      => (int) $stats['misses'],
			'pages_cached'      => (int) $cache_stats['count'],
			'cache_size_bytes'  => (int) $cache_stats['size'],
			'html_bytes_saved'  => (int) $stats['html_saved'],
			'css_bytes_saved'   => (int) $stats['css_saved'],
			'js_bytes_saved'    => (int) $stats['js_saved'],
			'total_bytes_saved' => (int) $stats['html_saved'] + (int) $stats['css_saved'] + (int) $stats['js_saved'],
			'last_purge'        => $last_purge,
			'webhook_errors'    => (int) $stats['webhook_errors'],
		];
	}
}
