<?php
/**
 * File Path: includes/api/esp/class-mbs-esp-getresponse.php
 * GetResponse 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_GetResponse 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 = 'https://api.getresponse.com/v3/';
	private string $api_key;
	public function __construct( string $api_key ) { $this->api_key = $api_key; }
	public function connect(): bool {
		$r = $this->get( 'accounts' );
		return ! is_wp_error( $r ) && 200 === (int) wp_remote_retrieve_response_code( $r );
	}
	public function get_lists(): array {
		$r = $this->get( 'campaigns' );
		if ( is_wp_error( $r ) ) { return array(); }
		$b = json_decode( wp_remote_retrieve_body( $r ), true );
		if ( ! is_array( $b ) ) { return array(); }
		$out = array();
		foreach ( $b as $c ) { $out[] = array( 'id' => (string) $c['campaignId'], 'name' => (string) $c['name'] ); }
		return $out;
	}
	public function subscribe( string $email, string $name, string $list_id, bool $double_optin ): bool {
		$payload = array(
			'email'      => $email,
			'name'       => $name,
			'campaign'   => array( 'campaignId' => $list_id ),
			'dayOfCycle' => 0,
		);
		if ( $double_optin ) {
			// Force re-confirmation via tag (GetResponse sends confirmation on double-opt-in if campaign settings require it).
			// No separate flag needed -- it's per-campaign config in GetResponse dashboard.
		}
		$r = $this->post( 'contacts', $payload );
		if ( is_wp_error( $r ) ) { return false; }
		$code = (int) wp_remote_retrieve_response_code( $r );
		// 202 Accepted is the success code for GetResponse contact creation.
		return 202 === $code || ( $code >= 200 && $code < 300 );
	}
	public function tag_contact( string $email, array $tags, string $list_id ): bool {
		if ( empty( $tags ) ) { return true; }
		// Find contact.
		$sr = $this->get( 'contacts?query[email]=' . rawurlencode( $email ) . '&perPage=1' );
		if ( is_wp_error( $sr ) ) { return false; }
		$sb = json_decode( wp_remote_retrieve_body( $sr ), true );
		$contact_id = $sb[0]['contactId'] ?? '';
		if ( '' === $contact_id ) { return false; }
		$all_ok = true;
		foreach ( $tags as $tag ) {
			// Create tag.
			$tr = $this->post( 'tags', array( 'name' => (string) $tag ) );
			if ( is_wp_error( $tr ) ) { $all_ok = false; continue; }
			$tb = json_decode( wp_remote_retrieve_body( $tr ), true );
			$tag_id = $tb['tagId'] ?? '';
			if ( '' === $tag_id ) { $all_ok = false; continue; }
			// POST contact/{contactId}/tags.
			$ctr = $this->post( 'contacts/' . rawurlencode( $contact_id ) . '/tags', array( 'tagId' => $tag_id ) );
			if ( is_wp_error( $ctr ) ) { $all_ok = false; }
		}
		return $all_ok;
	}
	public function supports_tags(): bool { return true; }
	public function supports_campaigns(): bool { return true; }
	public function create_campaign( string $subject, string $body_html, string $list_id ): ?string {
		$from_field_id = $this->get_default_from_field_id();
		if ( '' === $from_field_id ) {
			trigger_error( 'MBS GetResponse: no from-field ID found — register a From Field in your GetResponse account.', E_USER_NOTICE ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- trigger_error() used for recoverable errors in plugin lifecycle; acceptable in non-production contexts and gated by MBS_DEV_MODE
			return null; // V6-B-013: bail rather than sending a request doomed to fail
		}
		$payload = array(
			'subject'     => $subject,
			'name'        => $subject,
			'fromField'   => array( 'fromFieldId' => $from_field_id ),
			'replyTo'     => array( 'fromFieldId' => $from_field_id ),
			'campaign'    => array( 'campaignId' => $list_id ),
			'content'     => array( 'html' => $body_html, 'plain' => wp_strip_all_tags( $body_html ) ),
			'type'        => 'broadcast',
		);
		$r = $this->post( 'newsletters', $payload, self::TIMEOUT_CAMPAIGN );
		if ( is_wp_error( $r ) ) { return null; }
		if ( (int) wp_remote_retrieve_response_code( $r ) < 200 || (int) wp_remote_retrieve_response_code( $r ) >= 300 ) { return null; }
		$b = json_decode( wp_remote_retrieve_body( $r ), true );
		return isset( $b['newsletterId'] ) ? (string) $b['newsletterId'] : null;
	}
	public function send_campaign( string $campaign_id ): bool {
		// GetResponse schedules newsletter via PUT /newsletters/{id}
		$r = $this->request( 'PUT', 'newsletters/' . rawurlencode( $campaign_id ), array( 'status' => 'enabled' ), self::TIMEOUT_CAMPAIGN );
		if ( is_wp_error( $r ) ) { return false; }
		$code = (int) wp_remote_retrieve_response_code( $r );
		return 200 === $code || ( $code >= 200 && $code < 300 );
	}
	/**
	 * Fetch the account's default From Field ID from the GetResponse API.
	 * Cached for 1 hour per site. V5-C-003 / V6-B-001.
	 *
	 * @return string From Field ID or empty string when unavailable.
	 */
	private function get_default_from_field_id(): string {
		$cache_key = 'mbs_esp_gr_from_field_' . get_current_blog_id();
		$cached    = get_transient( $cache_key );
		if ( false !== $cached ) {
			return (string) $cached;
		}
		$r = $this->get( 'from-fields' );
		if ( is_wp_error( $r ) || (int) wp_remote_retrieve_response_code( $r ) !== 200 ) {
			return '';
		}
		$body = json_decode( wp_remote_retrieve_body( $r ), true );
		$id   = ( is_array( $body ) && ! empty( $body[0]['fromFieldId'] ) )
			? (string) $body[0]['fromFieldId']
			: '';
		set_transient( $cache_key, $id, HOUR_IN_SECONDS );
		return $id;
	}
	protected function auth_headers(): array {
		return array( 'X-Auth-Token' => 'api-key ' . $this->api_key );
	}
}
