<?php
/**
 * File Path: includes/api/esp/class-mbs-esp-sendy.php
 * Sendy ESP Adapter -- My Book Showroom
 * Sprint F-026: Email Channel Integration.
 * @package My_Book_Showroom
 * @since   1.1.0
 */
if ( ! defined( 'ABSPATH' ) ) { exit; }

class MBS_ESP_Sendy extends MBS_ESP_Adapter_Base { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix
	protected const BASE_URL = '';
	private string $api_key;
	private string $account_url;
	public function __construct( string $api_key, string $account_url = '' ) {
		$this->api_key = $api_key;
		// SA-H4: Validate account_url before storing — prevents SSRF via admin-supplied URL.
		$trimmed_url = rtrim( $account_url, '/' );
		if ( '' !== $trimmed_url && ( ! wp_http_validate_url( $trimmed_url ) || ! in_array( wp_parse_url( $trimmed_url, PHP_URL_SCHEME ), array( 'https', 'http' ), true ) ) ) {
			$trimmed_url = ''; // Reject non-HTTP(S) or structurally invalid URLs.
		}
		$this->account_url = $trimmed_url;
	}
	// Sendy: connect() pings the subscribe endpoint with a sentinel email to test real connectivity.
	public function connect(): bool {
		$api_key     = $this->api_key;
		$account_url = $this->account_url;
		if ( empty( $api_key ) || empty( $account_url ) ) {
			return false;
		}
		// Ping Sendy with an invalid email to test connectivity.
		$response = wp_safe_remote_post(
			trailingslashit( $account_url ) . 'subscribe',
			array(
				'timeout' => 5,
				'body'    => array(
					'api_key' => $api_key,
					'name'    => 'Test',
					'email'   => 'mbs_connection_test_invalid@localhost.invalid',
					'list'    => 'test',
					'boolean' => 'true',
				),
			)
		);
		if ( is_wp_error( $response ) ) {
			return false;
		}
		// Sendy returns "Some fields are missing." for bad list -- but connectivity is proven.
		$code = wp_remote_retrieve_response_code( $response );
		return $code >= 200 && $code < 500;
	}
	// Sendy has no list-listing API -- callers must supply a list ID manually.
	public function get_lists(): array { return array(); }
	public function subscribe( string $email, string $name, string $list_id, bool $double_optin ): bool {
		$url = $this->account_url . '/subscribe';
		$payload = array(
			'api_key' => $this->api_key,
			'list'    => $list_id,
			'email'   => $email,
			'name'    => $name,
			'boolean' => $double_optin ? 'true' : 'false',
		);
		$r = wp_safe_remote_post( $url, array( 'body' => $payload, 'timeout' => self::TIMEOUT_CONNECT, 'sslverify' => true ) );
		if ( is_wp_error( $r ) ) { return false; }
		// Sendy returns '1' on success.
		$body = wp_remote_retrieve_body( $r );
		return '1' === trim( $body ) || 'true' === strtolower( trim( $body ) );
	}
	// Sendy does not support tags -- documented no-op.
	public function tag_contact( string $email, array $tags, string $list_id ): bool { return true; }
	public function supports_tags(): bool { return false; }
	// Sendy does not support campaign creation via API -- documented no-op.
	public function create_campaign( string $subject, string $body_html, string $list_id ): ?string { return null; }
	public function send_campaign( string $campaign_id ): bool { return false; }
	public function supports_campaigns(): bool { return false; }
	protected function auth_headers(): array { return array(); }
}
