<?php
namespace Backreload\Notifiers;
if ( ! defined( 'ABSPATH' ) ) { exit; }

class WebhookNotifier extends AbstractNotifier {
	public static function type(): string        { return 'webhook'; }
	public static function label(): string       { return 'Custom Webhook'; }
	public static function description(): string { return 'POST JSON to any URL: pipe into your own system'; }

	public static function config_schema(): array {
		return [
			[ 'key' => 'url',    'label' => 'URL',                'type' => 'text',     'required' => true ],
			[ 'key' => 'secret', 'label' => 'Bearer token (optional)', 'type' => 'password', 'secret' => true,
			  'help' => 'If set, sent as Authorization: Bearer <token>' ],
			[ 'key' => 'method', 'label' => 'HTTP method',        'type' => 'select',
			  'options' => [ 'POST', 'PUT' ], 'default' => 'POST' ],
		];
	}

	public function validate( array $config ): array {
		$config = parent::validate( $config );
		$url    = $config['url'] ?? '';
		if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
			throw new NotifierValidationException( [ 'url' => 'Enter a valid http(s) URL' ] );
		}
		if ( ! preg_match( '#^https?://#i', $url ) ) {
			throw new NotifierValidationException( [ 'url' => 'URL must start with http:// or https://' ] );
		}
		// Block SSRF: refuse webhook targets pointing at the same host's loopback,
		// LAN, link-local, or cloud-metadata service. Hosts that legitimately need
		// a LAN webhook can flip the `backreload_allow_private_webhook` filter.
		self::assert_safe_remote_url( $url );
		return $config;
	}

	public function send( array $config, array $payload ): void {
		// Re-check at send time: DNS can rebind between save and delivery.
		self::assert_safe_at_send( (string) ( $config['url'] ?? '' ) );
		$headers = [ 'Content-Type' => 'application/json' ];
		if ( ! empty( $config['secret'] ) ) {
			$headers['Authorization'] = 'Bearer ' . $config['secret'];
		}

		$res = wp_remote_request( $config['url'], [
			'method'    => $config['method'] ?? 'POST',
			'timeout'   => 15,
			'sslverify' => true,
			'headers'   => $headers,
			'body'      => wp_json_encode( [
				'event'     => $payload['level'] === 'error' ? 'backup.failed' : 'backup.success',
				'title'     => $payload['title'],
				'message'   => $payload['message'],
				'level'     => $payload['level'],
				'backup'    => $payload['context'] ?? [],
				'timestamp' => gmdate( 'c' ),
			] ),
		] );
		if ( is_wp_error( $res ) ) {
			throw new \RuntimeException(  esc_html( $res->get_error_message() )  );
		}
		$code = wp_remote_retrieve_response_code( $res );
		if ( $code >= 400 ) {
			throw new \RuntimeException(  esc_html( 'HTTP ' . $code . ': ' . self::short_response_body( $res ) )  );
		}
	}
}
